Principle of Least Authority (PoLA)
The Principle of Least Authority (PoLA) is the rule that every component should hold only the specific authority it needs to do its job, without broad permissions or ambient access to surrounding systems. Cosmonic applies this principle by default: every Wasm component starts with no authority at all and must be granted each capability explicitly through its workload manifest.
Origins of PoLA
Saltzer and Schroeder coined "least privilege" in their 1975 paper The Protection of Information in Computer Systems as one of eight design principles for secure systems. The version most security engineers learn today comes from later capability-systems research, where Mark Miller and colleagues tightened the principle from least privilege to least authority in Robust Composition (Miller, 2006).
Where privilege is what a principal can invoke, authority is what they can cause to happen, directly or transitively, through any code they can call. In a system where every library function inherits its caller's privileges, "least privilege" can still permit cascading damage through transitive authority: for example, read_config() may seem to be a low-privilege operation until the config file contains a path the program will later open, write to, or exec. PoLA closes that gap by asking the harder question: what is the smallest set of things this code can ultimately make happen?
PoLA versus ambient authority
The opposite of PoLA is ambient authority: code runs with the surrounding context's full set of permissions by default. In a typical operating system, a process inherits the file descriptors, environment variables, network interfaces, and credentials of the user that launched it. Any library the process loads, any function it calls, any data it deserializes inherits that authority transitively. A SQL-injection vulnerability in a web app inherits the process's database credentials; a misconfigured deserializer can reach any file on disk the process can reach.
Under PoLA, code starts with no authority. Every capability it holds (e.g., the ability to open a specific file, contact a specific host, or read a specific configuration value) is passed to it explicitly. The path of authority is visible at every hop, which means the maximum damage from a compromise is bounded by what was passed in, not by what the surrounding process happens to be able to access.
PoLA in WebAssembly components
WebAssembly components are designed to be deny-by-default. A component compiled to wasm32-wasip2 starts with no file system, no network, no environment variables, and no clock. Its WIT world declares which capabilities it imports, and the host decides whether (and how) to satisfy those imports.
A component that wants to make an HTTP request must import wasi:http/outgoing-handler, and the host gets to decide what hosts that import resolves to. A component that wants to read configuration must import wasi:config, and the host decides what keys it can see.
See the Component Model Book for how WIT worlds describe capability surfaces, and WASI.dev for the standard WASI interfaces a host can choose to expose.
PoLA in Cosmonic Control
In Cosmonic Control, a workload's authority is declared in its manifest. Each component carries a localResources block that lists the capability resources the host should grant it — environment configuration, outbound egress allowlist, secrets, and the like. The simplest case is an HTTPTrigger that needs to call one external API:
apiVersion: control.cosmonic.io/v1alpha1
kind: HTTPTrigger
metadata:
name: weather-proxy
spec:
ingress:
host: weather.localhost.cosmonic.sh
paths:
- path: /
pathType: Prefix
template:
spec:
components:
- name: handler
image: ghcr.io/example/weather-proxy:0.1.0
localResources:
allowedHosts:
- https://api.weather.example.comThis component can serve HTTP requests on the trigger's ingress, and make outbound requests to api.weather.example.com.
Regardless of any bug or compromise in the component's code, it cannot read the host's filesystem, open a TCP connection to anywhere except api.weather.example.com, read another tenant's secrets, see other components on the same host, or shell out to a binary. None of those capabilities were granted. There is no --privileged flag to forget or 0.0.0.0/0 egress rule to misconfigure.
The capability boundary is enforced by the runtime sandbox at the CPU-instruction level, and it's pinned to the manifest the platform team controls.
Related
- Capabilities — the mechanism that makes PoLA enforceable: unforgeable references granted explicitly by the host.
- Security and Non-Deterministic I/O — why PoLA becomes load-bearing when an LLM is in the loop and the access pattern is no longer derivable from the code.
- Component Configuration — how
allowedHosts,localResources, and component config are passed at the manifest level. - Multitenancy — how PoLA composes with Kubernetes namespace boundaries to give per-tenant isolation.
- Sandbox AI — an applied example: bounding what an MCP server can reach when the model driving it is untrusted.
- Robust Composition (Miller, 2006) — the canonical treatment of PoLA, capabilities, and how they compose.