Skip to content
Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Repository files navigation

MergeWarden for AI PRs

Release CI MergeWarden License

Which of these pull requests needs you first?

npx --yes mergewarden@0.9.0 triage <your owner/repository>
8 open pull request(s) read. 7 have something a maintainer checks by hand.

#169755  feature/openAQ           AI disclosed · no linked issue · oversized
#176410  unifiprotect-config-map  no linked issue · oversized
#177530  tod-support-sun-events   AI disclosed · no linked issue

Nothing was closed, labelled, or commented on.

Every row is a fact you can check: no linked issue, no description, a template kept empty, a change past your review size, a Co-authored-by: trailer a coding tool wrote about itself, a file edited outside the scope the pull request declared. Nothing scores a contributor, guesses from writing style, or closes anything — there is no --close flag, and a test asserts there never is. A pull request closed by a bot in error is not reopened by the person who gave up on it.

The same rules run as a GitHub Action. It does not execute pull-request code, load policy from the PR head, or call an LLM, and every finding carries deterministic evidence that replays locally.

MergeWarden gates its own pull requests — the MergeWarden badge above is that live self-check (how we dogfood).

Triage your repo · Try a public PR · Install the Action · What it catches · Adopt safely · Documentation · 简体中文

Try It in 60 Seconds

See every rule fire on a bundled example — no token, no repository, no network — then scan a real pull request, by owner/repo#number or by URL:

npx --yes mergewarden@0.9.0 demo
npx --yes mergewarden@0.9.0 scan owner/repository#123
npx --yes mergewarden@0.9.0 scan https://github.com/owner/repository/pull/123

The full mergewarden demo report scrolling past in a terminal

Use GH_TOKEN or GITHUB_TOKEN for private repositories or higher API rate limits. MergeWarden intentionally has no token command-line flag.

The default output is concise; --format json or --format markdown gives the complete machine-readable report (CLI reference).

Install in 30 Seconds

Create .github/workflows/mergewarden.yml:

name: MergeWarden

on:
  pull_request:
    types: [opened, synchronize, reopened, edited, labeled, unlabeled, ready_for_review]

permissions:
  contents: read
  pull-requests: write

jobs:
  mergewarden:
    runs-on: ubuntu-latest
    steps:
      - uses: sjh9714/mergewarden@v0.9.0
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          mode: warn
          fail-on-block: false
          comment: auto

No checkout step is needed, and MergeWarden does not publish or recommend a mutable v0 tag. For an immutable install, pin the exact v0.9.0 release commit:

- uses: sjh9714/mergewarden@e97f47b59dcda0eb48ba88275c176fc734325659

The first run works without mergewarden.yml: a confirmed 404 on the PR base branch selects the built-in warn policy. Authentication, rate-limit, and server errors never fall back silently.

What You'll See

Most agent pull requests cross no boundary, and those get a pass and no comment — comment: auto speaks only when there is an error or a warning. Everything else is recorded in the Actions job summary. When a boundary is crossed you get one comment:

ERROR contract/out-of-scope: src/billing/invoice.ts changed outside the allowed contract scope.

Push a fix and that same comment updates itself to PASSED. It is never deleted, so a stale "NEEDS REVIEW" cannot outlive the problem it described. Fork pull requests get a read-only token from GitHub and so are never commented on. New here? Start here is the one-page version.

What It Catches

Boundary Deterministic evidence
Declared PR scope Files outside allowed_paths or inside blocked_paths
Agent control plane Changes to AGENTS.md, CLAUDE.md, GEMINI.md, .mcp.json, .cursor/**
Agentic workflow injection Untrusted GitHub text flowing into registered agent prompts
Workflow privilege Permission escalation, new write-all or OIDC access
Dangerous triggers pull_request_target use of attacker-controlled PR head refs
Workflow supply chain Unpinned actions, reusable workflows, and containers
Package execution Added or changed install/prepare lifecycle scripts
Test evidence High-risk source changes without matching test-file changes
Analysis integrity Missing content, incomplete file lists, or report limits

MergeWarden evaluates changes rather than re-reporting every pre-existing workflow condition. Findings show the rule, severity, path, canonical evidence, and a stable finding ID.

Or Check It Before the PR Exists

The same engine ships as an MCP server, for the person running the agent rather than the maintainer reviewing it. It answers one question — did this change stay inside the scope it was given — and emits the contract block the gate reads later.

{ "mcpServers": { "mergewarden": { "command": "npx", "args": ["-y", "mergewarden-mcp"] } } }

No network, no token, no model call (details).

What 2,204 Real Agent PRs Showed

We scanned 2,204 recently merged AI-agent pull requests (Devin, Copilot coding agent, Codex, Claude Code, Cursor) on public repositories with the default policy. 0 of 2,204 declared their intended scope in any machine-checkable form. Of the 349 that touched workflows or package manifests, 12.9% escalated workflow permissions and 17.5% introduced unpinned actions; 3.9% changed agent control-plane files. Repositories with 10k+ stars showed roughly half the boundary-crossing rate of the long tail.

Every number reproduces from published queries: study methodology.

Minimal Policy

Already have an AI-contribution policy (Apache / OpenSSF / Bitcoin Core lineage)? The ai-contribution-policy.yml preset enforces its checkable clauses in one copy-paste — see Enforce a policy. Or add mergewarden.yml to the base branch when you are ready to tune behavior:

version: 1
mode: warn

agent_detection:
  labels: [ai, agent, codex, claude]
  branch_patterns: ["codex/**", "claude/**", "ai/**"]

github_actions:
  checks:
    permission_escalation: error
    write_all: error
    id_token_write: warn
    pull_request_target_head: error
    unpinned_action: warn
    unpinned_reusable_workflow: warn
    unpinned_container: warn
    missing_permissions: warn
    unknown_write_permission: warn
    added_secret_reference: warn
    workflow_deleted: warn
    malformed_workflow: error

high_risk_paths:
  authentication:
    paths: ["src/auth/**"]
    require_tests: ["test/auth/**"]
    severity: error

For an agent-authored PR, the body can declare its intended scope:

<!-- mergewarden-contract
version: 1
agent: codex
task: update session expiry handling
allowed_paths:
  - src/auth/**
  - test/auth/**
-->

The contract is an untrusted PR declaration, not proof that the task or author is legitimate. The base-branch policy remains authoritative.

Time-Bounded Waivers

After reviewing a finding, maintainers can waive that exact evidence from the trusted base policy:

waivers:
  - finding_id: agf_0123456789abcdef
    reason: Approved OIDC release workflow
    expires_at: "2026-09-30T00:00:00Z"

Waived findings remain visible. Expired waivers reactivate the original finding and emit policy/waiver-expired. Analysis-integrity findings cannot be waived.

See the complete configuration reference.

Adopt Safely

  1. Start with mode: observe or mode: warn and fail-on-block: false.
  2. Review findings and tune per-check severity.
  3. Add narrow, expiring waivers only after human review.
  4. Move stable policy to mode: block.
  5. Set fail-on-block: true and require the check in branch protection.

Human report labels are deliberately distinct:

  • PASSED: analysis completed with no active warning/error findings.
  • OBSERVED FINDINGS: observe mode found evidence without changing the pass decision.
  • NEEDS REVIEW: warn mode requires a human decision.
  • BLOCKED: block mode rejected active policy findings.
  • ANALYSIS INCOMPLETE: MergeWarden could not make a trustworthy decision and fails closed.

Trust Boundary

The GitHub Action:

  • reads PR metadata and file contents through GitHub APIs only
  • loads configuration from the exact base commit
  • never checks out or executes PR-controlled code
  • never evaluates GitHub expressions from workflow YAML
  • never calls an LLM during analysis
  • limits API concurrency, content to 1 MiB per file side and 64 MiB per run, findings, and rendered report size
  • records base/head SHAs, policy digest, analyzed file counts, and engine version

The pull-request files API has a 3,000-file maximum. MergeWarden compares the authoritative PR file count with the collected list and fails closed instead of presenting a partial pass.

Read the full security model and evidence model.

MergeWarden Is Not a Workflow Linter

Workflow linters such as zizmor inspect workflow correctness and known misconfigurations. LLM reviewers apply semantic judgment. MergeWarden is the change-control layer between an AI-generated PR and merge: it asks whether the PR crossed repository-specific boundaries and records why. Use all three when appropriate; they solve different problems.

Action Outputs

Every input and output, and the exact failure behavior, is in the Action reference.

Development

pnpm install
pnpm test && pnpm typecheck && pnpm lint && pnpm build && pnpm format:check

Every rule requires passing and failing fixtures, exact rule/severity/decision assertions, and a Markdown snapshot for user-facing findings. Start with a good first issue — each names its file, verify command, and done criteria — or the contribution guide.

Documentation

Will it be noisy? It said nothing on 44 of 46 merged human PRs; both findings were correct. If it flags one your team decided was fine, open an issue with the scan output — the most useful bug report this project can get.

License

MIT

About

Triage the pull requests you didn't write. Reads your open PRs and reports what each is missing — deterministic, evidence-cited, and it never closes anything.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages