feat(security): make the resolved permission posture explicit and observable - #231
Open
raymondginger2018-sudo wants to merge 3 commits into
Open
feat(security): make the resolved permission posture explicit and observable#231raymondginger2018-sudo wants to merge 3 commits into
raymondginger2018-sudo wants to merge 3 commits into
Conversation
The effective security posture is spread across four interacting knobs (permission mode, access preset, command sandbox, approval policy), so no single field in a transcript tells a reader whether the run was gated or wide open: an unattended `full_auto` run and an attended one look identical. `describe_security_posture(profile, *, sandbox_backend=None)` returns a flat, string-friendly mapping suitable for a log line or a structured event, with `unattended` as the headline fact. It reports facts; it does not judge them. The one subtlety it encodes: legacy `full_auto` short-circuits the engine with an unconditional ALLOW while still reporting `on_request`, so trusting the approval policy field alone would label the most permissive configuration as gated -- the exact mistake this helper exists to prevent. Also exports the module's public names via `__all__` so the intended surface is explicit. Pure addition; no behaviour change to existing callers.
`build_agent_session` resolves the security profile on every call, but the result was invisible afterwards: the four knobs (permission mode, access preset, command sandbox, approval policy) interact, so an unattended `full_auto` run reads identically to an approval-gated one in a transcript. Log the flattened posture once per session, next to the engine it describes, so "could a rewritten tool call have run unattended?" is answerable from the log rather than reconstructed from four separate fields.
This workflow is the one caller that intentionally runs with no approver. Passing `default_mode=PermissionMode.FULL_AUTO` at the call site instead of inheriting the signature default makes the intent readable where it applies, and gives "who runs with no approver?" a grep-able answer. No behaviour change.
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.
What
The effective permission posture is resolved from four interacting knobs — permission mode, access preset, command sandbox, approval policy — and no single one of them tells a reader whether a run was gated or wide open. An unattended
full_autorun and an approval-gated one look identical in a transcript.This makes the resolved posture explicit, visible, and tested:
core/harness/policy.py—describe_security_posture(profile, *, sandbox_backend=None)returns a flat, string-friendly mapping (unattendedbeing the headline fact) suitable for a log line or a structured event without further shaping. It reports facts; it does not judge them. Also states the module's public surface via__all__.core/agent_setup.py— log the flattened posture once per session, next to the engine it describes, so "could a rewritten tool call have run unattended?" is answerable from the log instead of being reconstructed from four separate fields.workflows/code_implementation_workflow.py— statedefault_mode=PermissionMode.FULL_AUTOat the call site: this workflow is the one caller that intentionally runs with no approver. No behaviour change; the intent is simply readable where it applies.tests/test_harness_policy.py— 3 cases: the trap below, the gated modes, and rule counting.The subtlety it encodes
Legacy
full_autoshort-circuits the engine with an unconditional ALLOW while still reporting anon_requestapproval policy. A report that trusted the policy field alone would therefore label the most permissive configuration as gated — the exact mistake this helper exists to prevent. That is whyunattendedis derived from both fields, and why the test asserts it.Verification
pytest tests/test_harness_policy.py→ 19 passedpytest tests/test_harness_policy.py tests/application/test_agent_adapter.py tests/test_mcp_server.py tests/test_spawn_agent.py tests/test_subagent_composition.py→ 75 passedruff check+ruff format --checkon all four files with ruff 0.15.21 (the version pinned by.pre-commit-config.yaml) → clean