Engine/tooling housekeeping (4): delete stale dist/soul-with-nlg.el · SOUL_PORT no-op can bind the LIVE port · stale .elh headers · CORRECTED ps/API-key claim (env readable, argv clean) #113

Open
opened 2026-08-06 03:31:13 +00:00 by tim.lingo · 0 comments
Member

Filed by Neuron (Tim's instance) 2026-08-05. Four small engine/tooling items found while working the beta rounds. None is beta-blocking; all four are cheap and two are footguns that will cost someone an afternoon. Measured, with one claim corrected against its original report — see item 4.


1. dist/soul-with-nlg.el is a stale bundle that still wires the ungated handle_chat

neuron/dist/soul-with-nlg.el — 1,019,490 bytes, mtime Jun 25 17:31. Grep counts:

symbol hits
handle_chat 6 (including live call sites at lines 22976 and 23562)
layered_cycle 0
layered_generate 0
plain_chat_envelope 0

It predates the safety-layer rewiring entirely and routes chat through the handler that chat.el:1133-1138 now annotates "UNWIRED. DO NOT ROUTE /api/chat HERE [...] it has NO enforcing input gate and NO enforcing output gate." Anything built from this file gets chat with no safety gates.

Partly handled already: PR #109 adds a 15-line do-not-build banner to it — "Nothing in the repo references this file. It is kept only as a historical artifact and should be deleted once Will confirms nothing external depends on it."

Ask: confirm nothing external depends on it, then delete it. A banner is a comment; a deleted file cannot be built by mistake.


2. SOUL_PORT is a no-op — a sandbox build can bind the LIVE port

The engine reads NEURON_PORT and nothing else (neuron/soul.el:504-505):

let port_raw: String = env("NEURON_PORT")
let port: Int = if str_eq(port_raw, "") { 7770 } else { str_to_int(port_raw) }

SOUL_PORT has zero hits across every .el and .elh in the tree. But ~/neuron_soul_smokebuild.sh:23 sets it as if it were the knob:

HOME="$WORK/home" SOUL_PORT="$PORT" SOUL_ENGRAM_PATH="$WORK/data/snapshot.json" \

So the "sandbox" soul falls through to the default and binds 7770 — the live port — on any machine where 7770 happens to be free. The script's own log line ("sandbox boot on :$PORT", line 21) reports a port it is not using. That is a smoke test that can silently take over the real brain's socket.

The shipped launcher gets this right (neuron-daemons.sh:243: NEURON_PORT="$SOUL_PORT"), which is exactly why the inconsistency is dangerous — the same variable name means different things in different scripts.

Note: neuron_soul_smokebuild.sh lives on Tim's machine, not in the repo. Filing it here because (a) the underlying cause is engine-side — SOUL_PORT is a name the engine has never honored — and (b) if the same pattern exists in any of your dev scripts, it has the same failure mode. This is the same family as neuron#112 (launcher exports SOUL_LLM_BASE_URL, engine reads NEURON_LLM_0_URL): the tooling and the engine have drifted apart on env var names, and nothing detects it. A boot-time log of every env var the engine actually consulted, with its resolved value, would retire the whole class.


3. Committed .elh headers are stale against their .el sources

Committed dates skew by weeks:

module .el last commit .elh last commit
chat 2026-07-17 2026-07-13
routes 2026-07-13 2026-06-28
soul 2026-06-29 2026-06-17
awareness 2026-07-13 2026-07-13

Regenerating them produces diffs against what is committed — 12 files, +26/−11. Honest sizing: most of that is cosmetic. The single largest change is the auto-generated banner flipping an em dash to a hyphen (// auto-generated by elc --emit-header — do not edit- do not edit), which is an elc version difference, not drift. The substantive part is a handful of missing extern fn declarations for functions added to the .el sources since the headers were last regenerated (chat.elh +7/−1, safety.elh +6/−1, sessions.elh +5/−1, soul.elh +2).

Low severity — recorded so it is a known state rather than a surprise mid-debug. Ask: regenerate as part of the same pass that regenerates dist/soul.c (neuron#111, neuron-ui#209), so header and amalgamation never disagree about what exists.


4. CORRECTED: the launcher does not leak the API key into ps argv — but the environment is readable same-uid

This was reported to me as "soul-launch.sh leaks the API key into ps." I tested it and it does not reproduce as stated. Recording the correction so nobody goes looking for a leak that is not there.

~/neuron-dev-stack/bin/soul-launch.sh:10-12 uses the exec env VAR=value … binary pattern (the shipped neuron-daemons.sh:287-299 uses the same one). The intuition is that those assignments land in the process's argv. They do notenv consumes them and execs the target, so the assignments never reach the target's argument vector. Measured against the live soul:

$ ps -ww -o command= -p 95688
/Users/timlingo/neuron-dev-stack/bin/soul

Clean. Zero API_KEY occurrences.

What is real, and smaller: the key lives in the daemon's environment for the life of the process, and on macOS ps -E exposes a process's environment to any process running as the same user. Measured (names only, values withheld):

$ ps -Eww -o command= -p 95688 | grep -oE "^[A-Z_]+API_KEY="
ANTHROPIC_API_KEY=
ENGRAM_API_KEY=
SOUL_API_KEY=

So the accurate statement is: any process running as the user can read the customer's provider API key out of the brain's environment. Not cross-user, not over the network — but it does mean any userspace app on the machine can lift the key without touching the Keychain, which is the thing the Keychain storage was protecting against.

Worth a decision rather than a fix-by-reflex: passing the key on stdin at startup, or having the brain read it from the Keychain itself, both close it. Given that neuron#110 currently lets the network write memory unauthenticated, this one is the lesser concern — but it is on the same surface and worth handling in the same pass.


Cross-refs: neuron#110 (P0 network exposure), neuron#111 (dist/soul.c regen), neuron#112 (env var name drift, same root class as item 2), neuron#109 (adds the item-1 banner), neuron-ui#209 (regen automation).

**Filed by Neuron (Tim's instance) 2026-08-05.** Four small engine/tooling items found while working the beta rounds. None is beta-blocking; all four are cheap and two are footguns that will cost someone an afternoon. Measured, with one claim **corrected** against its original report — see item 4. --- ## 1. `dist/soul-with-nlg.el` is a stale bundle that still wires the ungated `handle_chat` `neuron/dist/soul-with-nlg.el` — 1,019,490 bytes, mtime **Jun 25 17:31**. Grep counts: | symbol | hits | |---|---| | `handle_chat` | **6** (including live call sites at lines 22976 and 23562) | | `layered_cycle` | **0** | | `layered_generate` | **0** | | `plain_chat_envelope` | **0** | It predates the safety-layer rewiring entirely and routes chat through the handler that `chat.el:1133-1138` now annotates *"UNWIRED. DO NOT ROUTE /api/chat HERE [...] it has NO enforcing input gate and NO enforcing output gate."* Anything built from this file gets chat with no safety gates. **Partly handled already:** PR #109 adds a 15-line do-not-build banner to it — *"Nothing in the repo references this file. It is kept only as a historical artifact and should be deleted once Will confirms nothing external depends on it."* **Ask:** confirm nothing external depends on it, then delete it. A banner is a comment; a deleted file cannot be built by mistake. --- ## 2. `SOUL_PORT` is a no-op — a sandbox build can bind the LIVE port The engine reads `NEURON_PORT` and nothing else (`neuron/soul.el:504-505`): ``` let port_raw: String = env("NEURON_PORT") let port: Int = if str_eq(port_raw, "") { 7770 } else { str_to_int(port_raw) } ``` `SOUL_PORT` has **zero** hits across every `.el` and `.elh` in the tree. But `~/neuron_soul_smokebuild.sh:23` sets it as if it were the knob: ``` HOME="$WORK/home" SOUL_PORT="$PORT" SOUL_ENGRAM_PATH="$WORK/data/snapshot.json" \ ``` So the "sandbox" soul falls through to the default and **binds 7770** — the live port — on any machine where 7770 happens to be free. The script's own log line ("sandbox boot on :$PORT", line 21) reports a port it is not using. That is a smoke test that can silently take over the real brain's socket. The shipped launcher gets this right (`neuron-daemons.sh:243`: `NEURON_PORT="$SOUL_PORT"`), which is exactly why the inconsistency is dangerous — the same variable name means different things in different scripts. **Note:** `neuron_soul_smokebuild.sh` lives on Tim's machine, not in the repo. Filing it here because (a) the underlying cause is engine-side — `SOUL_PORT` is a name the engine has never honored — and (b) if the same pattern exists in any of your dev scripts, it has the same failure mode. This is the same family as neuron#112 (launcher exports `SOUL_LLM_BASE_URL`, engine reads `NEURON_LLM_0_URL`): **the tooling and the engine have drifted apart on env var names, and nothing detects it.** A boot-time log of every env var the engine actually consulted, with its resolved value, would retire the whole class. --- ## 3. Committed `.elh` headers are stale against their `.el` sources Committed dates skew by weeks: | module | `.el` last commit | `.elh` last commit | |---|---|---| | `chat` | 2026-07-17 | 2026-07-13 | | `routes` | 2026-07-13 | 2026-06-28 | | `soul` | 2026-06-29 | 2026-06-17 | | `awareness` | 2026-07-13 | 2026-07-13 | Regenerating them produces diffs against what is committed — 12 files, +26/−11. **Honest sizing: most of that is cosmetic.** The single largest change is the auto-generated banner flipping an em dash to a hyphen (`// auto-generated by elc --emit-header — do not edit` → `- do not edit`), which is an `elc` version difference, not drift. The substantive part is a handful of missing `extern fn` declarations for functions added to the `.el` sources since the headers were last regenerated (`chat.elh` +7/−1, `safety.elh` +6/−1, `sessions.elh` +5/−1, `soul.elh` +2). Low severity — recorded so it is a known state rather than a surprise mid-debug. **Ask:** regenerate as part of the same pass that regenerates `dist/soul.c` (neuron#111, neuron-ui#209), so header and amalgamation never disagree about what exists. --- ## 4. CORRECTED: the launcher does **not** leak the API key into `ps` argv — but the environment is readable same-uid This was reported to me as *"`soul-launch.sh` leaks the API key into `ps`."* **I tested it and it does not reproduce as stated.** Recording the correction so nobody goes looking for a leak that is not there. `~/neuron-dev-stack/bin/soul-launch.sh:10-12` uses the `exec env VAR=value … binary` pattern (the shipped `neuron-daemons.sh:287-299` uses the same one). The intuition is that those assignments land in the process's argv. **They do not** — `env` consumes them and execs the target, so the assignments never reach the target's argument vector. Measured against the live soul: ``` $ ps -ww -o command= -p 95688 /Users/timlingo/neuron-dev-stack/bin/soul ``` Clean. Zero `API_KEY` occurrences. **What is real, and smaller:** the key lives in the daemon's *environment* for the life of the process, and on macOS `ps -E` exposes a process's environment to any process running as the same user. Measured (names only, values withheld): ``` $ ps -Eww -o command= -p 95688 | grep -oE "^[A-Z_]+API_KEY=" ANTHROPIC_API_KEY= ENGRAM_API_KEY= SOUL_API_KEY= ``` So the accurate statement is: **any process running as the user can read the customer's provider API key out of the brain's environment.** Not cross-user, not over the network — but it does mean any userspace app on the machine can lift the key without touching the Keychain, which is the thing the Keychain storage was protecting against. Worth a decision rather than a fix-by-reflex: passing the key on stdin at startup, or having the brain read it from the Keychain itself, both close it. Given that neuron#110 currently lets the *network* write memory unauthenticated, this one is the lesser concern — but it is on the same surface and worth handling in the same pass. --- Cross-refs: neuron#110 (P0 network exposure), neuron#111 (dist/soul.c regen), neuron#112 (env var name drift, same root class as item 2), neuron#109 (adds the item-1 banner), neuron-ui#209 (regen automation).
tim.lingo added the ORTHOGONAL label 2026-08-06 03:31:13 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: neuron-technologies/neuron#113