[P0][SECURITY] Unauthenticated LAN + unfenced /api/tools/file/write = remote arbitrary file write (escalates #110) #128

Open
opened 2026-08-07 03:13:35 +00:00 by tim.lingo · 1 comment
Member

Severity escalation of neuron#110 (BUG-41). Two separately-known facts combine into remote arbitrary file write on the user's machine. Both verified in the CURRENT shipped brain (8ec39278…, round 9.1) this session.

Fact 1 — the brain listens on all interfaces with no authentication. Byte search of the shipped binary: EL_HTTP_BIND_HOST 0 occurrences, EL_HTTP_AUTH_KEY 0 occurrences — the launcher sets both and logs "loopback-locked", and neither exists on the receiving side. Previously measured end-to-end: GET /health and an unauthenticated POST /api/neuron/memory both succeeded from the machine's LAN IP.

Fact 2 — there is an unfenced file-write route. POST /api/tools/file/write (studio.el:106-114) writes to any path, with no workspace fence, no path validation, and no check of the write's return — it responds ok:true regardless of whether the write succeeded. Present in the shipped binary (/api/tools/file/write, 1 occurrence). It has no caller in the app, so nothing in normal product use exercises it.

Combined: anything on the same Wi-Fi can write arbitrary files anywhere the Neuron process can reach, unauthenticated, with no user interaction and no record in the app. That includes the user's own dotfiles and login items. This is materially worse than the read/write-the-memory-graph exposure #110 was filed for.

Not exploited, not tested against a third party — asserted from the binary's own contents plus #110's earlier live LAN measurement. Confirming it end-to-end would mean writing a file to a machine over the network, which we have not done and will not without your say-so.

Why now: the beta test wave runs in an isolated VM, so this is contained today. It must close before any build reaches a person on a real network — a coffee-shop or shared-office Wi-Fi is exactly the scenario.

What done looks like: the binary honors a loopback bind and a per-install auth key (making the launcher's existing claim true), AND the write route grows a workspace fence with a checked return — or is removed, since nothing calls it.

**Severity escalation of neuron#110 (BUG-41). Two separately-known facts combine into remote arbitrary file write on the user's machine. Both verified in the CURRENT shipped brain (`8ec39278…`, round 9.1) this session.** **Fact 1 — the brain listens on all interfaces with no authentication.** Byte search of the shipped binary: `EL_HTTP_BIND_HOST` **0 occurrences**, `EL_HTTP_AUTH_KEY` **0 occurrences** — the launcher sets both and logs "loopback-locked", and neither exists on the receiving side. Previously measured end-to-end: `GET /health` and an unauthenticated `POST /api/neuron/memory` both succeeded from the machine's LAN IP. **Fact 2 — there is an unfenced file-write route.** `POST /api/tools/file/write` (`studio.el:106-114`) writes to **any path**, with no workspace fence, no path validation, and no check of the write's return — it responds `ok:true` regardless of whether the write succeeded. Present in the shipped binary (`/api/tools/file/write`, 1 occurrence). It has **no caller in the app**, so nothing in normal product use exercises it. **Combined:** anything on the same Wi-Fi can write arbitrary files anywhere the Neuron process can reach, unauthenticated, with no user interaction and no record in the app. That includes the user's own dotfiles and login items. This is materially worse than the read/write-the-memory-graph exposure #110 was filed for. **Not exploited, not tested against a third party** — asserted from the binary's own contents plus #110's earlier live LAN measurement. Confirming it end-to-end would mean writing a file to a machine over the network, which we have not done and will not without your say-so. **Why now:** the beta test wave runs in an isolated VM, so this is contained today. It must close before any build reaches a person on a real network — a coffee-shop or shared-office Wi-Fi is exactly the scenario. **What done looks like:** the binary honors a loopback bind and a per-install auth key (making the launcher's existing claim true), AND the write route grows a workspace fence with a checked return — or is removed, since nothing calls it.
tim.lingo added the blocks-public-betaP0security labels 2026-08-07 13:51:39 +00:00
Author
Member

Escalation: this is no longer a shipped-binary defect. It is measured, live exposure on a real machine — Tim's, right now. Measured 2026-08-07, read-only probes only.

The running production stack on Tim's Mac (LAN address 192.168.0.97) answers on all interfaces, not loopback:

lsof -nP -iTCP:7770 -sTCP:LISTEN   ->   soul  *:7770        <-- '*', not 127.0.0.1

curl http://192.168.0.97:7770/health                 -> HTTP 200, 204 bytes
curl http://192.168.0.97:7779/                       -> HTTP 200
curl http://192.168.0.97:8742/health                 -> HTTP 200

With no credentials of any kind:

GET /api/graph/nodes?limit=2        -> HTTP 200, 38,865,637 bytes
GET /api/neuron/recall?query=...    -> HTTP 200, 2,046 bytes   (real memory content)

Note limit=2 returned 38.9 MB — the limit parameter is not honoured, so a single unauthenticated request from any device on the network exfiltrates the entire memory graph. That is every memory, every note, everything the user has ever told Neuron.

There is no auth mechanism to misconfigure. Raw-byte count against the shipped brain binary:

X-Neuron-Auth      : 0 occurrences
EL_HTTP_AUTH_KEY   : 0 occurrences
EL_HTTP_BIND_HOST  : 0 occurrences

So this cannot be mitigated by configuration or an environment variable — the capability is absent from the binary. (Related: CredentialStore.kt:366 asserts the soul "requires X-Neuron-Auth". It does not. That claim is false as built.)

Context that makes it worse, not better: the host firewall is disabled (socketfilterfw --getglobalstate → State = 0) and there are 15 hosts in the local ARP cache. This is not a theoretical adjacency.

Composition is the real severity. Paired with the unfenced POST /api/tools/file/write (studio.el:106-114, present in the shipped binary, no path fence, no auth, returns ok regardless), this is remote arbitrary file write as the user with no interaction and no record — from any device on the same Wi-Fi. Read and write, unauthenticated, no audit trail.

Also worth noting: /health is auth-exempt and triggers a live provider call (routes.el:149), so an unauthenticated remote party can drive API spend.

Against the design. The architecture register states INV-RT-02: loopback-only bind plus a per-install keychain key. Today the bind is * and the key does not exist. In a first full conformance run of the invariant register completed today, this was judged the single most urgent violation of 117 — because it is the only one reachable end-to-end from off-loopback with no credentials, and because it amplifies every other read-path violation into a remote one.

This issue is still unassigned. It needs an owner.

Immediate mitigation available to a user today, without touching the daemons: enable the host firewall to block incoming connections. That is a workaround, not a fix — the fix is a loopback bind and a per-install key, which requires engine work.

**Escalation: this is no longer a shipped-binary defect. It is measured, live exposure on a real machine — Tim's, right now.** Measured 2026-08-07, read-only probes only. The running production stack on Tim's Mac (LAN address `192.168.0.97`) answers on **all interfaces**, not loopback: ``` lsof -nP -iTCP:7770 -sTCP:LISTEN -> soul *:7770 <-- '*', not 127.0.0.1 curl http://192.168.0.97:7770/health -> HTTP 200, 204 bytes curl http://192.168.0.97:7779/ -> HTTP 200 curl http://192.168.0.97:8742/health -> HTTP 200 ``` **With no credentials of any kind:** ``` GET /api/graph/nodes?limit=2 -> HTTP 200, 38,865,637 bytes GET /api/neuron/recall?query=... -> HTTP 200, 2,046 bytes (real memory content) ``` Note `limit=2` returned **38.9 MB** — the limit parameter is not honoured, so a single unauthenticated request from any device on the network exfiltrates the entire memory graph. That is every memory, every note, everything the user has ever told Neuron. **There is no auth mechanism to misconfigure.** Raw-byte count against the shipped brain binary: ``` X-Neuron-Auth : 0 occurrences EL_HTTP_AUTH_KEY : 0 occurrences EL_HTTP_BIND_HOST : 0 occurrences ``` So this cannot be mitigated by configuration or an environment variable — the capability is absent from the binary. (Related: `CredentialStore.kt:366` asserts the soul "requires X-Neuron-Auth". It does not. That claim is false as built.) **Context that makes it worse, not better:** the host firewall is **disabled** (`socketfilterfw --getglobalstate` → State = 0) and there are **15 hosts** in the local ARP cache. This is not a theoretical adjacency. **Composition is the real severity.** Paired with the unfenced `POST /api/tools/file/write` (`studio.el:106-114`, present in the shipped binary, no path fence, no auth, returns `ok` regardless), this is **remote arbitrary file write as the user with no interaction and no record** — from any device on the same Wi-Fi. Read and write, unauthenticated, no audit trail. Also worth noting: `/health` is auth-exempt and triggers a live provider call (`routes.el:149`), so an unauthenticated remote party can drive API spend. **Against the design.** The architecture register states `INV-RT-02`: loopback-only bind plus a per-install keychain key. Today the bind is `*` and the key does not exist. In a first full conformance run of the invariant register completed today, this was judged the single most urgent violation of 117 — because it is the only one reachable end-to-end from off-loopback with no credentials, and because it amplifies every other read-path violation into a remote one. **This issue is still unassigned.** It needs an owner. Immediate mitigation available to a user today, without touching the daemons: enable the host firewall to block incoming connections. That is a workaround, not a fix — the fix is a loopback bind and a per-install key, which requires engine work.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: neuron-technologies/neuron#128