Summary
Add security checks to detect and block malicious PR attack vectors, inspired by recent GitHub supply-chain attacks where attackers hide payloads in collapsed diffs, inject trojan configs (.claude/, .vscode/), and tamper with automated PRs.
Problem
GitHub's UI collapses large diffs and generated files, allowing attackers to hide malicious code in PRs that appear clean at a glance. Additional attack vectors include:
- Trojan config directories —
.claude/settings.json with "command": "node .claude/setup.mjs" executes malware on clone
- CI/CD pipeline tampering — modifications to
.github/workflows/ can exfiltrate secrets
- PR tampering — attacker pushes commits on top of a bot's PR, changing the last committer identity
The webhook server already clones the repo and sees the full diff — no GitHub UI collapsing applies. We can inspect everything.
Proposed Solution
Three configurable security checks, all working at all 3 config levels (global config.yaml → per-repo in config.yaml → in-repo .github-webhook-server.yaml):
1. Suspicious Path Detection (new check run: security-suspicious-paths)
- Configurable list of path prefixes under
security-checks.suspicious-paths
- Default blocked paths:
.claude/ — AI agent trojan configs
.vscode/ — editor config injection
.cursor/ — AI editor config injection
.devcontainer/ — container config injection
.pi/ — pi agent config injection
.github/workflows/ — CI/CD pipeline tampering
.github/actions/ — CI/CD action tampering
- When a PR changes files matching any pattern → fail the check run with details of which files matched
- Users can extend or override the list at any config level
2. Committer Identity Check (new check run: security-committer-identity)
- Compare
last_committer vs parent_committer (PR author)
- When they differ → fail the check run with a warning identifying the unexpected committer
- Detects the MintMaker-style tampering pattern where an attacker pushes commits on top of a bot's automated PR
- Configurable:
security-checks.committer-identity-check: true (default: true)
3. Auto-Merge Override
- In
pull_request_handler.py auto-merge logic, after auto_merge = True is determined
- Check changed files against
suspicious-paths list
- If any match → set
auto_merge = False, post comment: "Auto-merge blocked: PR modifies security-sensitive paths: [list of matched files]"
- No new check run — just blocks the auto-merge decision
- Ensures PRs touching sensitive paths are NEVER auto-merged, even for
auto_verified_and_merged_users
Configuration
security-checks:
suspicious-paths: # list of path prefixes to flag
- ".claude/"
- ".vscode/"
- ".cursor/"
- ".devcontainer/"
- ".pi/"
- ".github/workflows/"
- ".github/actions/"
committer-identity-check: true # flag when last committer ≠ PR author (default: true)
Configurable at all 3 levels:
- Global —
config.yaml (server-level defaults for all repos)
- Per-repo —
config.yaml under repositories: section
- In-repo codebase —
.github-webhook-server.yaml in the repository itself
Files to Modify
webhook_server/config/schema.yaml — add security-checks schema
webhook_server/libs/github_api.py — read security-checks config in _repo_data_from_config()
webhook_server/libs/handlers/runner_handler.py — new run_security_checks() method
webhook_server/libs/handlers/pull_request_handler.py — integrate security checks in PR processing + auto-merge override
webhook_server/utils/constants.py — new check run name constants
webhook_server/tests/ — tests for all 3 checks
examples/.github-webhook-server.yaml — example config
Done
Summary
Add security checks to detect and block malicious PR attack vectors, inspired by recent GitHub supply-chain attacks where attackers hide payloads in collapsed diffs, inject trojan configs (
.claude/,.vscode/), and tamper with automated PRs.Problem
GitHub's UI collapses large diffs and generated files, allowing attackers to hide malicious code in PRs that appear clean at a glance. Additional attack vectors include:
.claude/settings.jsonwith"command": "node .claude/setup.mjs"executes malware on clone.github/workflows/can exfiltrate secretsThe webhook server already clones the repo and sees the full diff — no GitHub UI collapsing applies. We can inspect everything.
Proposed Solution
Three configurable security checks, all working at all 3 config levels (global
config.yaml→ per-repo inconfig.yaml→ in-repo.github-webhook-server.yaml):1. Suspicious Path Detection (new check run:
security-suspicious-paths)security-checks.suspicious-paths.claude/— AI agent trojan configs.vscode/— editor config injection.cursor/— AI editor config injection.devcontainer/— container config injection.pi/— pi agent config injection.github/workflows/— CI/CD pipeline tampering.github/actions/— CI/CD action tampering2. Committer Identity Check (new check run:
security-committer-identity)last_committervsparent_committer(PR author)security-checks.committer-identity-check: true(default:true)3. Auto-Merge Override
pull_request_handler.pyauto-merge logic, afterauto_merge = Trueis determinedsuspicious-pathslistauto_merge = False, post comment: "Auto-merge blocked: PR modifies security-sensitive paths: [list of matched files]"auto_verified_and_merged_usersConfiguration
Configurable at all 3 levels:
config.yaml(server-level defaults for all repos)config.yamlunderrepositories:section.github-webhook-server.yamlin the repository itselfFiles to Modify
webhook_server/config/schema.yaml— addsecurity-checksschemawebhook_server/libs/github_api.py— readsecurity-checksconfig in_repo_data_from_config()webhook_server/libs/handlers/runner_handler.py— newrun_security_checks()methodwebhook_server/libs/handlers/pull_request_handler.py— integrate security checks in PR processing + auto-merge overridewebhook_server/utils/constants.py— new check run name constantswebhook_server/tests/— tests for all 3 checksexamples/.github-webhook-server.yaml— example configDone
security-checksto config schema withsuspicious-pathsandcommitter-identity-check_repo_data_from_config()