|
| 1 | +--- |
| 2 | +pr: google-gemini/gemini-cli#26207 |
| 3 | +sha: 16ff1e342a67de573d2301ebe22d27e9ed96daf5 |
| 4 | +verdict: request-changes |
| 5 | +reviewed_at: 2026-04-29T18:31:00Z |
| 6 | +--- |
| 7 | + |
| 8 | +# Add the ability to @ mention the gemini robot |
| 9 | + |
| 10 | +## Context |
| 11 | + |
| 12 | +Extends `.github/workflows/gemini-cli-bot-brain.yml` to fire on |
| 13 | +`issue_comment` events when a maintainer `@gemini-cli-robot` mentions |
| 14 | +the bot. The bot then loads `tools/gemini-cli-bot/brain/interactive.md`, |
| 15 | +runs in `ENABLE_PRS=true` mode, and is permitted to post comments and |
| 16 | +push to `bot/`-prefixed branches via the |
| 17 | +`GEMINI_CLI_ROBOT_GITHUB_PAT` secret. |
| 18 | + |
| 19 | +## What's good |
| 20 | + |
| 21 | +- The trigger guard at the job level is the right shape — uses |
| 22 | + `contains(fromJSON('["COLLABORATOR", "MEMBER", "OWNER"]'), github.event.comment.author_association)` |
| 23 | + to gate on association rather than username, which is harder to |
| 24 | + spoof. The reasoning job is also `permissions: contents: read`, |
| 25 | + so the LLM call itself can't push. |
| 26 | +- `concurrency.group` now includes `github.event.issue.number || …` |
| 27 | + so two concurrent maintainer mentions on different issues don't |
| 28 | + cancel each other. |
| 29 | +- The `<untrusted_context>...</untrusted_context>` wrapper around |
| 30 | + the comment body and `gh issue view` output in `trigger_context.md` |
| 31 | + is the correct prompt-injection mitigation idiom, and concatenating |
| 32 | + it *before* the system prompt keeps untrusted text from clobbering |
| 33 | + later instructions. |
| 34 | +- The push-time branch guard (`if [[ ! "$BRANCH_NAME" =~ ^bot/ ]]; then exit 1; fi`) |
| 35 | + and the comment-time author guard (`PR_AUTHOR=$(gh pr view "$PR_NUM" --json author --jq '.author.login'); if [ "$PR_AUTHOR" != "gemini-cli-robot" ]; then exit 1; fi`) |
| 36 | + are the right safety belt for the publish phase. |
| 37 | + |
| 38 | +## Concerns |
| 39 | + |
| 40 | +1. **Critique semantics inverted.** The previous code rejected on |
| 41 | + `[REJECTED]` *or* non-zero exit, defaulted to approve. The new |
| 42 | + code rejects on anything that isn't *explicitly* `[APPROVED]` and |
| 43 | + also lacks `[REJECTED]`. That's a stronger gate (good), but the |
| 44 | + comment "Critique failed, rejected, or did not explicitly approve |
| 45 | + changes" hides the fact that this is now a fail-closed contract. |
| 46 | + Maintainers who relied on the old "neutral = approve" semantics |
| 47 | + for their own dispatched runs will see silent skips. Worth a |
| 48 | + release note. |
| 49 | +2. **`Post PR/Issue Comment` step lost its `if:` guard.** Old code |
| 50 | + had `if: "${{ github.event.inputs.enable_prs == 'true' }}"`. The |
| 51 | + new step runs unconditionally — it's safe because the inner `if [ -s ... ]` |
| 52 | + tests check for content, but on a scheduled run with no comment |
| 53 | + artifact you now do extra work and the step shows green-with-noop |
| 54 | + in the UI. Minor but a regression in clarity. |
| 55 | +3. **`gh issue view ... 2>/dev/null || gh pr view "$TRIGGER_ISSUE_NUMBER"`** |
| 56 | + — if both fail (deleted issue, permissions hiccup), the script |
| 57 | + keeps going with empty trigger context. The bot then operates |
| 58 | + blind on whatever `interactive.md` says by default. Should |
| 59 | + `set -e` or explicitly check `[ -s trigger_context.md ]` before |
| 60 | + proceeding. |
| 61 | +4. **PAT scope.** `GEMINI_CLI_ROBOT_GITHUB_PAT` now ships into a |
| 62 | + workflow that any maintainer comment can trigger. If a |
| 63 | + compromised maintainer account exists, this is a remote command |
| 64 | + execution into the bot's branch space. The `bot/` prefix limits |
| 65 | + the blast radius but doesn't eliminate it. Consider narrowing |
| 66 | + the PAT to `contents: write` on `refs/heads/bot/*` only via a |
| 67 | + GitHub App installation token rather than a long-lived PAT. |
| 68 | + |
| 69 | +## Verdict |
| 70 | + |
| 71 | +`request-changes` — the security model is mostly sound, but the |
| 72 | +critique-result semantics flip needs an explicit comment in the |
| 73 | +diff, the comment-step `if:` guard should be restored, and the |
| 74 | +unconditional fall-through when both `gh issue view` and `gh pr view` |
| 75 | +fail needs to abort. The PAT-vs-App-token discussion is a separate |
| 76 | +follow-up but worth raising before this lands. |
0 commit comments