The upstream ruleset allow-lists FHS paths only (/usr, /bin, /lib, /opt,
/etc, /var), and every executable here resolves below the store: /bin/sh
is a symlink into /nix/store/<hash>-bash-5.3p9/bin/sh. Landlock matches
the resolved target rather than the symlinked view, so the harness
re-entry (`marmel --internal-sandbox-exec`) cannot exec the shell and
every shell tool call comes back as "Failed to exec shell in sandbox:
Permission denied (os error 13)" with exit 1. The sandbox is on by
default, so the only workaround on a Nix host is MARMEL_DISABLE_SANDBOX=1,
which drops the protection altogether.
The patch adds "/nix/store" to the read-only+execute list, guarded by
exists() like its neighbours. Store paths are world-readable by design,
so the added reach is nothing a local user did not already have. Checked
against the built binary: sandboxed exec works, git runs, workspace
writes work, ~/.ssh and /root stay blocked.
Tested: nix build .#marmel passes, lib suite 966 passed / 0 failed with
one filter. test_internal_sandbox_cross_directory_rename no longer needs
a skip and passes; test_internal_sandbox_exec_dev_null_and_dns stays
skipped for its own reason, the no-network build sandbox has no
/etc/resolv.conf. Temporary downstream fix, drop it once upstream takes
the store path (nix-overlay-5ml).
Track main at 3f238ff (per-role reasoning_effort, #12), 21 commits past
d6627d7 ("1.0.0 (#6)"). cargoHash is unchanged: Cargo.lock is identical
across that range, so the vendored tree is byte-for-byte the same.
The new tests/test_session_boot.rs spawns the real binary with
env_clear(), which drops SSL_CERT_FILE. rustls-native-certs is then left
with a fixed list of /etc paths to probe, none of which exist in the Nix
sandbox, so the child dies in reqwest::Client::new() and four exit-code
assertions observe the panic's 101. The patch forwards the runner's
SSL_CERT_FILE to the child and leaves every assertion intact.
The underlying defect is upstream's rather than Nix's:
src/llm/client.rs builds its 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. The
fallback can therefore never recover; it turns a reportable "no CA
certificates" error into a panic. Reproduced on a stock busybox image
with no /etc/ssl at all, so it hits any minimal container, not just
sandboxed builds.
Tested: 1251 tests pass across 31 targets, 0 failures.
The lib suite failed in the Nix sandbox:
harness::sandbox::tests::test_internal_sandbox_exec_dev_null_and_dns
harness::sandbox::tests::test_internal_sandbox_cross_directory_rename
Failed to exec shell in sandbox: Permission denied (os error 13)
apply_landlock_linux() allow-lists FHS paths only, and Landlock matches
inodes rather than symlinked views, so nothing under /nix/store can be
executed once the ruleset is applied; /bin/sh here is a store path. The
build sandbox also drops the /usr, /lib, /run and /var rules, since those
paths do not exist there, and has no /etc/resolv.conf without network, so
neither test can pass however the package is written. 342 of 344 tests run,
all green.
The same denial applies at runtime: every shell tool call goes through
marmel --internal-sandbox-exec and fails on NixOS. Tracked as
nix-overlay-5ml. Upstream main still carries the FHS-only list.
Refresh every package pin so the overlay stops carrying versions upstream
has moved past, and repair the pins where an automated bump had produced a
version that no longer resolves:
- graphify 0.9.61 -> 1.0.0 and back to tag tracking: the branch-tracking
update script generated v0.9.77-unstable-<date> for a rev = "v${version}"
src, a tag that never existed
- radar 1.13.1 -> 1.16.2 (upstream retagged its releases as k8s-ui-v*)
- llama-cpp b9645 -> b11439
- hipengine 0.5.0 -> 0.6.1, traycer 1.3.0 -> 1.4.2, freetoken 0.1.2 -> 0.1.3
- awg-tool 0.4.0, freebuff 0.2.19, kubernetes-mcp-server 0.0.67,
marmel 0-unstable-2026-10-05, open-code-review 1.12.12,
ds4 0-unstable-2026-09-20
- version-string normalisation for the branch-tracked packages already at
their newest commit (g3, haivemind, shardr, skillsmcp)
Every changed src hash was re-fetched and verified. omniroute stays at
3.8.50: 3.8.51 changes its npm lockfile, so its npmDepsHash would have to
be recomputed before the bump is usable.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
Pin Na1w/marmel to commit fd551ae. Upstream publishes no tags or
releases, so the version uses the shape nix-update generates for a
tagless repository, keeping `nix-update --version=branch=main` usable.
The test suite runs green (325 lib tests plus all integration suites)
with two accommodations, both documented in the derivation:
- Export SSL_CERT_FILE from nixpkgs cacert. rustls refuses to construct
a reqwest::Client without a system trust store, which failed 38 tests
with "No CA certificates were loaded from the system".
- Serialise the test harness. The lib suite shares process-global worker
registries and steer/abort buses, so manager-loop tests fail
nondeterministically on parallel threads: one unchanged derivation
produced 3 failures, then 1 failure, then 0 with --test-threads=1.
No test is skipped or filtered.
Annotated example configs are installed to share/doc/marmel/examples/.
Role prompts are embedded via include_str!, so there is no runtime data
directory. Upstream README states MIT but ships no LICENSE file and no
Cargo.toml license field.