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