feat(engine): Phase 0.5 — engine-enforced capabilities + deploy_dir path validation #11
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feature/phase05-engine-caps"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes the SOL-audit CRITICAL: the machine credential is full engine admin, so a compromised MCP can mutate the registry (≈ RCE by next deploy), unlock, or PATCH a shell-bearing
deploy_dir. This adds the durable boundary the ADR 0008 threat model requires.Additive & backward-compatible — the admin token keeps FULL access (
capScopestays undefined); nothing changes until a scoped token is issued and used. Safe to merge now; behavior flips only when the rollout below runs.What
KUA_DEPLOY_SCOPED_TOKENS(mirrors kua-vault'sKUA_VAULT_SCOPED_TOKENS):[{name, token(32+), caps:[read|deploy|rollback|registry:write|admin]}], digests stored not raw, matched inonRequest→request.capScope.requireCap()on every mutating endpoint: registryPUT/PATCH/DELETE+/registry/reload→registry:write;/release /deploy /rebuild→deploy;/rollback→rollback;/unlock+/progress/reset→admin;/runtime-status→ admin token or scopedread.isSafeDeployPath():repo_dir/deploy_dirmust match^/root/apps/[A-Za-z0-9._/-]+$with no..(they're interpolated intocd ${deployDir}). All 24 live registry entries already pass (verified).Verification
node --checkclean; capability matrix + path-injection cases unit-tested (all pass): a[deploy,rollback,read]token can deploy/rollback/read, cannot registry-write/unlock/reset; paths reject; rm,$(...),.., and outside-/root/apps.Rollout (follow-up, canaried — not in this PR)
{caps:[deploy,rollback,read]}token into kua-vault + setKUA_DEPLOY_SCOPED_TOKENSon the engine.getDeployAdminToken).🤖 Generated with Claude Code
Closes the SOL-audit CRITICAL: the machine credential was full engine admin, so a compromised MCP could mutate the registry (≈ RCE by next deploy), unlock, or PATCH a shell-bearing deploy_dir. This adds a scoped-token capability layer + path validation. ADDITIVE and backward-compatible: the admin token keeps FULL access (request.capScope stays undefined), so nothing changes until a scoped token is issued and a caller uses it. - Scoped tokens (KUA_DEPLOY_SCOPED_TOKENS, mirrors kua-vault's KUA_VAULT_SCOPED_TOKENS): JSON array of {name, token(32+), caps:[read|deploy|rollback|registry:write|admin]}. Digests stored, never raw. Matched in onRequest -> request.capScope. - requireCap() gates every mutating endpoint: * registry PUT/PATCH/DELETE + /registry/reload -> registry:write * /release /deploy /rebuild -> deploy ; /rollback -> rollback ; PATCH /progress -> deploy * /unlock + /progress/reset -> admin * /runtime-status -> admin token OR scoped 'read' (keeps its hard-bearer intent) - isSafeDeployPath(): repo_dir/deploy_dir must match ^/root/apps/[A-Za-z0-9._/-]+$ and contain no "..". All 24 live registry entries already pass (verified). Rollout (follow-up, canaried): (1) issue a scoped {caps:[deploy,rollback,read]} token into kua-vault + set KUA_DEPLOY_SCOPED_TOKENS on the engine; (2) switch kua-mcp-core to that token instead of the admin bearer; (3) deploy engine + verify a scoped token deploys OK but registry PUT returns 403 (the ADR Phase 2 test). Then the MCP no longer holds full admin. Logic unit-tested (capability matrix + path-injection cases all pass); node --check clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>