Back to skill

Security audit

Branch Protection Auditor

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent branch-protection auditor, but its provided fix command can overwrite existing repository protections without preserving stronger controls or requiring a clear review step.

Install only if you will use it as an audit reference and review all generated commands before running them. Do not run the fix command as written on production repositories; first fetch existing branch-protection settings, preserve current status checks and restrictions, target the actual default branch, and require an explicit before-and-after review.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:107
Finding
Branch Protection Remediation Can Overwrite Stronger Existing Controls## Vulnerability Details **File Location**: `SKILL.md`, lines 107-115 **Vulnerability Type**: Unsafe replacement of security configuration **Risk Level**: High ### Vulnerable Code ```bash # Apply protection to a repo gh api -X PUT "repos/$REPO/branches/main/protection" \ -f required_pull_request_reviews='{"required_approving_review_count":2,"dismiss_stale_reviews":true,"require_code_owner_reviews":true}' \ -f required_status_checks='{"strict":true,"contexts":["ci/test","ci/lint"]}' \ -f enforce_admins=true \ -f restrictions=null \ -F allow_force_pushes=false \ -F allow_deletions=false ``` ### Technical Analysis The documented remediation uses an authenticated `PUT` request to replace branch-protection settings with a fixed template. It does not retrieve and merge the repository's existing configuration before making the change. In particular: - Existing required status-check contexts are replaced with only `ci/test` and `ci/lint`. - `restrictions=null` explicitly removes existing user, team, or application push restrictions. - The target branch is hard-coded as `main`, although the audit process discovers each repository's actual default branch. - The command lacks a preview, comparison, or confirmation step. - Repository-specific requirements are not preserved. A repository may already require stronger or additional checks, such as security scanning, integration tests, deployment approval, provenance verification, or organization-specific policy checks. Replacing those settings can weaken the repository despite the command being presented as a security fix. ### Attack Path 1. A repository has existing branch protection with organization-specific status checks or restricted push actors. 2. The audit report recommends applying the documented remediation. 3. An operator with repository administration privileges executes the generated `gh api -X PUT` command. 4. GitHub replaces the existin ...[truncated 1214 chars]
Remediation
## Remediation Suggestions 1. Retrieve the current branch-protection configuration before making any modification. 2. Use the repository's discovered default branch rather than hard-coding `main`. 3. Merge approved changes into the existing configuration instead of replacing all settings with a static template. 4. Preserve all existing required status-check contexts unless an authorized operator explicitly approves their removal. 5. Preserve existing push restrictions. Do not set `restrictions` to `null` unless broadening push access is an intentional, separately confirmed action. 6. Generate a before-and-after configuration diff and require explicit operator confirmation. 7. Validate that the configured status-check names exist in the target repository. 8. Use a correctly typed JSON request body and verify the resulting configuration with a follow-up API request. 9. Add a dry-run mode and process repositories individually so that an error cannot weaken protections across an entire organization. 10. Abort remediation if the existing configuration cannot be retrieved or parsed reliably.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:42
Finding
API and Parsing Failures Are Misreported as Missing Branch Protection## Vulnerability Details **File Location**: `SKILL.md`, lines 42-63 **Vulnerability Type**: Fail-open audit logic and improper exception handling **Risk Level**: Medium ### Vulnerable Code ```bash # For each repo, check branch protection gh api "repos/$REPO/branches/$DEFAULT_BRANCH/protection" 2>/dev/null | python3 -c " import json, sys try: p = json.load(sys.stdin) checks = { 'required_reviews': p.get('required_pull_request_reviews') is not None, 'min_reviewers': p.get('required_pull_request_reviews', {}).get('required_approving_review_count', 0), 'dismiss_stale': p.get('required_pull_request_reviews', {}).get('dismiss_stale_reviews', False), 'require_code_owner': p.get('required_pull_request_reviews', {}).get('require_code_owner_reviews', False), 'status_checks': p.get('required_status_checks') is not None, 'strict_checks': p.get('required_status_checks', {}).get('strict', False), 'enforce_admins': p.get('enforce_admins', {}).get('enabled', False), 'force_push': not p.get('allow_force_pushes', {}).get('enabled', True), 'deletions': not p.get('allow_deletions', {}).get('enabled', True), 'linear_history': p.get('required_linear_history', {}).get('enabled', False), 'signed_commits': p.get('required_signatures', {}).get('enabled', False), } for k, v in checks.items(): status = '✅' if v else '❌' print(f' {status} {k}: {v}') except: print(' ❌ NO PROTECTION RULES') " ``` ### Technical Analysis The audit suppresses all standard-error output from `gh api` and uses a bare Python `except` clause. Consequently, every failure encountered while reading or processing the response is classified as proof that no protection rules exist. The same output can be produced for materially different conditions, including: - An actual API response indicating that protection is absent. - ...[truncated 2067 chars]
Remediation
## Remediation Suggestions 1. Remove the blanket `2>/dev/null` redirection or capture diagnostics in a controlled audit log. 2. Check the exit status of `gh api` before attempting to parse its output. 3. Handle HTTP outcomes separately: - Treat a confirmed `404` for the branch-protection endpoint as absent protection where appropriate. - Treat `401` and `403` as authentication or authorization failures. - Treat `429` as rate limiting and retry with bounded backoff. - Treat transport and server errors as an unknown audit state. 4. Replace the bare `except` with narrow exception handlers such as `json.JSONDecodeError`, `KeyError`, and `TypeError`. 5. Report failures as `UNKNOWN — AUDIT FAILED`, not `NO PROTECTION RULES`. 6. Preserve the repository name, branch name, HTTP status, and sanitized error message in the report. 7. Do not generate or apply remediation for repositories whose audit state is unknown. 8. Validate `$REPO` and `$DEFAULT_BRANCH` before constructing the API endpoint. 9. Return a nonzero process status when any repository could not be audited, allowing automation to detect an incomplete scan. 10. Add tests covering absent protection, permission denial, malformed JSON, rate limiting, invalid branches, and network failures.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep

Static analysis

No suspicious patterns detected.