Capa

A programming language where every function declares what it is allowed to do.

Capability-based security with a pythonic syntax. Designed for the era of supply-chain attacks and the EU Cyber Resilience Act.

v0.4.0-alpha · MIT · 536 tests · hand-written compiler in Python

v0.4.0-alpha Released 2026-05-12. Doc comments + --doc HTML generator, per-call data-flow tracking in the manifest, custom domain live with HTTPS. Read the notes →

Authority is explicit

If a function can touch the network, the filesystem, the environment, or any other system resource, it has to say so in its signature. There is no ambient permission.

fun fetch(net: Net, url: String)
    return net.get(url)

fun pure_thing(x: Int) -> Int
    // no caps: cannot do IO.
    return x * 2

Capabilities can be narrowed

A capability is not all-or-nothing. Net.restrict_to(host) returns a fresh Net with authority limited to one host. Restrictions only narrow, never widen.

fun main(net: Net)
    let api = net.restrict_to("api.example.com")
    // `api` can only reach api.example.com.
    fetch_users(api)

Libraries define their own

You declare your own capabilities, SendEmail, QueryDB, PublishMessage. The discipline applies uniformly. A library's contract is enforced at the type level.

capability SendEmail
    fun send(self,
        to: String,
        subject: String,
        body: String)
        -> Result<Unit, IoError>

Capa at a glance

Two functions and a main. The compiler rejects any attempt to fetch from a host other than api.example.com, because the attenuated Net is the only network authority anything downstream of main ever sees.

// A function that needs the network states it in its signature.
fun fetch_user(net: Net, id: String) -> Result<String, IoError>
    return net.get("https://api.example.com/users/${id}")

// A pure function declares no capabilities and cannot do IO.
// `net`, `stdio`, `fs`, `env` are not in scope; the compiler rejects
// any reference to them.
fun extract_email(payload: String) -> Option<String>
    ...

fun main(net: Net, stdio: Stdio)
    // Narrow the network capability before handing it onward.
    let api = net.restrict_to("api.example.com")
    match fetch_user(api, "42")
        Ok(body) -> stdio.println(body)
        Err(e)   -> stdio.eprintln("${e}")

Who builds with Capa

Library authors

When someone installs your library, they want to know what it can do, not trust your README. Capa puts the authority surface in the type signatures, so the contract is enforced at compile time.

Teams preparing for the EU CRA

The Cyber Resilience Act, applicable December 2027, requires machine-readable evidence of behavioural control. Capa produces it directly from the compiler: capability manifest, CycloneDX 1.5 SBOM, HTML doc page.

Researchers and academics

A working reference implementation of capability-based security with a pythonic surface. Hand-written compiler, formal EBNF grammar, complete white paper, MIT-licensed. Suitable as study material or as the substrate for further research.

Engineers tired of ambient authority

Every supply-chain incident of the last decade has the same shape: a dependency did something its API never claimed. Capa is the language where that claim is checked at compile time, not in production.

How Capa compares

A short matrix of properties that matter for supply-chain security and CRA-style audit. Honest on alpha status.

Property Python TypeScript Rust Capa
Ambient authority full full limited none
Effects in the type system no no Send/Sync only yes
Capability attenuation no no no yes (5 built-in caps)
Audit artefact from compiler no no no manifest + SBOM + HTML docs
Static rejection of unintended IO no no partial yes
Production maturity mature mature mature alpha

Capa is not a replacement for Rust or Python. It is a different slice through the language design space, focused on encoding effect surfaces explicitly. Rust and Capa are orthogonal: one prevents memory errors, the other prevents effect errors. A future language could combine both.

Frequently asked

Is Capa production-ready?

No. v0.4.0-alpha means the compiler runs, the discipline is implemented end-to-end, 536 tests pass on three operating systems and three Python versions, and the artefacts the language emits (manifest, CycloneDX, HTML docs) are real. But the language surface can still change between minor versions, and tooling that a team needs day-to-day (language server, formatter, native backend) is not there yet. Use Capa for prototypes, research, security demos, or as a study substrate, not yet as a production runtime.

How does Capa compare to Rust?

Different problem. Rust prevents memory errors via ownership and borrowing; Capa prevents effect errors via capabilities. They are orthogonal: you can imagine a future "Rust with capabilities" or "Capa with linear types". Today, the discipline Capa enforces is not expressible in idiomatic Rust without a lot of newtype scaffolding, and Rust's memory guarantees are not enforced by Capa.

Can I use my Python libraries from Capa?

Yes, through the Unsafe capability and the py_import / py_invoke builtins. Crossing into Python loses Capa's guarantees (Python has ambient authority), but the boundary is explicit: a function that uses Python interop must declare unsafe: Unsafe in its parameter list. The manifest flags every such function with has_unsafe: true for separate audit.

Why does the compiler target Python?

Speed of development. Capa is research-quality software; binding the transpiler output to Python let the capability discipline be implemented in weeks instead of years, with full access to a mature runtime, package ecosystem, and tooling. A native LLVM backend is in the long-term roadmap; until then, Capa programs are Python at runtime, with all the tradeoffs that implies.

Does Capa prevent supply-chain attacks?

It eliminates a specific class: attacks that depend on a dependency doing something its API never claimed. The 2018 event-stream incident exfiltrated cryptocurrency wallets from a function nominally limited to stream transformations; the walkthrough page shows the Capa version where the analyser rejects the attack at compile time. Capa does not prevent a dependency that legitimately needs Net from then misusing it; capability attenuation narrows that risk further but does not eliminate it.

Will Capa make my product CRA-compliant?

Capa is a tool, not a product, and compliance is at the product level. What Capa does is make the evidence trivial: every function's declared authority, attached audit metadata, and effective attenuation chain are emitted directly by the compiler as JSON (--manifest), CycloneDX 1.5 SBOM (--cyclonedx), and HTML (--doc). The Manifest page maps each CRA obligation to the manifest field that documents it.

What about performance?

Currently Capa programs run as transpiled Python on CPython, so the runtime characteristics are Python's. The capability checks add no runtime overhead; they are entirely compile-time, except for runtime gating on attenuated capabilities (e.g. Fs.read checking the path prefix before opening). A native backend is not in the v1 scope.

Is the language stable?

No. Pre-1.0 minor-version bumps may introduce breaking changes. The capability discipline itself (structural, flow, linear layers) is stable and unlikely to change. Surface syntax, the manifest schema, and the attribute catalogue may evolve. The CHANGELOG.md tracks every change.

Where to go next

Capa is in alpha. The compiler runs, 536 tests pass on three operating systems, and the three pillars of the discipline are implemented. There is still no language server, no module system, no native backend.