Skip to main content

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. PoLA is a refinement of the older principle of least privilege, and it is the central design rule of capability-based security. 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.

Key takeaways
  • PoLA sets, at deploy time, the maximum damage a compromised component can cause.
  • It generalizes the principle of least privilege by counting transitive authority: what code can ultimately make happen.
  • WebAssembly components enforce PoLA structurally: a component starts with no capabilities and the host grants only the imports declared in its WIT world.

Origins: from least privilege to least authority

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. Fifty years on, it is still the canonical formulation referenced by NIST and OWASP. The version most capability-systems researchers learn today comes from later work, 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 — the classic case is Hardy's Confused Deputy (1988), where a trusted intermediary is tricked into using its authority on an untrusted caller's behalf. PoLA closes that gap by asking the harder question: what is the smallest set of things this code can ultimately make happen?

PoLA versus the Principle of Least Privilege

The two terms are often used interchangeably, but they are not the same.

  • Least privilege is about naming what each principal is allowed to invoke: read this file, call this API, write to this database. It works when the access pattern is known at policy-design time and when authority does not flow transitively through called code.

  • Least authority is the strictly stronger property. Authority is what a principal can ultimately cause to happen, including everything its called code, loaded libraries, and deserialized inputs can reach. A system can enforce least privilege without enforcing least authority — and most do, which is why a single SQL-injection vulnerability inside a web service can exfiltrate every database the surrounding process can reach. Least authority requires the language or runtime to bound transitive reach, which is exactly what capability-based security provides.

In short: every system that enforces least authority also enforces least privilege; the reverse is not true.

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.

Side-by-side comparison. Left: an OS process under ambient authority, with solid arrows reaching out to Filesystem, Env vars, Credentials, and Network — every resource is reachable by default. Right: a Wasm component under the Principle of Least Authority, with dashed lines to the same resources marked as unreachable, and a single solid arrow out to one explicitly granted capability — wasi to api.weather.example.com.

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/store, 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.com

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

Frequently asked questions

What is the Principle of Least Authority?

The Principle of Least Authority (PoLA) is a security design rule that says every component should hold only the specific authority it needs to do its job, counted transitively across every library, function, or piece of data it touches. It is the central design rule of capability-based security and a strict strengthening of the older principle of least privilege.

What is the difference between Principle of Least Authority and Principle of Least Privilege?

Least privilege bounds what a principal is named to invoke (X user can read Y file). Least authority bounds what a principal can ultimately cause to happen through any code it calls. A system can enforce least privilege without enforcing least authority — and most do, which is why a single library-level bug can compromise an entire process. Least authority requires the runtime to bound transitive reach, which is what capability-based security provides.

How does the Principle of Least Authority apply to WebAssembly?

WebAssembly components are deny-by-default: a component starts with no file system, no network, no environment variables. Its WIT world declares the capabilities it imports, and the host decides whether and how to satisfy each one. The maximum reach of the component is structurally bounded by its imports, not by what the surrounding process happens to have access to.

What is the Confused Deputy problem?

The Confused Deputy (Hardy, 1988) is the canonical example of why least privilege is not enough. A trusted intermediary, holding broad ambient authority, is tricked by an untrusted caller into using that authority on the caller's behalf. Capability-based systems prevent the attack structurally: the intermediary only holds the capabilities it was passed, so the attacker's request cannot be silently elevated.

How does Cosmonic enforce the Principle of Least Authority?

Every Wasm component on Cosmonic Control starts with zero authority. Each capability (e.g., outbound HTTP, configuration values, key-value buckets, secrets) must be granted explicitly through the workload manifest, and the runtime sandbox enforces the bound at the CPU-instruction level. A reviewer can read the manifest and know, statically, every external resource a component can touch.

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