SKILL·3069E7

harden-github-repo-security

pjt222
Aktualisiert 7 days ago
26
3
26
Auf GitHub ansehen
Designautomationdesign

Über

Dieses Claude Skill wendet mehrschichtige Sicherheitsvorkehrungen für GitHub-Repositorys an, einschließlich Rulesets, Secret Scanning, Dependabot und Branch Protection. Es wurde entwickelt, um öffentliche Repos nach Audits abzusichern, Schutzmaßnahmen hinzuzufügen, ohne Automatisierung zu unterbrechen, und GitHub-App-Umgehungen für vertrauenswürdige Bots zu erstellen. Der Prozess ist verändernd und gestaffelt – zunächst werden Bewertungen vorgenommen, Basisschutzmaßnahmen angewendet und dann erforderliche Checks separat behandelt.

Schnellinstallation

Claude Code

Empfohlen
Primär
npx skills add pjt222/agent-almanac -a claude-code
Plugin-BefehlAlternativ
/plugin add https://github.com/pjt222/agent-almanac
Git CloneAlternativ
git clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/harden-github-repo-security

Kopieren Sie diesen Befehl und fügen Sie ihn in Claude Code ein, um diese Fähigkeit zu installieren

Dokumentation

Harden GitHub Repository Security

Apply GitHub protections in order of blast radius: assess, then a zero-downside baseline that never breaks CI, then a gated decision on required checks / PR. Every mutating step is confirmation-gated. Running example: a public, user-owned repo whose CI auto-commits to the default branch via stefanzweifel/git-auto-commit-action with the default GITHUB_TOKEN.

Throughout, R = OWNER/REPO (e.g. pjt222/agent-almanac). Set it once: R=OWNER/REPO. All gh api writes require repo admin.

When to Use

  • Hardening a public user-owned repo after assess-github-repo-security
  • A repo has no ruleset / branch protection and you want a safe baseline
  • Adding required status checks or required PR without breaking a bot that pushes to the default branch
  • Provisioning a GitHub App (or deploy key) bypass actor for trusted automation

Inputs

  • Required: OWNER/REPO and admin access (gh auth status shows admin)
  • Required: whether a CI bot pushes to the default branch (and which action/identity)
  • Optional: assessment report from assess-github-repo-security
  • Optional: exact CI check context name(s) to require (must run on push)
  • Optional: GitHub App id + private key if going to required checks/PR

Procedure

Step 1: Assess First and Confirm Scope

Never mutate blind. Run the read-only assessment and confirm the plan with the user.

# 1. Run the companion read-only skill first (or its core probes):
gh api /repos/$R --jq '{visibility,default_branch,is_org:.organization!=null}'
gh api /repos/$R/rulesets --jq '.[] | {id,name,enforcement}'
gh api /repos/$R/actions/permissions/workflow

# 2. Confirm the two decisive facts before any write:
#    - Is the repo PUBLIC and USER-OWNED?  (rulesets are free here)
#    - Does a bot push to the default branch?  (gates Step 3 entirely)

Confirm with the user: baseline (Step 2) is always safe; Step 3 (required checks / PR) is a separate opt-in that will block a default-branch bot unless a bypass is provisioned first.

Expected: You know visibility, owner type, current rulesets, current token default, and whether a bot pushes to the default branch. The user has approved applying at least the baseline.

On failure: If the repo is private and user-owned, rulesets need GitHub Pro — stop and surface that. If not admin, stop (writes will 403). If a bot pushes to the default branch, flag that Step 3 is blocked until Step 3a runs.

Step 2: Apply the Zero-Downside Baseline (never breaks a CI auto-commit)

This tier hardens the repo without breaking a direct-push bot. Apply after confirmation. Force-push/deletion protection, a read-only token default, the free security features, and policy files.

# 2a. Default-branch ruleset: force-push + deletion protection ONLY.
#     These do NOT block the bot's direct push.
gh api --method POST /repos/$R/rulesets --input - <<'JSON'
{
  "name": "protect-default",
  "target": "branch",
  "enforcement": "active",
  "conditions": { "ref_name": { "include": ["~DEFAULT_BRANCH"], "exclude": [] } },
  "rules": [ { "type": "deletion" }, { "type": "non_fast_forward" } ]
}
JSON

# 2b. Actions token: read-only default + no token PR approval.
#     A DEFAULT (not a cap) for same-repo push events, so the bot still works
#     once its job declares contents: write.
gh api --method PUT /repos/$R/actions/permissions/workflow \
  -f default_workflow_permissions=read \
  -F can_approve_pull_request_reviews=false

# 2c. Free security features (all free on public repos):
gh api -X PUT repos/$R/vulnerability-alerts          # alerts + dependency graph
gh api -X PUT repos/$R/automated-security-fixes      # Dependabot fix PRs (separate toggle!)
gh api -X PATCH repos/$R --input - <<'JSON'
{"security_and_analysis":{"secret_scanning":{"status":"enabled"},"secret_scanning_push_protection":{"status":"enabled"}}}
JSON
gh api -X PUT repos/$R/private-vulnerability-reporting

Leave Settings > Actions > General fork-PR approval at the public-repo default ("Require approval for first-time contributors"). Fork pull_request runs already receive a read-only GITHUB_TOKEN with no access to secrets, so a fork cannot auto-commit to the default branch (no REST toggle — this is a UI setting; tighten to "all external contributors" only if the repo has secrets or self-hosted runners).

Then add two tracked files (commit them):

.github/dependabot.yml — include a github-actions block so action SHAs stay fresh:

version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"

.github/SECURITY.md — a short disclosure policy pointing reporters at the "Report a vulnerability" button (private vulnerability reporting, enabled above).

Flipping the token default to read silently strips write from every workflow that assumed a write default, not just the auto-commit job. Audit all files in .github/workflows/ and declare the minimal permissions: each job actually needs — common scopes are contents, packages, pull-requests, pages, and id-token. For the running example: top-level permissions: {}, contents: write only on the auto-commit job, and every uses: pinned to a full 40-char commit SHA with the version in a trailing comment.

Expected: gh api /repos/$R/rulesets shows protect-default active; .../actions/permissions/workflow shows default_workflow_permissions: read and can_approve_pull_request_reviews: false; secret scanning + push protection

  • Dependabot + private reporting are on; .github/dependabot.yml and .github/SECURITY.md are committed. The bot's next run still pushes.

On failure: If 2b makes an existing bot push 403 — or any other workflow fails after losing a write scope it silently relied on — the job is missing the explicit permissions: it needs (e.g. contents: write, packages: write, pull-requests: write); add the minimal scope back (the read-only default is not a hard cap for same-repo pushes). If automated-security-fixes seems to do nothing, verify vulnerability-alerts (2c line 1) ran first — alerts are a separate prerequisite toggle from fixes. If push protection later fails a bot run, treat the flagged secret as a real finding — the bot cannot click the interactive web bypass.

Step 3: Decision Gate — Required Status Checks / Required PR

STOP. Required checks and required PR block direct pushes to the ref, not just PR merges. If a bot pushes to the default branch, turning either on will break it unless you first provision a bypass. The default GITHUB_TOKEN / github-actions[bot] cannot be a bypass actor (GitHub design). Do not enable this tier on a bot-pushing branch without a bypass in place.

Also, on a solo repo, required_approving_review_count >= 1 is a self-lockout (you cannot approve your own PR) — keep it 0. And a required check that only runs on pull_request never reports on a direct push, so it permanently blocks the bot. Ensure the check runs on push.

Step 3a — provision the bot bypass FIRST (if a bot pushes to this branch). Recommended: a GitHub App installation token. (Deploy key is a narrower single-repo alternative: add an SSH deploy key with write access and use actor_type: DeployKey in 3b.)

# Create a GitHub App (personal account, Settings > Developer settings >
# GitHub Apps), permission Repository > Contents: Read and write; install it
# on THIS repo. Store the App id as a repo variable and the private key as an
# Actions secret. In the workflow, mint a token and pass it to checkout + the
# commit action:
#   - uses: actions/create-github-app-token@<sha>   # v2
#     id: app-token
#     with: { app-id: ${{ vars.APP_ID }}, private-key: ${{ secrets.APP_KEY }} }
#   - uses: actions/checkout@<sha>
#     with: { token: ${{ steps.app-token.outputs.token }} }
#   - uses: stefanzweifel/git-auto-commit-action@<sha>
#     with: { ... }   # inherits the app token via the checkout credentials
#
# The numeric App id used in Step 3b is shown on the App's own page:
# Settings > Developer settings > GitHub Apps > <your app> > About ("App ID").
# It is unrelated to the repository id and cannot be derived from /repos/$R.

Higher-assurance alternative (no standing bypass actor). If a manual merge click is acceptable, convert the job to open a PR with the App token (e.g. peter-evans/create-pull-request) and let a human merge. No bypass actor is needed and every rule stays enforced even against the automation's identity. The App token is still required: a PR opened with the plain GITHUB_TOKEN does not trigger pull_request/push workflows, so required checks never run and it sits expected forever (see Common Pitfalls).

Step 3b — apply the hardened ruleset with the App as an Integration bypass actor. Replace RULESET_ID with the id from Step 2a, <APP_ID> with your App id, and build with your real check context. bypass_mode: always because the action pushes directly (use pull_request only if the bot opens PRs).

gh api --method PUT /repos/$R/rulesets/RULESET_ID --input - <<'JSON'
{
  "name": "protect-default",
  "target": "branch",
  "enforcement": "active",
  "conditions": { "ref_name": { "include": ["~DEFAULT_BRANCH"], "exclude": [] } },
  "bypass_actors": [ { "actor_id": <APP_ID>, "actor_type": "Integration", "bypass_mode": "always" } ],
  "rules": [
    { "type": "deletion" },
    { "type": "non_fast_forward" },
    { "type": "pull_request", "parameters": { "required_approving_review_count": 0, "dismiss_stale_reviews_on_push": true, "require_code_owner_review": false, "require_last_push_approval": false, "required_review_thread_resolution": false, "allowed_merge_methods": ["merge"] } },
    { "type": "required_status_checks", "parameters": { "strict_required_status_checks_policy": true, "do_not_enforce_on_create": true, "required_status_checks": [ { "context": "build" } ] } }
  ]
}
JSON

# Verify the bypass actor is present:
gh api /repos/$R/rulesets/RULESET_ID --jq '.bypass_actors'

do_not_enforce_on_create: true avoids the new-branch catch-22 (CI can't have run on a branch that does not exist yet). If there is no bot on this branch, you may skip 3a and omit bypass_actors.

Trade-off: strict_required_status_checks_policy: true ("branch must be up to date") forces every open human PR to be re-updated each time the bot auto-commits to the default branch, and dismiss_stale_reviews_on_push: true compounds the churn — a chatty bot can make PRs perpetually unmergeable. On a frequently-auto-committed branch prefer strict_required_status_checks_policy: false (loose) unless up-to-date-before-merge is genuinely required.

Expected: The ruleset now enforces the required check and required-PR rule for humans and forks, .bypass_actors lists the App (Integration), and the bot's next run still lands on the default branch (via the App token). Humans must open a PR; the check must be green.

On failure: If the bot 403s after 3b, the App identity is not actually the bypass actor — confirm the workflow passes the App token to checkout (not just to the commit action) and that <APP_ID> in bypass_actors matches. If the bot's push sits expected/pending forever, the required check does not run on push — make it trigger on push or drop it from the required list. If the bypass-actor picker does not appear on your personal repo, the required-PR + auto-commit combination is unsatisfiable here; GitHub's workaround is a free org. If merges are blocked on a solo repo, required_approving_review_count is >= 1 — set it to 0.

Step 4: Optional Advanced Hardening

Apply individually, each still confirmation-gated. None of these are needed for the baseline; several have sharp edges.

# 4a. Tag ruleset — protect release tags (classic tag protection is deprecated):
gh api --method POST /repos/$R/rulesets --input - <<'JSON'
{ "name": "protect-tags", "target": "tag", "enforcement": "active",
  "conditions": { "ref_name": { "include": ["refs/tags/v*"], "exclude": [] } },
  "rules": [ { "type": "deletion" }, { "type": "non_fast_forward" } ] }
JSON

# 4b. Merge-method toggles (e.g. merge-commits-only to preserve per-commit history):
gh api -X PATCH repos/$R -F allow_merge_commit=true -F allow_squash_merge=false \
  -F allow_rebase_merge=false -F delete_branch_on_merge=true

# 4c. CodeQL "default setup" (server-managed — commits NO workflow YAML):
gh api -X PATCH repos/$R/code-scanning/default-setup -f state=configured -f query_suite=default

# 4d. sha_pinning_required — ONLY after every `uses:` is a full 40-char SHA,
#     or every workflow run fails (including actions/checkout):
gh api --method PUT /repos/$R/actions/permissions -F enabled=true \
  -f allowed_actions=selected -F sha_pinning_required=true
# selected mode also gates WHICH actions may run: github_owned covers actions/*,
# but git-auto-commit-action is NOT GitHub-owned — allow-list it in the SAME
# step or the bot fails with "actions are not allowed":
gh api --method PUT /repos/$R/actions/permissions/selected-actions \
  -F github_owned_allowed=true -F verified_allowed=false \
  -f 'patterns_allowed[]=stefanzweifel/git-auto-commit-action@*'
gh api /repos/$R/actions/permissions --jq '.sha_pinning_required'   # verify

Note: allowed_actions=selected with github_owned_allowed=true still blocks stefanzweifel/git-auto-commit-action until it is in patterns_allowed (the 4d allow-list command handles this). Require-signed-commits and require-linear-history are intentionally omitted here: signing blocks the unsigned git-CLI bot push, and linear history is mutually exclusive with a merge-commits-only policy.

Expected: Each selected advanced control is applied and verified without breaking the bot: tag ruleset lists on .../rulesets, merge toggles reflect on the repo object, CodeQL default setup shows state: configured, sha_pinning_required reads true only after all actions are SHA-pinned, and git-auto-commit-action is in patterns_allowed so the bot still runs.

On failure: If every workflow fails right after 4d, an action is still tag-pinned — convert all uses: to SHAs or revert sha_pinning_required to false. If the bot fails with "actions are not allowed" after restricting allowed actions, add git-auto-commit-action to patterns_allowed. If 4c errors, the repo may have no CodeQL-supported language — skip it.

Validation

  • Assessment ran and scope (public/user-owned, bot-on-default-branch) confirmed before any write
  • protect-default ruleset active with deletion + non_fast_forward
  • default_workflow_permissions=read and can_approve_pull_request_reviews=false
  • Secret scanning + push protection + Dependabot alerts + fixes + private reporting enabled
  • .github/dependabot.yml (github-actions ecosystem) and .github/SECURITY.md committed
  • Auto-commit bot's next run still pushes successfully (baseline did not break it)
  • Required checks/PR enabled ONLY with a GitHub App (or deploy key) bypass in place first
  • Solo repo keeps required_approving_review_count: 0; required checks run on push
  • Loop guard added if a bot now pushes with an App token or PAT

Common Pitfalls

  • GITHUB_TOKEN is not a bypass actor: github-actions[bot] / the default token cannot be added to any ruleset bypass list and cannot push to a protected branch, by design. "Just add the Actions bot to the bypass list" has no such option — the push 403s. Use a GitHub App or deploy key.
  • PAT bypass is an anti-pattern: an admin/personal PAT in the bypass list (or classic BP with enforce_admins=false) exempts ALL admin actions including your own interactive pushes — role-wide, not automation-scoped, and long-lived. Prefer an App (Integration) or deploy key (DeployKey).
  • Required checks only on pull_request: a check that never runs on push never reports on the bot's direct push, so it permanently blocks the bot and new-branch creation. Make the check run on push and set do_not_enforce_on_create: true.
  • Loop guard once an App token replaces GITHUB_TOKEN: the default token suppresses downstream push/pull_request triggers; an App token or PAT does not, so the auto-commit workflow can re-trigger itself indefinitely. Guard with if: github.actor != '<app>[bot]', paths-ignore, or [skip ci].
  • PR via the default GITHUB_TOKEN is a false fix: a PR opened by GITHUB_TOKEN does not trigger pull_request/push workflows, so required checks never run and it sits expected forever. Create the PR with the App token.
  • Alerts != fixes: vulnerability-alerts and automated-security-fixes are separate toggles; enabling alerts opens no PRs. Enable both.
  • Don't buy GHAS on a public repo: secret scanning, push protection, CodeQL, and dependency review are already free on public repos; the paid Secret Protection / Code Security products target private/org repos.

Related Skills

  • assess-github-repo-security - the read-only companion; always run this first
  • configure-git-repository - baseline .gitignore, branches, remotes, hooks
  • setup-github-actions-ci - the CI workflow whose token/permissions this hardens

GitHub Repository

pjt222/agent-almanac
Pfad: i18n/es/skills/harden-github-repo-security
0
agentsagentskillsai-assisted-developmentclaude-codeskillsteams
FAQ

Häufig gestellte Fragen

Was ist der Skill harden-github-repo-security?

harden-github-repo-security ist ein Claude Skill von pjt222. Skills bündeln Anweisungen und Ressourcen, die Claude bei Bedarf lädt, um Aufgaben rund um harden-github-repo-security ohne zusätzliche Eingaben auszuführen.

Wie installiere ich harden-github-repo-security?

Verwende die Installationsbefehle auf dieser Seite: Füge harden-github-repo-security als Plugin zu Claude Code hinzu oder klone das Repository in dein Skills-Verzeichnis. Starte Claude danach neu, damit der Skill geladen wird.

Zu welcher Kategorie gehört harden-github-repo-security?

harden-github-repo-security gehört zur Kategorie Design.

Kann ich harden-github-repo-security kostenlos nutzen?

Ja. harden-github-repo-security ist auf AIMCP gelistet und kann kostenlos installiert werden.

Verwandte Skills

executing-plans
Design

Verwenden Sie die Fähigkeit "executing-plans", wenn Sie einen vollständigen Implementierungsplan zur Ausführung in kontrollierten Batches mit Überprüfungspunkten vorliegen haben. Sie lädt den Plan und überprüft ihn kritisch, führt dann Aufgaben in kleinen Batches (standardmäßig 3 Aufgaben) aus und meldet den Fortschritt zwischen jedem Batch zur Überprüfung durch den Architekten. Dies gewährleistet eine systematische Implementierung mit integrierten Qualitätskontrollpunkten.

Skill ansehen
requesting-code-review
Design

Diese Fähigkeit sendet einen Unteragenten für Code-Review, um Codeänderungen anhand der Anforderungen zu analysieren, bevor fortgefahren wird. Sie sollte nach dem Abschließen von Aufgaben, der Implementierung größerer Funktionen oder vor dem Zusammenführen in den Hauptzweig verwendet werden. Die Überprüfung hilft dabei, Probleme frühzeitig zu erkennen, indem die aktuelle Implementierung mit dem ursprünglichen Plan verglichen wird.

Skill ansehen
connect-mcp-server
Design

Diese Fähigkeit bietet Entwicklern eine umfassende Anleitung, um MCP-Server über HTTP-, stdio- oder SSE-Transports mit Claude Code zu verbinden. Sie behandelt Installation, Konfiguration, Authentifizierung und Sicherheit für die Integration externer Dienste wie GitHub, Notion und benutzerdefinierter APIs. Nutzen Sie sie beim Einrichten von MCP-Integrationen, bei der Konfiguration externer Tools oder bei der Arbeit mit Claude's Model Context Protocol.

Skill ansehen
web-cli-teleport
Design

Diese Fähigkeit unterstützt Entwickler bei der Wahl zwischen Claude Code Web- und CLI-Schnittstellen basierend auf Aufgabenanalysen und ermöglicht nahtloses Session-Teleporting zwischen diesen Umgebungen. Sie optimiert den Workflow, indem sie den Sitzungsstatus und Kontext beim Wechsel zwischen Web, CLI oder Mobilgeräten verwaltet. Nutzen Sie sie für komplexe Projekte, die in verschiedenen Phasen unterschiedliche Werkzeuge erfordern.

Skill ansehen