{"id":51224780,"url":"https://github.com/saagpatel/agent-permission-diff-bot","last_synced_at":"2026-06-28T10:03:10.474Z","repository":{"id":366100094,"uuid":"1275040618","full_name":"saagpatel/agent-permission-diff-bot","owner":"saagpatel","description":"Detect and explain agent-facing permission changes in pull requests.","archived":false,"fork":false,"pushed_at":"2026-06-20T08:17:57.000Z","size":116,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-20T09:22:24.778Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/saagpatel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-20T07:09:31.000Z","updated_at":"2026-06-20T08:17:53.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/saagpatel/agent-permission-diff-bot","commit_stats":null,"previous_names":["saagpatel/agent-permission-diff-bot"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/saagpatel/agent-permission-diff-bot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fagent-permission-diff-bot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fagent-permission-diff-bot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fagent-permission-diff-bot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fagent-permission-diff-bot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/saagpatel","download_url":"https://codeload.github.com/saagpatel/agent-permission-diff-bot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fagent-permission-diff-bot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34884278,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-28T02:00:05.809Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-28T10:03:09.644Z","updated_at":"2026-06-28T10:03:10.467Z","avatar_url":"https://github.com/saagpatel.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Agent Permission Diff Bot\n\n[![CI](https://github.com/saagpatel/agent-permission-diff-bot/actions/workflows/ci.yml/badge.svg)](https://github.com/saagpatel/agent-permission-diff-bot/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n\nAgent Permission Diff Bot detects and explains changes to agent-facing permissions in\npull requests. It is a semantic correlator, not just a config linter: the useful signal is\nwhen a PR changes what an agent can read, write, deploy, reach, or trust.\n\nThe first dogfood target is local CLI usage against Git refs or two checked-out trees,\nwith a composite GitHub Action for pull request scanning.\n\n## Current Surfaces\n\n- MCP and Copilot MCP config: `mcpServers`, `tools`, `env`, `headers`, `url`, `command`,\n  and launch args.\n- GitHub Actions: token permissions, OIDC, runner labels, trigger context, environments,\n  secrets/env references, and deploy/publish actions.\n- Egress policy: `allow_hosts`, `allow_connectors`, `network_name_globs`, and related\n  policy keys.\n- Agent instructions: `AGENTS.md`, `CLAUDE.md`, Copilot instructions, Cursor rules, and\n  Windsurf rules.\n\n## Installation\n\n**Python \u003e= 3.11 required.**\n\nInstall directly from GitHub (no PyPI release yet):\n\n```bash\npip install git+https://github.com/saagpatel/agent-permission-diff-bot.git@v0.4.0\n```\n\nOr pin to a specific tag for reproducible installs:\n\n```bash\npip install \"git+https://github.com/saagpatel/agent-permission-diff-bot.git@v0.4.0\"\n```\n\n## Usage\n\nCompare two Git refs:\n\n```bash\nagent-permission-diff diff --repo . --base-ref origin/main --head-ref HEAD\n```\n\nCompare two directories:\n\n```bash\nagent-permission-diff diff --base-dir /tmp/base --head-dir /tmp/head --markdown report.md\n```\n\nEmit machine-readable output:\n\n```bash\nagent-permission-diff diff \\\n  --repo . \\\n  --base-ref origin/main \\\n  --head-ref HEAD \\\n  --json report.json \\\n  --sarif report.sarif\n```\n\nGate modes:\n\n- `observe`: records whether the threshold was met but always exits 0.\n- `warn`: exits 2 when findings meet `--fail-on`; intended for soft rollout checks.\n- `enforce`: exits 2 when findings meet `--fail-on`; intended for required checks.\n\nDefault gate threshold is `critical`.\n\nJSON and Markdown reports include the evaluated gate decision: mode, `fail_on`,\nwhether the threshold was met, status, exit code, and reason. The composite Action also\nexposes `gate-status` and `gate-threshold-met` outputs for workflow wiring.\n\nAcknowledgement policy:\n\n```yaml\nacknowledgements:\n  - rule_id: APD001\n    paths:\n      - .github/workflows/agent-runner.yml\n    reason: Self-hosted runner is protected by repository-only triggers and runner groups.\n    expires: \"2026-12-31\"\n```\n\nPass the file with `--policy .agent-permission-diff.yml` or the Action `policy` input.\nAcknowledged findings stay visible in JSON, Markdown, SARIF, and PR comments, but are\nexcluded from gate decisions. Each acknowledgement must match the finding rule and all\nfinding paths; expired acknowledgements are ignored.\n\n## GitHub Action\n\nThe composite action expects the repository to be checked out with enough history to\ncompare the base and head refs.\n\n```yaml\npermissions:\n  contents: read\n  security-events: write # only needed when upload-sarif is true\n\nsteps:\n  - uses: actions/checkout@v7\n    with:\n      fetch-depth: 0\n\n  - uses: saagpatel/agent-permission-diff-bot@v0.4.0\n    with:\n      mode: observe\n      upload-sarif: \"false\"\n```\n\nTo also create or update a sticky pull request comment, opt in with `comment: \"true\"`\nand grant `issues: write` and `pull-requests: write` to the scanning job:\n\n```yaml\npermissions:\n  contents: read\n  issues: write # only needed when comment is true\n  pull-requests: write # needed by some PR comment runs\n\nsteps:\n  - uses: actions/checkout@v7\n    with:\n      fetch-depth: 0\n\n  - uses: saagpatel/agent-permission-diff-bot@v0.4.0\n    with:\n      mode: observe\n      comment: \"true\"\n      upload-sarif: \"false\"\n```\n\nThe action preserves the scanner exit code if PR commenting fails, and emits a workflow\nwarning instead of masking the permission-diff result.\n\n## Action Inputs\n\n| Input | Required | Default | Description |\n|---|---|---|---|\n| `base-ref` | No | `\"\"` | Base Git ref or SHA. Defaults to the pull request base SHA when available. |\n| `head-ref` | No | `\"\"` | Head Git ref or SHA. Defaults to the pull request head SHA or current SHA. |\n| `mode` | No | `observe` | Gate mode: `observe`, `warn`, or `enforce`. |\n| `fail-on` | No | `critical` | Minimum severity that exits 2 in `warn`/`enforce` mode. |\n| `policy` | No | `\"\"` | Optional YAML policy file containing acknowledgement entries. |\n| `json` | No | `agent-permission-diff.json` | JSON report output path. Empty string disables JSON output. |\n| `sarif` | No | `agent-permission-diff.sarif` | SARIF 2.1.0 output path. Empty string disables SARIF output. |\n| `markdown` | No | `\"\"` | Markdown report output path. Empty string disables Markdown artifact output. |\n| `step-summary` | No | `\"true\"` | Append the Markdown report to the GitHub Actions step summary. |\n| `comment` | No | `\"false\"` | Create or update a sticky pull request comment with the Markdown report. Requires `issues: write` and may require `pull-requests: write`. |\n| `upload-sarif` | No | `\"false\"` | Upload SARIF to GitHub code scanning. Requires `security-events: write`. |\n| `working-directory` | No | `\".\"` | Repository working directory to scan. |\n\n## Action Outputs\n\n| Output | Description |\n|---|---|\n| `json-file` | Path to the JSON report. |\n| `sarif-file` | Path to the SARIF report. |\n| `markdown-file` | Path to the Markdown report. |\n| `exit-code` | `agent-permission-diff` exit code. |\n| `max-severity` | Maximum finding severity from the JSON report. |\n| `findings-count` | Number of findings from the JSON report. |\n| `gate-status` | Gate decision status: `observe`, `pass`, `warn`, or `fail`. |\n| `gate-threshold-met` | Whether the maximum finding severity met the `fail-on` threshold. |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaagpatel%2Fagent-permission-diff-bot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsaagpatel%2Fagent-permission-diff-bot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaagpatel%2Fagent-permission-diff-bot/lists"}