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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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