fix: NANOCLAW_* flags set in .env never reach process.env under launchd/systemd#2730
Open
sturdy4days wants to merge 1 commit into
Open
fix: NANOCLAW_* flags set in .env never reach process.env under launchd/systemd#2730sturdy4days wants to merge 1 commit into
sturdy4days wants to merge 1 commit into
Conversation
…hd/systemd Several modules read operational flags straight from process.env — e.g. egress-lockdown.ts gates on process.env.NANOCLAW_EGRESS_LOCKDOWN at module evaluation, and docs/SECURITY.md tells users to "set NANOCLAW_EGRESS_LOCKDOWN=true". But nothing loads .env into the process environment: readEnvFile deliberately returns values without exporting them (so secrets stay out of child-process envs), and services started by launchd/systemd get no shell environment. The result is that putting the flag in .env — the place every other setting lives — silently does nothing: the host spawns agents on the default bridge network while the operator believes lockdown is on. Fail-open, and invisible until audited. Fix: promoteEnvFlags() in env.ts copies NANOCLAW_-prefixed entries (flags and tuning knobs by convention, never credentials) from .env into process.env, with real environment values taking precedence. Called at the top of config.ts, which the import graph evaluates before any flag reader. No-op under vitest so a developer's live .env can't steer tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jun 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug
Several modules read operational flags straight from
process.env— most notablyegress-lockdown.ts, which gates onprocess.env.NANOCLAW_EGRESS_LOCKDOWNin a top-level const, and whose docs (docs/SECURITY.md) tell users to "setNANOCLAW_EGRESS_LOCKDOWN=true". But nothing loads.envinto the process environment:readEnvFiledeliberately returns values without exporting them (so secrets stay out of child-process envs), and services started by launchd/systemd get no shell environment.The result: putting the flag in
.env— the place every other setting lives — silently does nothing. The host spawns agents on the default bridge network while the operator believes lockdown is on. Fail-open, and invisible until you auditdocker inspectoutput. Found this live: lockdown was "enabled" for days with zero effect.Related symptom family: #1934, #2134 (flags behaving differently under the service manager vs
pnpm run devfrom a shell, where exported vars happen to exist).Fix
promoteEnvFlags()insrc/env.ts: copiesNANOCLAW_-prefixed entries from.envintoprocess.env.NANOCLAW_prefix only — by convention those are feature flags and tuning knobs, never credentials. Secrets keep going throughreadEnvFileand stay out of child-process environments (the existing design, unchanged)..envnever overrides a var the service manager set explicitly.src/config.ts, which the import graph evaluates before any flag reader (verified: every importer ofegress-lockdown.ts—container-runner.ts,host-sweep.ts— importsconfig.jsfirst, as doesindex.ts).VITEST, so a developer's live-install.envcan't steer test behavior.Testing
src/env.test.ts: 5 tests (promotion, comment/prefix filtering, no-override precedence, quote stripping, missing-file no-op, VITEST guard) — all passtsccleanvitestsuite: failure set byte-identical to stockmainin the same environment (the pre-existing failures are unrelated to this change); the new test file passesNANOCLAW_EGRESS_LOCKDOWN=truein.envtakes effect on service start🤖 Generated with Claude Code