carabiner makes any repository secure by default, keeps it that way with a ratchet that only turns one way, and then attacks your own defences to prove they actually fire.
gitleaks, Trivy, Semgrep, OSV-Scanner are excellent and free. carabiner reimplements none of them. It fixes the three reasons the median repository still runs nothing.
Securing one repo means five READMEs and four config files. A two-hour job you do once and never repeat — so it never happens on repo number two.
Point any scanner at a codebase older than a year and it buries you in findings about code nobody has touched since. The gate gets switched off, and now the tool has negative value — it looks like coverage.
The config is perfect and nothing runs. Invisible to every static checker, including this one — the only way to know is to plant a credential and watch what happens.
The mechanism that makes this installable in a ten-year-old repo on a Tuesday afternoon.
carabiner init runs everything once and records every existing
finding as accepted. Your build goes green immediately.carabiner debt, with the
date it was taken on. It is recorded, not deleted.Everything else reads files. The drill reads outcomes — it plants a private key, runs your installed hooks against it, and asks GitHub whether your protections are switched on at all.
$ carabiner drill HIGH DRILL002 pre-commit hooks are configured but NOT installed — the config looks right and nothing runs fix: run `pre-commit install`; until then every hook in that file is decorative HIGH DRILL013 the default branch 'main' has no protection rule — CI cannot gate what can be pushed to directly 2 new 1.53s
A drill that could not run never
reports as passing. No token, no network, no pre-commit binary all produce
“could NOT be verified”, not a green check. Unverified is not secure — and a green check you
did not earn is worse than no check at all.
Findings land in your PR’s Security tab, tracked across commits by the same fingerprint the ratchet uses.
permissions: contents: read security-events: write steps: - uses: actions/checkout@v4 - uses: MaXiMo000/carabiner@v0.2.1 - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: carabiner.sarif
repos: - repo: https://github.com/MaXiMo000/carabiner rev: v0.2.1 hooks: - id: carabiner # the fast path is budgeted under 2s — anything slower # gets uninstalled from pre-commit inside a week
$ pip install carabiner-sec $ carabiner init # detect, configure, ratchet. once per repo. $ carabiner scan # what is new. pre-commit and CI. $ carabiner drill # prove the controls fire. $ carabiner debt # what you carry, and since when.
A missing scanner degrades to an install hint. A scanner that fails produces a finding saying the check did not happen — a tool that errors is not a repo that is clean.
| Engine | Checks | Needs |
|---|---|---|
| ci · Actions | pull_request_target with a PR-head checkout · script injection from
github.event into run: · unpinned actions · token blast radius ·
self-hosted runners | nothing |
| ci · GitLab | script injection from a merge-request title or branch name · unpinned remote
include: · mutable image and service tags | nothing |
| repo | .gitignore gaps · committed key material · missing disclosure policy ·
credentials embedded in git remotes | nothing |
| secrets | working tree every commit; history behind --all and one severity higher,
because deleting the file is not remediation | gitleaks |
| deps | lockfile advisories across PyPI, npm, Go, Maven, crates.io and more — ids normalised to CVE so two scanners cannot report one problem twice | osv-scanner |