fix(kernel-cli,kernel-node-runtime): restrict the daemon control socket's permissions and RPC surface - #1034
Open
sirtimid wants to merge 4 commits into
Open
fix(kernel-cli,kernel-node-runtime): restrict the daemon control socket's permissions and RPC surface#1034sirtimid wants to merge 4 commits into
sirtimid wants to merge 4 commits into
Conversation
The control socket had no authentication and no explicit permissions, so authorization was whatever the ambient umask happened to leave behind. It also served `executeDBQuery`, which runs caller-supplied SQL against kernel state. - Create `$OCAP_HOME` 0700 and `daemon.sock` 0600 explicitly. The directory mode is reapplied on every start so an `$OCAP_HOME` from before this change is brought forward rather than keeping its old permissions. - Withhold `executeDBQuery`, `clearState`, and `terminateAllVats` from the handler set unless the daemon is started with `OCAP_DEV_MODE=true`. - Document the trust model: anyone who can open the socket controls the kernel, so this narrows the surface without being a security boundary. Fixes #988 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…parsing The $OCAP_HOME mode assertions and the only end-to-end exercise of OCAP_DEV_MODE lived in a suite that no workflow ran, so deleting the chmod in daemon-entry would have left CI green. `resolveDevMode` moves to its own module taking `env` and `warn` as parameters. daemon-entry calls `main()` at module load and so cannot be imported by a test; the exact-match parsing is the part worth pinning, since relaxing it to something like `!== 'false'` would serve arbitrary SQL on a daemon whose operator believed the flag was unset. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
sirtimid
marked this pull request as ready for review
August 26, 2026 13:49
sirtimid
marked this pull request as draft
August 26, 2026 13:51
sirtimid
marked this pull request as ready for review
August 26, 2026 13:51
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 57d5620. Configure here.
An ambient OCAP_DEV_MODE=true leaked through the spawn env and unlocked the dev-only methods, making the refusal assertions vacuous. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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.

Fixes #988.
The daemon control socket had no authentication and no explicit permissions, so authorization was whatever the ambient umask happened to leave behind. It also served
executeDBQuery, which runs caller-supplied SQL against kernel state.Permissions are explicit
$OCAP_HOMEis created0700anddaemon.sock0600. The directory mode is reapplied on every start, so an$OCAP_HOMEcreated before this change is brought forward rather than keeping its old permissions.The socket bind runs under a
0o177umask so it is not briefly reachable by other local users between bind andchmod. Achmodthat fails closes the server rather than leaving it listening on a socket whose mode is unknown.Dev-only methods
executeDBQuery,clearState, andterminateAllVatsare served only when the daemon is started withOCAP_DEV_MODE=true. Their handlers are not registered at all in default mode, so theexecuteDBQueryhook is never constructed. The refusal message names the flag rather than reporting a bare "Method not found" for a method the operator can see in the source.OCAP_DEV_MODEis matched exactly:1,TRUE, andyesall leave dev mode off, with a warning.Trust model
Documented in
packages/kernel-cli/README.md. Anyone who can open the socket controls the kernel —launchSubclusterruns caller-supplied vat code in a worker thread of the daemon process, andqueueMessageinvokes any method on any object the kernel holds. So the gating narrows the surface but is not a security boundary, and is not a substitute for keeping the socket private.Two points on scope:
resetis not a separate RPC method.kernel.reset()is reachable only throughclearState, which is gated.revoke,terminateVat, andterminateSubclusterstay reachable. The criterion is blast radius, not destructiveness — per-vat operations are part of normal operation. GatingterminateAllVatsis close to cosmetic, sincegetStatusplus a loop overterminateSubclusterreproduces it; it is gated for symmetry withclearState.Testing
rpc-socket-server.test.tsis new — the file had no unit coverage. It covers the socket mode, the fail-closedchmodpath, gating in both directions driven by the exportedDEV_ONLY_METHODS, and that a refusedexecuteDBQuerynever reaches the database.dev-mode.test.tspins theOCAP_DEV_MODEvalue table.E2E coverage in both tiers, including the upgrade path: the CLI helper loosens
$OCAP_HOMEto0755aftermkdtempso the daemon'schmodhas something real to tighten.@metamask/kernel-cliis added to the CI e2e matrix. It was in no workflow, so the$OCAP_HOMEassertions and the only end-to-end exercise ofOCAP_DEV_MODEnever ran on a PR.Follow-ups, not addressed here
isSocketLivetreats any connect error as "stale". With the socket now0600, a probe against another user's live daemon returnsEACCESand reads as absent. Only reachable when$OCAP_SOCKET_PATHpoints at a shared non-sticky directory, but it should decide on the errno.process.umasknarrowing inbind()is best-effort and unobservable when skipped (it throws on a worker thread). A logger would make the claim falsifiable.🤖 Generated with Claude Code
Note
Medium Risk
Changes daemon authorization (permissions) and breaking RPC defaults for methods that touch kernel state; socket access still fully controls the kernel per the documented trust model.
Overview
Hardens the daemon control socket by setting explicit filesystem permissions and narrowing the default RPC surface, with docs and CI to match.
Permissions: On start,
$OCAP_HOMEis ensured0700(including upgrading older dirs) anddaemon.sockis0600. The RPC server binds under a restrictive umask and refuses to listen if post-bindchmodfails, instead of leaving a world- or group-writable socket.Dev-only RPC (breaking):
executeDBQuery,clearState, andterminateAllVatsare not registered unless the daemon runs withOCAP_DEV_MODE=true(exact string only; other values warn and stay off). Default callers get a method-not-found message that names the flag. The CLI wires env resolution via newresolveDevModeand passesdevModeintostartDaemon/startRpcSocketServer.Docs & CI: README adds a trust model for the unauthenticated socket and drops resolved “limitations.”
@metamask/kernel-clijoins the e2e workflow matrix. Unit and e2e tests cover permissions, gating, and the chmod fail-closed path.Reviewed by Cursor Bugbot for commit 3e0329a. Bugbot is set up for automated code reviews on this repo. Configure here.