fix(remediation): allow sandbox output paths #177

Merged
nimmo merged 2 commits from fix/issue-176-remediation-output-policy into main 2026-08-16 09:15:40 +01:00
Owner

Summary

  • allow the two exact absolute output paths used by OpenCode inside the Bubblewrap sandbox
  • retain the deny-by-default edit policy and all other tool boundaries
  • assert the generated global and remediation-agent edit policies exactly match those paths

Validation

  • ./tests/nixos-update-remediation-regressions.sh
  • nix flake check

Remaining live evidence

A Nova remediation canary and no-op follow-up remain required after merge; this MR intentionally uses Refs #176 rather than closing the issue.

Refs #176

## Summary - allow the two exact absolute output paths used by OpenCode inside the Bubblewrap sandbox - retain the deny-by-default edit policy and all other tool boundaries - assert the generated global and remediation-agent edit policies exactly match those paths ## Validation - `./tests/nixos-update-remediation-regressions.sh` - `nix flake check` ## Remaining live evidence A Nova remediation canary and no-op follow-up remain required after merge; this MR intentionally uses `Refs #176` rather than closing the issue. Refs #176
fix(remediation): allow sandbox output paths
All checks were successful
Build and Push Attic Cache / test (pull_request) Successful in 1m36s
Build and Push Attic Cache / build (pull_request) Has been skipped
Build and Push Attic Cache / pin-lifecycle (pull_request) Has been skipped
Build and Push Attic Cache / remediate (pull_request) Has been skipped
Build and Push Attic Cache / notify-remediation (pull_request) Has been skipped
AI pull-request review / review (pull_request) Successful in 2m38s
d0ecacdc88
Refs #176
Author
Owner

Automated code review

Reviewed commit: a9e75c7b0166f659843634a5f0ebfc428ab8dfed

Verdict: Ready to merge

No blocking or important findings were retained, and deterministic checks passed. Suggestions remain advisory.

Overall assessment

Updates OpenCode sandbox policy to anchor read/exclude and edit/allow paths to absolute /workspace/ prefixes, preventing unintended access outside the sandboxed environment. Corresponding integration tests are updated to verify exact permission dictionaries for both top-level and nested agent configurations.

Blocking findings

None.

Important findings

None.

Suggestions

  • Verify policy engine precedence for allow-all vs specific deny patterns (scripts/nixos-update-remediation.py:953; medium confidence)
    "*": "allow" precedes specific deny patterns (e.g., "/workspace/.env": "deny") in the read dictionary.
    Impact: Depending on the policy engine's evaluation model, a sequential first-match or allow-override rule could bypass specific deny restrictions, weakening sandbox isolation.
    Suggested fix: Confirm that the underlying policy engine uses a deny-override precedence model. If it evaluates sequentially, consider placing specific deny patterns before the wildcard allow rule, or explicitly document the expected evaluation order.

Tests and validation

  • No configured deterministic checks.

Questions

  • Does the underlying policy/glob engine evaluate dictionary entries sequentially, or does it use a separate precedence/weight system for allow vs deny rules?

Review limitations

  • Review is limited to the provided diff; cannot validate runtime sandbox behavior, full flake evaluation, or regression test execution without direct access to the repository environment.
  • Assumes the policy engine's glob matching and precedence rules align with standard implementations; actual behavior depends on the specific OpenCode/Bubblewrap integration.

Diff coverage

  • scripts/nixos-update-remediation.py: reviewed — included in a context-limited batch
  • tests/nixos-update-remediation-integration.py: reviewed — included in a context-limited batch
Review metadata
  • Reviewer: forgejo-ai-review v1
  • Model: qwen3.6:35b-a3b-q8_0
  • Guidance loaded: .forgejo/ai-review.md, .forgejo/ai-review.yml, AGENTS.md, README.md
  • Commits considered: 2
  • Previous automated review: updated
  • Findings: 1
<!-- forgejo-ai-review:v1 --> ## Automated code review Reviewed commit: `a9e75c7b0166f659843634a5f0ebfc428ab8dfed` ## Verdict: Ready to merge No blocking or important findings were retained, and deterministic checks passed. Suggestions remain advisory. ### Overall assessment Updates OpenCode sandbox policy to anchor read/exclude and edit/allow paths to absolute `/workspace/` prefixes, preventing unintended access outside the sandboxed environment. Corresponding integration tests are updated to verify exact permission dictionaries for both top-level and nested agent configurations. ### Blocking findings None. ### Important findings None. ### Suggestions - **Verify policy engine precedence for allow-all vs specific deny patterns** (scripts/nixos-update-remediation.py:953; medium confidence) "*": "allow" precedes specific deny patterns (e.g., "/workspace/.env": "deny") in the `read` dictionary. Impact: Depending on the policy engine's evaluation model, a sequential first-match or allow-override rule could bypass specific deny restrictions, weakening sandbox isolation. Suggested fix: Confirm that the underlying policy engine uses a deny-override precedence model. If it evaluates sequentially, consider placing specific deny patterns before the wildcard allow rule, or explicitly document the expected evaluation order. ### Tests and validation - No configured deterministic checks. ### Questions - Does the underlying policy/glob engine evaluate dictionary entries sequentially, or does it use a separate precedence/weight system for allow vs deny rules? ### Review limitations - Review is limited to the provided diff; cannot validate runtime sandbox behavior, full flake evaluation, or regression test execution without direct access to the repository environment. - Assumes the policy engine's glob matching and precedence rules align with standard implementations; actual behavior depends on the specific OpenCode/Bubblewrap integration. ### Diff coverage - `scripts/nixos-update-remediation.py`: **reviewed** — included in a context-limited batch - `tests/nixos-update-remediation-integration.py`: **reviewed** — included in a context-limited batch <details><summary>Review metadata</summary> - Reviewer: forgejo-ai-review v1 - Model: qwen3.6:35b-a3b-q8_0 - Guidance loaded: .forgejo/ai-review.md, .forgejo/ai-review.yml, AGENTS.md, README.md - Commits considered: 2 - Previous automated review: updated - Findings: 1 </details>
fix(remediation): anchor read exclusions to sandbox
All checks were successful
Build and Push Attic Cache / test (pull_request) Successful in 1m35s
Build and Push Attic Cache / build (pull_request) Has been skipped
Build and Push Attic Cache / pin-lifecycle (pull_request) Has been skipped
Build and Push Attic Cache / remediate (pull_request) Has been skipped
Build and Push Attic Cache / notify-remediation (pull_request) Has been skipped
AI pull-request review / review (pull_request) Successful in 2m15s
a9e75c7b01
Refs #176
Author
Owner

Review follow-up addressed in a9e75c7.

/workspace is the single canonical sandbox root: the controller read-only binds the worktree there, rebinds the two writable output files beneath it, and starts OpenCode with both --chdir /workspace and --dir /workspace; there is no fallback root.

The audit also found the existing path-specific read exclusions were relative. They are now anchored to /workspace (including root and nested .env files, .git, and secrets), and the regression fixture asserts the exact global and agent policy maps. The remediation suite and nix flake check pass again.

Review follow-up addressed in a9e75c7. `/workspace` is the single canonical sandbox root: the controller read-only binds the worktree there, rebinds the two writable output files beneath it, and starts OpenCode with both `--chdir /workspace` and `--dir /workspace`; there is no fallback root. The audit also found the existing path-specific read exclusions were relative. They are now anchored to `/workspace` (including root and nested `.env` files, `.git`, and `secrets`), and the regression fixture asserts the exact global and agent policy maps. The remediation suite and `nix flake check` pass again.
Author
Owner

Verified the remaining advisory point against the current OpenCode permissions documentation: rules are evaluated by pattern match and the last matching rule wins. The documented common pattern is exactly a catch-all first, followed by specific overrides.

Our read policy therefore deliberately has "*": "allow" first and the /workspace/... deny rules afterwards; the latter take precedence for protected paths. No code change is needed for this advisory finding.

Source: https://opencode.ai/docs/permissions/#granular-rules-object-syntax

Verified the remaining advisory point against the current OpenCode permissions documentation: rules are evaluated by pattern match and the **last matching rule wins**. The documented common pattern is exactly a catch-all first, followed by specific overrides. Our read policy therefore deliberately has `"*": "allow"` first and the `/workspace/...` deny rules afterwards; the latter take precedence for protected paths. No code change is needed for this advisory finding. Source: https://opencode.ai/docs/permissions/#granular-rules-object-syntax
nimmo merged commit 65f4f5c768 into main 2026-08-16 09:15:40 +01:00
nimmo deleted branch fix/issue-176-remediation-output-policy 2026-08-16 09:15:41 +01:00
Sign in to join this conversation.
No reviewers
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
nimmo/nixos-config!177
No description provided.