microsoft / microsoft/agent-governance-toolkit

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

Open
#3,662 4 comments 0 reactions 0 assignees View on GitHub
needs-review:MEDIUM
Dominant language
Python
Stars
6.3k
Forks
1.1k
Avg merge
5d 11h
Merged PRs (30d)
142

Description

## Package

Other — `agent-governance-opencode`

## Description

The bundled default OpenCode policy can permit a recursive deletion command because two behaviors compound:

1. The `recursive-delete` pattern in `config/default-policy.json` uses `\b-rf\b`. The boundary before `-rf` can never match because both the preceding space and the hyphen are non-word characters.
2. The command therefore falls through to the default `reviewTools` handling for `bash`. `normalizeEffectForOpenCode` returns `review` in both advisory and enforce modes, and the OpenCode hook only appends `__agt_review_reason`; nothing blocks execution.

Current implementation:

```js
return state.policy.mode === "advisory" ? "review" : "review";
```

The result is that a clean installation's default policy evaluates `rm -rf /` as `review`, while the session status and audit trail indicate governance is active.

## How does this impact your work?

This is a critical fail-open path in the shipped default configuration. Operators naturally place high-impact tools in `reviewTools`, but on the OpenCode surface `review` currently behaves like allow unless another host permission layer intervenes.

The current workaround is to keep `reviewTools` empty, use `defaultEffect: "deny"`, and provide human approval through the host's native permission system.

## Steps to Reproduce

```js
import { loadPolicy, evaluateOpenCodeTool } from "@microsoft/agent-governance-opencode/policy";

const state = await loadPolicy({ auditPath: "/tmp/audit.json" });
console.log(await evaluateOpenCodeTool(state, {
tool: "bash",
args: { command: "rm -rf /" },
cwd: "/app",
sessionId: "x",
}));
// observed: { effect: "review", reason: "" }
// expected: deny
```

Also test `rm -fr`, `rm -r -f`, `rm --recursive --force`, and mixed short-flag forms.

## Suggested resolution / acceptance criteria

- Replace the recursive-delete expression with order-independent checks for recursive and force flags, including long forms.
- Add regression tests over the shipped default policy for all common flag arrangements.
- Define enforce-mode `review` semantics explicitly:
- preferably normalize `review` to `deny` when the OpenCode host cannot complete an approval; or
- clearly document that it is non-blocking and expose that limitation in policy status.
- Ensure the default configuration cannot silently permit a command that its own deny rule intends to block.

## Environment

- `@microsoft/agent-governance-opencode@5.0.0`
- `@microsoft/agent-governance-sdk@3.7.0`
- Node 26.7.0
- macOS arm64
- Verified against AGT commit `81955d4`

## Code of Conduct

- [x] I agree to follow the Microsoft Open Source Code of Conduct

## Coordination status

- Active implementation: #3676.
- Related overlapping work: #3251, a broader cross-integration recursive-delete parser.

Contributors should coordinate on those active PRs rather than open a parallel implementation.

Contributor guide

Open the contributing guide

Research direction

Start with config/default-policy.json and normalizeEffectForOpenCode, then run the reproduction for rm -rf / and the listed flag variants. Review the active implementation in #3676 and overlapping work in #3251 before changing anything. Done means the shipped default policy rejects all covered recursive-delete forms and enforce-mode review behavior is explicitly resolved or exposed.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js
Domain
authorization, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.