fix(kernel): require env:write for Shared-scope env mutations - #1605
Conversation
|
@cursor Can you please fix the PR template, but also make sure that CI is green? |
|
I fixed the rustfmt and clippy failures, added a DCO sign-off, and filled the PR template. Code / DCO (on Template: I could not overwrite #1605’s description (not agent-managed). The filled template is in a comment on #1605 — paste it into the description to clear that check. Same change with the template already applied: #1644 ( Waiting on CI for both branches. I’ll fix anything that still fails. |
Host-wide Shared env/secret namespaces are not principal-private storage. Gate Shared EnvSet/EnvDelete on global env:write even when the caller names themselves, so self:* agents cannot write system:control:* scopes. Co-authored-by: Joshua J. Bouw <[email protected]> Signed-off-by: Cursor Agent <[email protected]>
e0628ea to
daab43c
Compare
|
I could not overwrite this PR description from the agent (GitHub rejects the edit as not agent-managed). Please replace the description with the filled template below so the template / linked-issue checks pass. The same change with this template applied is also in #1644. ## Linked Issue
Closes #1544
This lands one public-runtime hardening item from the adversarial audit: Shared-scope env/secret mutations must require global `env:write`. Remaining #1544 sub-issues are tracked separately (#1545–#1552).
## Summary
Host-wide `EnvStorageScope::Shared` namespaces are not principal-private storage. The kernel previously treated `EnvSet`/`EnvDelete` as self-scoped whenever the caller named themselves, so a builtin `self:*` agent could write `system:control:*` secrets that every principal's capsule resolution falls back to.
This change gates Shared-scope env mutations on global `env:write`. Agent-scoped self writes stay on `self:env:write`.
## Changes
- Resolve `EnvSet`/`EnvDelete` with `EnvStorageScope::Shared` as `AuthorityScope::Global`, even when `principal == caller`.
- Keep Agent-scoped env writes self-scoped when the caller targets themselves.
- Add a regression test that builtin agent profiles cannot authorize Shared writes and still can authorize `self:env:write`.
- Changelog fragment: `changes/1544.security.md`.
## Verification
- `cargo fmt --all -- --check`
- `cargo test -p astrid-kernel --lib shared_env_mutations --locked`
- `cargo clippy -p astrid-kernel --locked --all-targets -- -D warnings`
## AI / Tool Assistance
Assisted-by: Cursor Grok 4.6
Cursor drafted the Shared-scope authority gate, the regression test, rustfmt/clippy cleanups, and this PR template. I reviewed that Shared writes require `env:write`, Agent-scoped self writes remain `self:env:write`, and the previous dedicated Shared match arm is gone so `clippy::match_same_arms` does not fire.
## Checklist
- [x] Linked to an issue
- [x] Changelog fragment added under `changes/1544.security.md`
- [x] I understand every change in this PR and can explain its design, risks, and validation.
- [x] I reviewed and tested any meaningful tool-generated output included in this PR.
- [x] Every non-bot, non-merge commit has a matching `Signed-off-by` trailer. |
joshuajbouw
left a comment
There was a problem hiding this comment.
Makes sense to me, good catch.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit daab43c. Configure here.
astrid secret delete probes Agent then Shared. After Shared EnvDelete requires global env:write, a self-scoped agent failed the command via into_result even when the agent-scoped delete already succeeded. Treat Shared permission denials as a skipped probe. Agent-scope denials and Shared validation errors still fail. Signed-off-by: Cursor Agent <[email protected]> Co-authored-by: Joshua J. Bouw <[email protected]>



Linked Issue
Closes #1544
This lands one public-runtime hardening item from the adversarial audit: Shared-scope env/secret mutations must require global
env:write. Remaining #1544 sub-issues are tracked separately (#1545–#1552).Summary
Host-wide
EnvStorageScope::Sharednamespaces are not principal-private storage. The kernel previously treatedEnvSet/EnvDeleteas self-scoped whenever the caller named themselves, so a builtinself:*agent could writesystem:control:*secrets that every principal's capsule resolution falls back to.This change gates Shared-scope env mutations on global
env:write. Agent-scoped self writes stay onself:env:write.Changes
EnvSet/EnvDeletewithEnvStorageScope::SharedasAuthorityScope::Global, even whenprincipal == caller.self:env:write.changes/1544.security.md.Verification
cargo fmt --all -- --checkcargo test -p astrid-kernel --lib shared_env_mutations --lockedcargo clippy -p astrid-kernel --locked --all-targets -- -D warningsAI / Tool Assistance
Assisted-by: Cursor Grok 4.6
Cursor drafted the Shared-scope authority gate, the regression test, rustfmt/clippy cleanups, and this PR template. I reviewed that Shared writes require
env:write, Agent-scoped self writes remainself:env:write, and the previous dedicated Shared match arm is gone soclippy::match_same_armsdoes not fire.Checklist
changes/1544.security.mdSigned-off-bytrailer.Note
High Risk
This is authorization hardening on env/secret admin mutations; incorrect scope mapping could either block legitimate admins or re-open host-wide secret poisoning by self-scoped principals.
Overview
Closes a privilege-escalation path where builtin agents with only
self:env:writecould mutate host-wide shared env/secret namespaces by naming themselves as the target principal.resolve_admin_scopenow treatsEnvSetandEnvDeleteas global authority whenscopeisShared(even ifprincipal == caller), because shared storage is not principal-private and capsules can fall back tosystem:control:*on miss. Cross-principal env mutations remain global; agent-scoped self writes still resolve toself:env:write.A regression test asserts shared set/delete require
env:writeand that the builtin agent profile cannot authorize globalenv:writewhile still allowingself:env:write. Changelog fragment added underchanges/1544.security.md.Reviewed by Cursor Bugbot for commit daab43c. Bugbot is set up for automated code reviews on this repo. Configure here.