Skip to main content
nono uses kernel-enforced sandboxing instead of application-level controls. This page explains why this architectural choice provides fundamentally stronger security guarantees.

The Problem with Application-Level Controls

Many AI agent frameworks implement their own permission systems:
This approach has a fatal flaw: the agent can bypass it.

Why Application Controls Fail

  1. The agent controls the runtime
    • The agent can modify its own code
    • It can call system APIs directly
    • It can ignore the permission checks entirely
  2. No enforcement boundary
    • Application controls are just code running in the same process
    • A compromised or malicious agent has full access to everything
  3. Single point of failure
    • One bug in the permission system = complete bypass
    • The agent can probe for and exploit these bugs

How OS-Level Enforcement Differs

Key Differences

1. Irreversibility

Application controls: Can be modified or disabled at runtime
OS-level (nono): Cannot be modified after application

2. Enforcement Authority

Application controls: Enforced by code the agent can modify OS-level (nono): Enforced by the kernel
  • Agent cannot modify kernel code (without a kernel exploit)
  • System calls are intercepted before they can succeed
  • The agent never gains unauthorized access, even momentarily

3. Process Inheritance

Application controls: Child processes may not inherit restrictions
OS-level (nono): All child processes inherit restrictions

4. Attack Surface

Application controls: Every permission check is an attack vector
OS-level (nono): Kernel implementation is battle-tested
  • Landlock and Seatbelt handle edge cases
  • Symlink resolution is done correctly
  • TOCTOU windows are minimized or eliminated
  • Implemented by kernel security experts

Comparison Table

* Requires kernel exploit to bypass

Real-World Implications

Scenario: Malicious Dependency

Your agent loads a compromised npm package: With application controls:
With nono:

Scenario: Prompt Injection

An agent is tricked via prompt injection to exfiltrate secrets: With application controls:
With nono:

Scenario: Agent Self-Modification

Agent tries to remove its own restrictions: With application controls:
With nono:

When Application Controls Are Acceptable

Application-level controls still have uses:
  1. UX improvement - Provide helpful error messages before hitting kernel denial
  2. Auditing - Log what the agent intended to do
  3. Rate limiting - Throttle API calls (not a security boundary)
  4. Defense in depth - Additional layer on top of OS controls
But they should never be the primary security boundary for untrusted code.

Summary

nono chooses OS-level enforcement because the agent is untrusted by definition. Any security model that relies on the agent cooperating with restrictions is fundamentally broken. The kernel doesn’t care what the agent wants. It enforces the rules regardless.