DEV Community

jaryn
jaryn

Posted on

"Treat Copilot Review Instructions as Untrusted Code"

A pull request changes .github/copilot-instructions.md, then asks Copilot to review the same branch. If the reviewer consumes instructions from the head branch, the author may be changing both the code under review and the rules used to review it. That is not automatically an exploit, but it is a trust-boundary crossing worth making visible.

GitHub's July 17 changelog says Copilot code review can use custom instructions from the head branch and documents setup plus firewall and runner controls. This is the relevant latest verified official signal, not a July 27 release. I rejected unverified secondary claims dated July 27 and found no reliable first-party update that supersedes it.

Draw the boundary before adding policy

Treat base-branch policy as trusted configuration and head-branch policy as proposed input:

base commit ── trusted review policy ───────┐
                                            ├─ policy gate ─ review
head commit ─ code + proposed instructions ┘
                         ^ untrusted together
Enter fullscreen mode Exit fullscreen mode

The invariant is narrow: a pull request cannot silently weaken the review policy applied to itself. It does not imply that GitHub's feature is unsafe, nor that Copilot will obey hostile text. The gate simply prevents an ambiguous authority path.

Use a small manifest owned on the default branch:

instruction_policy:
  protected_paths:
    - .github/copilot-instructions.md
    - .github/instructions/
  self_review: base_only
  required_reviewers: [platform-security]
  log_sha: true
Enter fullscreen mode Exit fullscreen mode

A CI check can compare changed paths and emit an evidence record. This is illustrative shell, not a claim about GitHub's implementation:

#!/usr/bin/env bash
set -euo pipefail
base="${BASE_SHA:?}"
head="${HEAD_SHA:?}"
changed=$(git diff --name-only "$base" "$head")

if grep -Eq '^\.github/(copilot-instructions\.md|instructions/)' <<<"$changed"; then
  printf '{"decision":"hold","base":"%s","head":"%s","reason":"review-policy-change"}\n' "$base" "$head"
  exit 42
fi
printf '{"decision":"allow","base":"%s","head":"%s"}\n' "$base" "$head"
Enter fullscreen mode Exit fullscreen mode

Exit 42 is a hold, not a failed review. Branch protection should require an independent owner to inspect the instruction diff, then rerun review under the accepted base policy or merge the policy separately before reviewing the code change.

Positive and negative fixtures

Fixture Changed files Expected decision Evidence
ordinary patch src/parser.ts allow base/head SHA log
policy-only PR instruction file hold path and owner approval
mixed change instruction plus auth code hold no AI review used as gate
renamed policy path old and new path hold both diff entries retained
deleted instructions protected file deletion hold deletion status recorded

Normal path: a source-only PR passes the path check, review runs with the repository's accepted instructions, and the result remains advisory until normal human and deterministic checks finish.

Failure path: a mixed PR is held before customized review can satisfy a required check. The owner either splits the PR or approves the policy change independently. If the CI job cannot fetch the base SHA, fail closed and report policy_context_unavailable; do not quietly fall back to head instructions.

GitHub's firewall and runner controls constrain execution, not the authority of branch text. Keep deterministic checks outside this instruction channel.

Merge gate checklist

  • Pin base, head, and instruction blob SHAs in the review record.
  • Require CODEOWNERS or equivalent approval for every protected instruction path.
  • Re-request review after any policy or code revision.
  • Never let an AI review waive deterministic checks or human security approval.
  • Exercise missing-base, renamed-file, force-push, and runner-unavailable cases.
  • Retain enough evidence to explain why the gate allowed or held the revision.

This design cannot prove prompt-injection resistance, find every alternative instruction location, or validate the semantic quality of review guidance. Verify current documentation before enforcing paths; this design does not establish that an attack occurred.

A bounded MonkeyCode evaluation

After the repository-level gate is working, MonkeyCode can be considered separately as an open-source AGPL-3.0 AI development platform with an overseas online option, managed server-side cloud development environments, model/task/requirement management, and build/test/preview workflows. I have not tested those capabilities here. A sensible evaluation is to replay the positive and negative fixtures and require the same evidence boundary before considering its free-to-start option: evaluate through the official campaign.

Disclosure: This article promotes MonkeyCode using an official campaign link. I’m a MonkeyCode user, not affiliated with the project, and I receive no commission from this link.

AI assistance disclosure: This article was drafted with AI assistance and reviewed against the cited primary sources.

Top comments (0)