Skip to content

Revert "Make PR reviews strictly read-only" - #29

Merged
dceoy merged 1 commit into
mainfrom
revert-27-agent/restrict-review-agent-permissions
Jul 11, 2026
Merged

Revert "Make PR reviews strictly read-only"#29
dceoy merged 1 commit into
mainfrom
revert-27-agent/restrict-review-agent-permissions

Conversation

@dceoy

Copy link
Copy Markdown
Owner

Reverts #27

@dceoydceoy self-assigned this Jul 11, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:baa3c2fa7b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadaction.yml
echo "Copied bundled OpenCode config, preserving existing files"
fi
mkdir -p "${HOME}/.config/opencode"
cp -rn "${ACTION_PATH}/.opencode/." "${HOME}/.config/opencode/"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Restore project-config isolation for /review-pr

On /review-pr runs against a checked-out PR, this preserving copy is now paired with the removal of OPENCODE_DISABLE_PROJECT_CONFIG, so OpenCode can still discover .opencode project config/plugins from the repository under review instead of only the trusted toolkit. In workflows that run the reviewer with provider secrets and pull-requests: write, a PR can add a project plugin/command that executes inside the review job before the bundled reviewer starts; the deleted malicious-plugin regression was guarding this exact path. Please keep the fresh trusted config and disable project config for review prompts.

Useful? React with 👍 / 👎.

trap 'rm -f "${review_payload:-}" "${review_update_payload:-}"' EXIT

jq -n \
--arg commit_id "$head_oid" \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Revalidate the PR head before posting reviews

When a review takes long and the PR is pushed after the initial headRefOid/diff are captured, this payload still uses the old $head_oid without first checking that it equals the current gh pr view --json headRefOid. GitHub's review API accepts non-latest commit IDs and documents that they can make comments outdated after subsequent commits, so the POST can succeed with inline comments against a stale diff instead of failing or restarting; re-fetch and compare the head SHA immediately before each review write as the removed helper did.

Useful? React with 👍 / 👎.

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

OpenCode PR Review (this review covers .opencode/agents/code-simplifier.md:6; companion reviews on .opencode/commands/review-pr.md:89, action.yml:104, and action.yml:118 carry the other three inline findings).

This PR is a clean revert of #27 (the fix for #24). The local QA suite (validate-opencode.bats, test-resolve-app-token.bats, prettier, yamllint, shellcheck) still passes on the reverted tree, so the basic invariants hold. The open question is whether the maintainer is intentionally rolling back the review-only boundary that #27 added; if so, the findings below are the most concrete regressions to call out so they are at least visible in the PR history.

Context: #24 documents an incident in which /review-pr executed the reviewed repo's QA script, picked up ruff format / ruff check --fix / prettier --write / zizmor --fix, generated a github_conf/branch_protection_rules.json containing a 404 response, and opencode github run then committed and pushed the dirty worktree to the PR branch as opencode-agent[bot]. #27 closed the resulting trust gap; this PR reopens it.

Summary-only findings (covered in the body of the companion reviews on this PR):

  • review-pr.md (TOCTOU) — Loss of head-SHA pinning. #27's review-pr-gh.sh and review-pr-submit.sh re-read the live headRefOid immediately before each POST/PUT to pulls/.../reviews and aborted on a mismatch. The reverted state has no such guard, so a force-push between gh pr view and the review write can attach the review to a different SHA than the one that was originally analyzed.
  • action.yml (coverage) — Loss of test-review-pr-read-only.bats regression coverage (140 lines covering context detection, head-movement rejection, shell-composition rejection, project-plugin exclusion). The token-resolution path is still covered, but nothing now verifies the review-only guard, the toolkit rm -rf, or OPENCODE_DISABLE_PROJECT_CONFIG.
  • review-pr.md (untested shell) — Token resolution and the 60-line gh api review-submission block are inlined as untested markdown code blocks. set -euo pipefail is gone, shellcheck does not see them, and identity attribution (opencode-agent[bot] vs github-actions[bot] vs fail-closed) now lives in prose rather than in a script with bats tests.
  • code-simplifier.md (cosmetic) — Frontmatter is the only one of 11 agent files without a color: key. The only agent with edit: allow is also the only one missing color:, which makes the inconsistency stand out.
  • README.md (docs/contract drift) — README.md:143 says /review-pr simplify is "refinement only, does not return a review", but with code-simplifier reverted to edit: allow that wording is misleading. Either the agent should remain read-only or the README should describe the new mutating behaviour.

Net effect: the maintainer appears to be trading #27's hard review-only boundary for the simpler pre-#27 workflow, accepting that /review-pr can now mutate the reviewed repo (via the simplify aspect, via the reviewed repo's own .opencode/ config, and via any shell command the agent decides to run) and that head-SHA pinning is best-effort. Token attribution, the external_directory allow-list, and opencode-agent[bot] identity verification are unchanged from #27, so the worst-case identity attribution is still bounded; the remaining holes are data-integrity holes, not token holes.

"*.env.example": allow
glob: allow
grep: allow
edit: allow

@github-actionsgithub-actionsBotJul 11, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical · opencode-agent[bot]: edit: allow re-opens the exact failure mode #24 documented. With this and the new long-form body (You operate autonomously and proactively, refining code immediately after it's written or modified without requiring explicit requests), /review-pr simplify will now write to the reviewed checkout instead of producing proposals. #27's read-only simplify was proposal-only; if the maintainer wants simplify to actually modify files, the AGENTS.md and README should say so explicitly and the agent should at least carry a color: key for consistency with the other ten agents.

github-actions[bot]
github-actionsBot previously requested changes Jul 11, 2026

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical · opencode-agent[bot] (replaced placeholder): the simplify aspect dispatches code-simplifier with no allow-list or read-only constraint, and the agent at .opencode/agents/code-simplifier.md:6 is now edit: allow. Functionally this hands the LLM a write tool over the reviewed PR. If a malicious PR is being reviewed, the agent's own "Recently modified code" framing is whatever files that PR just added, and there is no scope guard distinguishing simplify-on-the-PR from simplify-on-the-worktree. Either gate simplify behind the read-only simplify that #27 had, or document the new mutating behaviour in README.md:143 (which currently still says "refinement only, does not return a review"). The full review body that replaces these placeholder review entries follows in a separate structured review.

- `comments` → `comment-analyzer`
- `errors` → `silent-failure-hunter`
- `types` → `type-design-analyzer`
- `simplify` → run `code-simplifier` as a refinement step only; do not return a review; stop after simplification

@github-actionsgithub-actionsBotJul 11, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical · opencode-agent[bot]: the simplify aspect dispatches code-simplifier with no allow-list or read-only constraint, and the agent at .opencode/agents/code-simplifier.md:6 is now edit: allow. Functionally this hands the LLM a write tool over the reviewed PR. If a malicious PR is being reviewed, the agent's own "Recently modified code" framing is whatever files that PR just added, and there is no scope guard distinguishing simplify-on-the-PR from simplify-on-the-worktree. Either gate simplify behind the read-only simplify that #27 had, or document the new mutating behaviour in README.md:143 (which currently still says "refinement only, does not return a review").

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical · opencode-agent[bot] (replaced placeholder): cp -rn unconditionally merges the bundled .opencode/ into ~/.config/opencode/, with no rm -rf branch for /review-pr runs. #27's REVIEW_ONLY step wiped the global config first and then copied a fresh toolkit, so a reviewed repo's .opencode/config or .opencode/plugins/* was never loaded. That isolation is gone. The malicious-project/.opencode/plugins/pwn.ts fixture that documented this exact path has also been deleted in this PR, removing the regression test that would catch a re-introduction of the bug. The full review body that replaces these placeholder review entries follows in a separate structured review.

Comment threadaction.yml
echo "Copied bundled OpenCode config, preserving existing files"
fi
mkdir -p "${HOME}/.config/opencode"
cp -rn "${ACTION_PATH}/.opencode/." "${HOME}/.config/opencode/"

@github-actionsgithub-actionsBotJul 11, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical · opencode-agent[bot]: cp -rn unconditionally merges the bundled .opencode/ into ~/.config/opencode/, with no rm -rf branch for /review-pr runs. #27's REVIEW_ONLY step wiped the global config first and then copied a fresh toolkit, so a reviewed repo's .opencode/config or .opencode/plugins/* was never loaded. That isolation is gone. The malicious-project/.opencode/plugins/pwn.ts fixture that documented this exact path has also been deleted in this PR, removing the regression test that would catch a re-introduction of the bug.

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

important · opencode-agent[bot] (replaced placeholder): the Run OpenCode env block no longer passes OPENCODE_DISABLE_PROJECT_CONFIG. #27 set it to 1 for /review-pr runs (if: steps.review_mode.outputs.enabled == 'true'); the revert drops it (this TIMEOUT_MINUTES line is the last env-var entry that survived the diff hunk for the deleted line, hence the anchor). Combined with the unconditional cp -rn two steps above, the reviewed repo's own .opencode/ config is back inside the OpenCode trust boundary, which is the same exposure that produced the #24 incident. If the isolation is intentionally removed, please also drop the line in AGENTS.md that documents the review-only mode so the documentation does not contradict the action. The full review body that replaces these placeholder review entries follows in a separate structured review.

Comment threadaction.yml
@@ -139,7 +116,6 @@ runs:
VARIANT: ${{ inputs.variant }}
OIDC_BASE_URL: ${{ inputs.oidc-base-url }}
TIMEOUT_MINUTES: ${{ inputs.timeout-minutes }}

@github-actionsgithub-actionsBotJul 11, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

important · opencode-agent[bot]: the Run OpenCode env block no longer passes OPENCODE_DISABLE_PROJECT_CONFIG. #27 set it to 1 for /review-pr runs (if: steps.review_mode.outputs.enabled == 'true'); the revert drops it (this TIMEOUT_MINUTES line is the last env-var entry that survived the diff hunk for the deleted line, hence the anchor). Combined with the unconditional cp -rn two steps above, the reviewed repo's own .opencode/ config is back inside the OpenCode trust boundary, which is the same exposure that produced the #24 incident. If the isolation is intentionally removed, please also drop the line in AGENTS.md that documents the review-only mode so the documentation does not contradict the action.

@opencode-agent

Copy link
Copy Markdown

Structured PR review submitted to #29 as 4 inline comments plus 4 review bodies (REQUEST_CHANGES on the simplify finding).

Findings (4 inline, 5 summary-only):

  • code-simplifier.md:6 (critical) — edit: allow plus the new "applies refinements … proactively" body make /review-pr simplify actually write to the reviewed checkout. This is the exact failure mode PR review run committed and pushed a generated file #24 documented; Make PR reviews strictly read-only #27 closed it; the revert reopens it.
  • review-pr.md:89 (critical) — the simplify aspect dispatches code-simplifier with no read-only or scope guard, so it's effectively a write tool over the reviewed PR.
  • action.yml:104 (critical) — cp -rn unconditionally merges the bundled .opencode/ into ~/.config/opencode/, with no rm -rf branch for /review-pr runs. The malicious-project/.opencode/plugins/pwn.ts fixture that documented this path is also deleted in this PR.
  • action.yml:118 (important) — Run OpenCode env block no longer passes OPENCODE_DISABLE_PROJECT_CONFIG, restoring the trust-boundary exposure that produced the PR review run committed and pushed a generated file #24 incident.

Summary-only: loss of head-SHA pinning (TOCTOU on review submission), loss of test-review-pr-read-only.bats regression coverage, inlined gh api and token-prep logic in review-pr.md:23-39 and :200-261 (no set -euo pipefail, no shellcheck, no bats), code-simplifier.md is the only one of 11 agents without a color: key, and README.md:143 still describes simplify as "refinement only, does not return a review" while the agent is now edit: allow.

Validation: local QA (validate-opencode.bats, test-resolve-app-token.bats, prettier, yamllint, shellcheck) passes on the reverted tree, so the basic invariants still hold. The external_directory allow-list, App-token identity verification, and opencode-agent[bot] attribution are unchanged from #27 — the remaining holes are data-integrity holes, not token holes.

Review posted at #29 (review) (and companion reviews 4678566162, 4678566237, 4678566485).

github run

@dceoy
dceoy merged commit 15d553c into mainJul 11, 2026
15 checks passed
@dceoy
dceoy deleted the revert-27-agent/restrict-review-agent-permissions branch July 11, 2026 19:17
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@dceoy