chore(marmel): bump to b08923ea (main), drop obsolete patches
CI / check (push) Has been cancelled

Upstream fixed both reasons for the local patches, so neither is needed:

- 62cb75634c6e (#16) reports a missing TLS trust store instead of
  panicking through reqwest::Client::default(); the env-cleared test
  child now stays reachable without SSL_CERT_FILE, which is what
  session-boot-trust-store.patch existed to work around.
- b08923eaef60 (#17) adds /nix/store and /gnu/store to
  BUILTIN_READONLY_PATHS; the checkPhase rebuild confirms the store rule
  works on a Nix host: test_internal_sandbox_cross_directory_rename and
  test_internal_sandbox_extra_readonly_paths_never_grant_write run for
  real, no SKIP line is printed, and only the /etc/resolv.conf DNS test
  stays filtered. Lib suite: 1055 passed, 1 filtered; all integration
  suites green.

passthru.updateScript now passes the bare attribute name: nix-update
rejects ".#marmel" with AttributePathError, so the documented bump path
was broken. Verify with `nix-update --flake marmel --use-update-script`.
This commit is contained in:
2026-10-19 09:52:45 +03:00
parent f12ce65f34
commit adbed5f3c0
3 changed files with 29 additions and 96 deletions
-29
View File
@@ -1,29 +0,0 @@
--- a/src/harness/sandbox.rs
+++ b/src/harness/sandbox.rs
@@ -414,8 +414,25 @@
}
// 5. System toolchains, device nodes, runtime files (DNS /run/systemd/resolve), and binaries (Read-Only + Execute)
+ //
+ // On NixOS and Guix /bin, /usr/bin and /lib are symlink farms: every executable
+ // resolves below the package store, and Landlock matches the resolved target rather
+ // than the symlinked view, so the store has to be listed here or nothing can be exec'd
+ // at all. Store paths are world-readable by design, so read+execute there adds no
+ // reach that a local user does not already have.
let ro_paths = [
- "/usr", "/bin", "/lib", "/lib64", "/opt", "/etc", "/dev", "/proc", "/sys", "/run", "/var",
+ "/usr",
+ "/bin",
+ "/lib",
+ "/lib64",
+ "/opt",
+ "/etc",
+ "/dev",
+ "/proc",
+ "/sys",
+ "/run",
+ "/var",
+ "/nix/store",
];
for p in ro_paths {
if Path::new(p).exists()
+29 -24
View File
@@ -11,35 +11,33 @@ rustPlatform.buildRustPackage rec {
# says 1.0.0, so the version is meaningless and the source is tracked by
# branch head, dated by nix-update's 0-unstable-* scheme. Bump with
# nix-update (see passthru.updateScript).
version = "0-unstable-2026-10-17";
version = "0-unstable-2026-10-19";
src = fetchFromGitHub {
owner = "Na1w";
repo = "marmel";
rev = "981b35b0d356e56de429ab4198e427ccfbe7d85f";
hash = "sha256-Z72o5LsjwTIk1EsiTYfNO+WIFzOSOEmCzzfyJKksYF4=";
rev = "b08923eaef6057410140d80f5dad37b6b511c5af";
hash = "sha256-GkGjhsVCWNqaa6a5kwSSgiI69ZabkFLPWmnI9RfWXuQ=";
};
cargoHash = "sha256-etqW3xcxkiNfkiPxl/Emt5pQCkNnoIhHFkX0Zqfs4rc=";
nativeCheckInputs = [ cacert ];
patches = [
./session-boot-trust-store.patch
# Temporary downstream fix, upstream has no NixOS-aware allow-list yet.
# Adds "/nix/store" to the read-only+execute list of the Landlock ruleset, so the
# sandbox re-entry can exec `sh` on a Nix host at all. Drop when upstream lands it
# (nix-overlay-5ml).
./landlock-nix-store.patch
];
# Both downstream patches are gone as of b08923eaef60 ("Landlock improvements",
# Na1w/marmel#17) and 62cb75634c6e ("report missing TLS trust store instead of
# panicking", #16): upstream now lists /nix/store and /gnu/store in
# BUILTIN_READONLY_PATHS, and the HTTP client reports a missing trust store
# instead of panicking through reqwest::Client::default().
# The test suite builds `reqwest::Client`s, and rustls rejects construction
# outright when no system trust store is found ("No CA certificates were
# loaded from the system"). rustls-native-certs probes only SSL_CERT_FILE,
# SSL_CERT_DIR and a fixed list of /etc dirs (/etc/ssl, /etc/pki/tls, ...),
# none of which exist in the build sandbox, so point the tests at nixpkgs'
# bundle. Build-time only; the installed binary still uses the host's trust
# store at runtime.
# The test suite exercises real HTTP round-trips against loopback servers and
# builds its `reqwest::Client`s through rustls-native-certs, which probes only
# SSL_CERT_FILE, SSL_CERT_DIR and a fixed list of /etc dirs (/etc/ssl,
# /etc/pki/tls, ...), none of which exist in the build sandbox. Without a CA
# bundle the client build fails ("No CA certificates were loaded from the
# system") and every request fails terminally with ChatError::TrustStore, so
# point the tests at nixpkgs' bundle. Build-time only; the installed binary
# still uses the host's trust store at runtime.
preCheck = ''
export SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt
'';
@@ -52,12 +50,15 @@ rustPlatform.buildRustPackage rec {
# then 1 failure, then 0 with serial threads. Drop this flag once upstream
# makes that state per-instance.
#
# Only the DNS sandbox-exec test is skipped now. It re-execs `sh` through
# Only the DNS sandbox-exec test is skipped. It re-execs `sh` through
# `marmel --internal-sandbox-exec` and then reads /etc/resolv.conf, which the
# no-network build sandbox does not provide. landlock-nix-store.patch fixed the
# exec half for both sandbox-exec tests: with it, the cross-directory rename
# test runs for real (no SKIP printed by `integration_host`) and the lib suite
# passes at 1030 tests with that single filter.
# no-network build sandbox does not provide (upstream's own decision note in
# src/harness/sandbox.rs says the same: the exec half works on a store host,
# the resolv.conf half is a fixture question). Upstream now lists
# /nix/store and /gnu/store in BUILTIN_READONLY_PATHS, so the cross-directory
# rename test and test_internal_sandbox_extra_readonly_paths_never_grant_write
# run for real here: no SKIP line is printed and the lib suite passes at 1055
# tests with that single filter.
cargoTestFlags = [
"--"
"--test-threads=1"
@@ -75,10 +76,14 @@ rustPlatform.buildRustPackage rec {
passthru = {
category = "AI Coding Agents";
# nix-update rejects a leading dot in the attribute path (".#marmel" →
# AttributePathError), so the bare attribute name is what the bare
# `nix-update --flake` invocation takes. Verify with
# `nix-update --flake marmel --use-update-script`.
updateScript = [
"nix-update"
"--flake"
".#marmel"
"marmel"
"--version=branch=main"
];
};
@@ -1,43 +0,0 @@
Give the env-cleared child process a trust store.
run_marmel() wipes the child environment so the binary under test cannot
inherit the runner's MARMEL_* variables or its terminal. reqwest's TLS stack
is rustls-native-certs, which reads SSL_CERT_FILE / SSL_CERT_DIR and then the
well-known /etc paths, so where no system trust store exists at all the child
dies inside reqwest::Client::new() ("No CA certificates were loaded from the
system") before it ever reads the bundle. Four cases in this file assert the
CLI's exit codes and stderr, and they then observe the panic's 101 instead.
Forward the test runner's SSL_CERT_FILE when it has one. On a normal Linux
host the child picks the trust store up from /etc as before, so the assertions
themselves are unchanged.
This is a workaround, not the real fix. The panic should not happen at all:
src/llm/client.rs builds the client with unwrap_or_default() on a
Result<Client, reqwest::Error>, and reqwest's Client::default() is
Client::new(), which repeats the same build and .expect()s it, so the fallback
can never recover. Upstream was told; drop this patch once the error is
propagated instead of discarded.
--- a/tests/test_session_boot.rs
+++ b/tests/test_session_boot.rs
@@ -221,8 +221,17 @@
let err_file = std::fs::File::create(&err_path).expect("stderr file");
let mut cmd = Command::new(env!("CARGO_BIN_EXE_marmel"));
- cmd.current_dir(dir)
- .env_clear()
+ cmd.current_dir(dir).env_clear();
+ // rustls-native-certs reads SSL_CERT_FILE / SSL_CERT_DIR, both of which the
+ // env_clear() above drops, so when no system trust store can be probed
+ // either the child dies inside reqwest::Client::new() ("No CA certificates
+ // were loaded from the system") before it ever reaches the bundle, and the
+ // exit-code assertions below then see the panic's 101. Forward the runner's
+ // value when it has one; the assertions themselves are untouched.
+ if let Some(trust_store) = std::env::var("SSL_CERT_FILE").ok().filter(|p| !p.is_empty()) {
+ cmd.env("SSL_CERT_FILE", trust_store);
+ }
+ cmd
// A minimal, deterministic environment: the binary must not inherit the
// test runner's `MARMEL_*` variables or its terminal.
.env("PATH", "/usr/bin:/bin")