Skip to content

fix(opencode): block recursive deletes and review decisions - #3676

Open
Kerberosmansour (kerberosmansour) wants to merge 1 commit into
microsoft:mainfrom
kerberosmansour:agent/fix-3662-opencode-default-enforcement
Open

fix(opencode): block recursive deletes and review decisions#3676
Kerberosmansour (kerberosmansour) wants to merge 1 commit into
microsoft:mainfrom
kerberosmansour:agent/fix-3662-opencode-default-enforcement

Conversation

@kerberosmansour

@kerberosmansour Kerberosmansour (kerberosmansour) commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • correct the bundled policy's recursive-delete matcher so common rm flag forms are denied
  • fail closed when an enforce-mode tool rule resolves to review, because the OpenCode adapter has no approval continuation
  • retain non-blocking review behavior in advisory mode
  • add regression coverage for combined, split, and long-form recursive/force flags

Root cause

The regular expression treated -rf as a word-boundary token, which cannot match as written. Separately, enforce-mode review decisions were allowed to continue even though the adapter cannot complete an approval flow.

Validation

  • cd agent-governance-opencode && npm run check — 26/26 tests passed
  • changed-line spelling and whitespace checks passed

Closes #3662

Tracking and overlapping work

Signed-off-by: kerberosmansour <13433538+kerberosmansour@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@github-actions github-actions Bot added the size/S Small PR (< 50 lines) label Aug 10, 2026
@github-actions

Copy link
Copy Markdown

PR Review Summary

Check Status Details
🔍 Code Review ⚠️ Missing No current-run comment
🛡️ Security Scan ⚠️ Missing No current-run comment
🔄 Breaking Changes ⚠️ Missing No current-run comment
📝 Docs Sync ⚠️ Missing No current-run comment
🧪 Test Coverage ⚠️ Missing No current-run comment

Verdict: ⚠️ AI review incomplete; ready for human review

AI review comments are untrusted advisory output. The summary reports workflow-generated completion status only, not model-authored pass/fail claims.

@github-actions

Copy link
Copy Markdown

🟡 Contributor Check: MEDIUM

Check Result
Profile MEDIUM
Credential MEDIUM
Overall MEDIUM

Automated check by AGT Contributor Check.

@github-actions github-actions Bot added the needs-review:MEDIUM Contributor check flagged MEDIUM risk label Aug 10, 2026
@kerberosmansour
Kerberosmansour (kerberosmansour) marked this pull request as ready for review August 10, 2026 22:08
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested the regex claim rather than reading it, because "this pattern cannot match as written" is worth confirming before it goes in a changelog. It is correct, and it is worse than the summary implies.

\brm\b[\s\S]*\b-rf\b matched nothing at all. \b before - requires a word-to-non-word transition, and in rm -rf / the character before the hyphen is a space, so non-word meets non-word and there is no boundary. Ten cases through both patterns:

command                      OLD    NEW
rm -rf /                     False  True
rm -fr /                     False  True
rm -r -f /                   False  True
rm --recursive --force /     False  True
rm --force --recursive /     False  True
rm -rf ./build               False  True
rm file.txt                  False  False
rm -r /tmp/x                 False  False
rm -f /tmp/x                 False  False
confirm -rf thing            False  False

So the bundled default policy shipped a recursive-delete deny rule that never fired. For a governance toolkit that is the worst failure mode available: the control is present in the policy file, visible to anyone auditing it, and inert. Nothing downstream could have noticed, because a rule that never matches is indistinguishable from a rule whose condition is never met.

The new pattern holds on both sides. It catches combined, split and long-form flags in either order, and it does not match rm without both flags, or confirm -rf. Requiring recursive and force is a deliberate narrowing rather than an oversight, so rm -r /tmp/x still passes; that matches the rule's stated intent, and widening it is a separate policy decision rather than a bug fix.

The second half is a genuinely dead branch: return state.policy.mode === "advisory" ? "review" : "review" returns the same value either way. Given the adapter has no approval continuation, an enforce-mode review meant the call proceeded with nobody reviewing it, which reads as enforcement and is not. Returning deny there and keeping non-blocking review in advisory mode is the right split.

On #3251: agreed it is the maintainers' call to sequence, and flagging it rather than opening a third implementation is the right instinct. Worth noting it is currently sitting with fixes pushed after its last review, so it needs a maintainer look either way.

No approve bit on this repo, so a comment, but I would merge it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-review:MEDIUM Contributor check flagged MEDIUM risk size/S Small PR (< 50 lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: OpenCode default policy can permit recursive deletion and review is non-blocking

2 participants