Safeguard
Developer Tools•

How do I write a small evidence collector with the GitHub CLI?

A short shell script using gh api can pull branch protection, rulesets, code scanning alerts and artifact lists into dated files. Steps and caveats.

Safeguard Security Team
4 min read

A few lines of shell using the GitHub CLI can save branch protection settings, rulesets, code scanning alerts and artifact lists into a dated folder. The gh api command makes authenticated requests to any REST endpoint. Run it on a schedule, from a dedicated read-only identity, and never edit the output.

What gh api does

The GitHub CLI manual says gh api makes an authenticated HTTP request to the GitHub API and prints the response. The endpoint can be a REST path, or graphql for the GraphQL API. Placeholders for owner, repo and branch in the path are filled from the current repository or from the GH_REPO environment variable. The default method is GET, which is what an evidence collector needs.

Endpoints worth collecting

WhatREST path shape (from the REST documentation)
Branch protectionrepos, owner, repo, branches, branch, protection
Rulesetsrepos, owner, repo, rulesets
Code scanning alertsrepos, owner, repo, code-scanning, alerts
Code scanning analysesrepos, owner, repo, code-scanning, analyses
Workflow artifactsrepos, owner, repo, actions, artifacts
Organization repositoriesorgs, org, repos

The artifacts response includes created and expiry times and a digest per artifact, which is useful for proving a file was not changed.

A minimal script

#!/usr/bin/env bash
set -euo pipefail
ORG="your-org"
REPO="your-repo"
OUT="evidence/$(date -u +%Y-%m)/$REPO"
mkdir -p "$OUT"

gh api "repos/$ORG/$REPO/branches/main/protection" > "$OUT/branch-protection.json"
gh api "repos/$ORG/$REPO/rulesets" > "$OUT/rulesets.json"
gh api --paginate "repos/$ORG/$REPO/code-scanning/alerts?state=open" > "$OUT/code-scanning-open.json"
gh api "repos/$ORG/$REPO/actions/artifacts" > "$OUT/artifacts.json"

date -u +%Y-%m-%dT%H:%M:%SZ > "$OUT/collected-at.txt"
sha256sum "$OUT"/*.json > "$OUT/sha256.txt"

Adjust the branch name and loop over repositories listed from the organization endpoint. On macOS use shasum with the algorithm flag instead of sha256sum.

Steps to run it responsibly

  1. Create a machine user or app with read-only access to the repositories it needs. Do not use a personal token with admin rights.
  2. Store the token in your CI secret store.
  3. Schedule the script monthly in CI and commit nothing to the source repository. Push the output to a separate, restricted storage location.
  4. Log failures. A silent failure is a gap in your evidence that you find during the audit.
  5. Review the output once to confirm it contains what you expect. Some endpoints return an error when a feature is not enabled for a repository, and that error is useful evidence in itself.

Caveats

Branch protection returns an error for branches without a rule, and organizations using rulesets will see the settings under the rulesets endpoint instead. Collect both. Permissions differ by endpoint, so test each against a private repository.

Do not make the script smarter than it needs to be. Collection should be boring. Interpretation, such as "this setting meets the control", belongs to a person.

See also what to automate first.

Where Safeguard fits

Safeguard provides compliance and evidence automation along with SBOM and dependency scanning, so you do not have to script every source yourself. The free scan is a quick start.

Quick check

Does gh api need special flags for GET requests?

No. The manual says the default method is GET unless you add parameters or override it.

Should the script commit output to the code repository?

No. Store output in restricted storage so it stays separate from the code it describes.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.