Lab project 002 · pre-alpha · Apache-2.0

Security memory for your codebase.

Cairn turns every vulnerability you fix into a proven rule, finds the siblings you missed, and stops the same mistake coming back on every future pull request.

  1. 1
    pipx install git+https://github.com/twomuchlabs/cairn
  2. 2

    Open any project and type cairn. The first time, press Enter once to set up its engine. That's it.

The fix closed one hole. The lesson found the one next to it, and once a person approves it, it blocks that pattern on every pull request.

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.

01 · Proven

No proof, no enforcement

A lesson is accepted only if its rule matches the vulnerable code and stays silent on the fix.

02 · Open

Plain YAML, in your repo

Rules use the Opengrep and Semgrep language. Read every line, and share packs between teams.

03 · Yours

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.

  1. Fix

    You merge a focused security fix, as you do today.

    git commit
  2. Learn

    Cairn reads the before and after, and drafts a rule.

    cairn learn
  3. Prove

    The rule must catch the bug and stay silent on the fix, or it's retried.

    differential test
  4. Hunt

    The new lesson searches the codebase for siblings the fix missed.

    cairn hunt
  5. Guard

    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.

Before the fixrule must match
@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()
Both lookups trust the ID in the URL. The rule has to flag both.
After the fixrule must stay silent
@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
Each lookup is scoped to the current user. A rule that still fires here is too broad.
gate 1Matches the bug

Fires near the lines the fix changed.

gate 2Silent on the fix

Doesn't fire on the patched code.

gate 3Quiet on clean code

Stays under the false-positive budget.

thenA person approves

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
Models: 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.

200real advisories
4languages, 50 each
67held out, never tuned on
5starter lessons
What we measureBar 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.

Our own kill switch: if the pass rate stays below 30% or precision below 50%, the approach changes, not the prompt.

Honest limits

What it doesn't do yet

  • Rules follow data within a file, not across services.
  • learn works 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

now · 0–90 days

The lesson loop

  • Publish VariantBench numbers
  • 100+ starter lessons
  • Secret and dependency checks in the agent plugin
  • Sessions with first-time users
next · 3–6 months

Evidence

  • Merge findings from other scanners
  • Exploitability statements (OpenVEX)
  • Validated single-file fixes
  • Signed lessons
later · 6–12 months

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.