Content scanning

Inspect every push before a single byte reaches GitHub.

{
  "name": "acme/demo", "id": 1, "installationId": 2,
  "scan": {
    "secrets": true,
    "blockedPaths": [".github/workflows/", "*.pem"],
    "maxBlobBytes": 5242880,
    "allowlist": [{ "rule": "aws-access-key", "path": "docs/example.md" }]
  }
}

Options

secrets

Checks blob contents against built-in rules: private-key, github-token, aws-access-key, anthropic-key, openai-key, slack-token, gcp-service-account.

blockedPaths

Up to 100 plain-string patterns, ASCII case-insensitive:

PatternMatches
*.pemAny file ending in .pem, at any depth
dir/Everything below dir at the repository root
.envThat path, and that file name at any depth (not .env.example)
a/bThat exact path or anything below a/b/

maxBlobBytes

Blocks any new blob larger than the limit. With secrets on, it must be at most 10 MiB, and blobs over 10 MiB are always blocked because the rules can't read them.

allowlist

Up to 100 path-scoped exemptions for one rule (blocked-path, max-blob-bytes, or a secret rule id). The same content at another path is still blocked.

How it runs

The broker syncs a bare mirror of the repository, writes the push into a quarantine directory, indexes the pack against the mirror, and inspects every commit and blob the push adds — including earlier commits, merges, and root commits.

  • Clean: the quarantined bytes are forwarded.
  • Findings: 403 CONTENT_BLOCKED listing each finding's kind, rule, path, and 12-character commit. The matched value is never included.
  • Unreferenced objects: 403 UNSCANNABLE_OBJECT.
  • No mirror: 503 SCAN_UNAVAILABLE.

Findings can't be approved around. Rewrite history, or have an operator add a path-scoped allowlist entry.

Limits

Not a DLP guarantee

Rules are regexes. Encoded, compressed, encrypted, or split secrets get through. Scanning reduces accidental leaks and low-effort exfiltration; it doesn't stop a determined agent.

  • Only blob contents and paths are checked — not commit messages, author fields, ref names, or LFS objects.
  • Size the state volume for one full clone per scanned repository plus one push body per concurrent push.
  • An approval consumed by a blocked push stays spent. A failed mirror sync leaves it unspent for retry.