Why Cairn
Finding bugs is getting cheap. Fixing them for good isn't.
The same root cause comes back in another file, another service, another quarter. AI coding agents now repeat old mistakes faster than reviewers can catch them. Cairn keeps what your team has learned as lessons: small, readable files holding a rule and the evidence that it works.
No proof, no enforcement
A lesson is accepted only if its rule matches the vulnerable code and stays silent on the fix.
Plain YAML, in your repo
Rules use the Opengrep and Semgrep language. Read every line, and share packs between teams.
Runs on your machine
Bring any model, including a local one. Nothing is sent anywhere unless you set it up to be.
/how
One fix, stacked into memory
A cairn is a pile of stones that marks the path for whoever comes next. Each fix you make becomes one more stone.
Fix
You merge a focused security fix, as you do today.
git commitLearn
Cairn reads the before and after, and drafts a rule.
cairn learnProve
The rule must catch the bug and stay silent on the fix, or it's retried.
differential testHunt
The new lesson searches the codebase for siblings the fix missed.
cairn huntGuard
A person approves it. From then on it blocks the pattern on every PR.
cairn check
How a lesson is proven
It has to catch the bug, and leave the fix alone
This is Cairn's own starter lesson for an insecure direct object reference: any logged-in user can read anyone's invoice by changing the number in the URL.
@bp.get("/api/invoices/<int:invoice_id>")@login_requireddef get_invoice(invoice_id): invoice = Invoice.query.get_or_404(invoice_id) return jsonify(invoice.to_dict()) @bp.delete("/api/receipts/<int:receipt_id>")@login_requireddef delete_receipt(receipt_id): receipt = Receipt.query.get(receipt_id) receipt.delete()
@bp.get("/api/invoices/<int:invoice_id>")@login_requireddef get_invoice(invoice_id): invoice = Invoice.query.filter_by( id=invoice_id, owner_id=current_user.id ).first_or_404() return jsonify(invoice.to_dict()) # delete_receipt is scoped the same way
Fires near the lines the fix changed.
Doesn't fire on the patched code.
Stays under the false-positive budget.
Only approved lessons can fail CI.
/use
Where it runs
In your terminal
Type cairn in any project to scan it. Turn a fix into a lesson, or re-prove every lesson.
$ cairn $ cairn learn --commit <fix> $ cairn validate $ cairn doctor --fix # for scripts and CI
On every pull request
A GitHub Action that reports only what the PR introduces, so an existing codebase doesn't flood anyone.
# .github/workflows/cairn.yml
- uses: twomuchlabs/cairn@<sha>
- uses: github/codeql-action/
upload-sarif@<sha>
Inside your coding agent
A Claude Code plugin checks every edit the agent makes against your lessons, and blocks launching agents with safety checks off.
/plugin install cairn \
--marketplace TwoMuchLabs/cairn
hunt, check and validate need no model and no network. learn uses one: Anthropic (automatic if ANTHROPIC_API_KEY is set), any OpenAI-compatible API, or a local model through Ollama, so code never leaves your machine./quality
Measured in public, failures included
VariantBench runs Cairn on real security advisories whose fix was one focused commit. A third of the cases are held back and never used for tuning.
| What we measure | Bar to launch |
|---|---|
| Rule pass rateFixes that become a lesson passing the differential test | ≥ 40% |
| Sibling precisionReal problems among the siblings Cairn flags, checked by a person | ≥ 60% |
| Median attemptsModel answers needed for a passing lesson | ≤ 2 |
| Confirmed variantsReal siblings reported privately and confirmed by maintainers | ≥ 3 |
Measuring now. The first numbers ship with the first release.
Honest limits
What it doesn't do yet
- Rules follow data within a file, not across services.
learnworks best on focused fixes of 1–4 files. Broad refactors make poor lessons, so Cairn refuses them.- Fix generation and exploitability analysis are on the roadmap, not in this release.
Roadmap
The lesson loop
- Publish VariantBench numbers
- 100+ starter lessons
- Secret and dependency checks in the agent plugin
- Sessions with first-time users
Evidence
- Merge findings from other scanners
- Exploitability statements (OpenVEX)
- Validated single-file fixes
- Signed lessons
Scale
- Compliance evidence mapping
- Policies generated from lessons
- C and C++ support
- Org-wide lesson sharing
Get involved
Add a stone
Lessons are the most valuable contribution. Every one ships under Apache-2.0, and we will never relicense them.