From harness-claude
Guides implementing capability-based security to replace ambient authority with unforgeable, revocable tokens, preventing confused deputy attacks in plugins, sandboxes, and APIs.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Replace ambient authority ("who are you?") with explicit capabilities ("what token do you hold?") -- eliminating confused deputy attacks by making every permission a transferable, revocable, unforgeable object
Provides patterns for JWT/session/OAuth auth, RBAC authorization, encryption, secrets, CORS, rate limiting, and security checklists for web apps.
Guides API authentication, authorization, and security patterns including OAuth 2.0 flows with PKCE, OIDC, JWT, API keys, rate limiting, and common vulnerabilities.
Detects OAuth2, JWT, RBAC/ABAC, session management, and MFA patterns in codebases. Evaluates auth security against OWASP guidelines and recommends improvements for tokens, permissions, and MFA. Useful for auth flow audits and PR reviews.
Share bugs, ideas, or general feedback.
Replace ambient authority ("who are you?") with explicit capabilities ("what token do you hold?") -- eliminating confused deputy attacks by making every permission a transferable, revocable, unforgeable object
The confused deputy problem (first described by Norm Hardy in 1988) occurs when a privileged program is tricked into misusing its authority on behalf of an attacker. Classic example: a compiler service has write access to billing logs through ambient authority (its process identity grants access); an attacker passes a crafted output filename that targets the billing log, and the compiler overwrites it using authority that was granted for a different purpose entirely. In ACL-based systems, the compiler's identity grants write access regardless of who initiated the request or for what purpose. In capability-based systems, the compiler only possesses capabilities explicitly passed to it by the caller -- no ambient authority exists to misuse.
CSRF is a web-specific confused deputy: the browser attaches cookies (ambient authority) to cross-origin requests, allowing a malicious site to act with the user's authority on any site the user is logged into. SameSite cookies are a partial mitigation; capability-based tokens (where the request must explicitly include a token, not relying on automatic cookie attachment) eliminate the attack class entirely.
Pre-signed URLs (S3, GCS, Azure Blob) are real-world capabilities deployed at massive scale: unforgeable, time-limited, scoped to a specific action on a specific resource -- the architectural opposite of ambient authority.
Understand the core principle: authority follows the reference. A capability is an unforgeable reference that both designates a resource and authorizes an action on it. Possessing the capability is sufficient to perform the action -- no additional identity check is needed. This contrasts fundamentally with ACL/RBAC systems where the system asks "who are you?" and checks a permission list associated with the resource. In capability systems, the question is "what token do you hold?" The capability itself carries the authorization.
Design capabilities as unforgeable tokens. A capability must be impossible to guess or fabricate. Three implementation approaches:
The critical property across all approaches is unforgeability: a party that does not possess a capability cannot create one through guessing, computation, or manipulation.
Apply the Principle of Least Authority (POLA). When creating a new process, plugin, service call, or function invocation, grant only the capabilities it needs -- nothing more. Do not pass a database connection object when the function only needs to read one table. Do not pass a write capability when read suffices. Do not pass an unbounded-time capability when a 5-minute window is appropriate.
Capability systems make POLA natural because authority is explicit at the call site: the caller constructs and passes exactly the set of capabilities the callee needs. In contrast, ACL systems make POLA difficult because services accumulate ambient authority through their identity, and restricting that authority requires modifying the central permission list rather than the call site.
Support attenuation (narrowing but never expanding rights). A holder of a write capability should be able to derive a read-only capability from it and pass that derived capability to a less-trusted party. Attenuation is strictly one-directional: you can narrow capabilities but never widen them.
If Alice has (document:X, read+write, expires:2025-12-31), she can derive (document:X, read-only, expires:2025-06-30) -- same or narrower action scope, same or earlier expiration -- and share it with Bob. Bob cannot re-derive write access or extend the expiration. Macaroons implement attenuation via HMAC-chained caveats that can only be appended, never removed.
Implement revocation. Capabilities that cannot be revoked are permanent, transferable, irrevocable grants of authority -- unacceptable for most production systems. Revocation strategies ordered by complexity:
Apply to real-world systems. Capability-based security is not theoretical -- it is deployed at massive scale in production systems:
--allow-read=/tmp grants a filesystem read capability scoped to /tmp. Without the flag, the runtime has zero filesystem access. Every permission is an explicit capability grant on the command line.sandbox attribute strips all ambient capabilities (scripts, forms, popups, top navigation). Adding allow-scripts restores only the script execution capability.--cap-drop ALL --cap-add NET_BIND_SERVICE drops all Linux kernel capabilities and selectively restores only the ability to bind privileged ports below 1024.| Property | ACL / RBAC | Capability-Based |
|---|---|---|
| Authority model | Ambient (identity checked against resource's permission list) | Explicit (token/reference held by the caller) |
| Confused deputy resistance | Vulnerable (program uses its own ambient authority on attacker's behalf) | Resistant by construction (program only has capabilities passed to it) |
| Delegation | Complex (requires delegating identity or modifying ACLs) | Natural (pass the capability token to the delegate) |
| Attenuation | Not native (requires creating new restricted roles) | Native (derive narrower capability from existing one) |
| Revocation | Immediate (remove entry from ACL) | Requires explicit mechanism (expiration, revocation list) |
| Centralized audit | Natural (one ACL per resource, query centrally) | Harder (capabilities are distributed, must track delegation chains) |
| Integration effort | Standard in most frameworks (RBAC middleware) | Requires architectural changes (explicit capability passing at call sites) |
Many production systems use both models: ACL-based identity checks at the perimeter (who can log in, what features can they access) and capability-based tokens for specific resource operations (pre-signed URLs for file access, scoped API tokens for third-party integrations, sandboxed execution environments for plugins).
Macaroons are bearer credentials that support decentralized attenuation through HMAC-chained caveats. Published by Google researchers, they are the most sophisticated capability token format in widespread use.
Construction:
HMAC(root_key, identifier). This represents the unrestricted capability.new_mac = HMAC(previous_mac, "time < 2025-06-01"). Each caveat further restricts what the token authorizes. Any holder can append caveats, but no one can remove them -- removal would require recomputing the HMAC chain from the root key, which only the issuing server possesses.Example attenuation chain:
Each party in the chain narrows the capability independently without contacting the others. The resource server verifies the entire chain by recomputing the HMAC from the root key and evaluating all caveats against the current request context.
URLs like https://app.com/share/a8f3c9d1e2b4f5a6789012345678abcd where the random token in the path is the capability. Knowing the URL grants access -- no additional authentication required. This pattern is used extensively by Google Docs ("anyone with the link can view"), Figma, Notion, Dropbox, WeTransfer, and most modern file-sharing services.
Security considerations:
Referrer-Policy: no-referrer or Referrer-Policy: origin.robots.txt exclusions and X-Robots-Tag: noindex headers on capability URL paths.Mitigations: short expiration times, access logging with alerting on anomalous patterns, download count limits, and the ability to revoke (regenerate) the sharing link from the UI.
In microservice systems, capabilities solve the confused deputy problem that arises when Service A calls Service B on behalf of User X. With ambient authority (service-to-service mTLS + RBAC), Service B checks that Service A is authorized -- but Service A might be calling on behalf of any user, including an attacker who found an SSRF vulnerability in Service A.
With capability-based inter-service communication:
{resource: "order:123", action: "read", user: "alice", expires: "2025-06-01T12:05:00Z", sig: "..."}.This pattern is implemented by Google's ALTS (Application Layer Transport Security) and by service mesh systems using SPIFFE-based identity with request-level authorization tokens.
The object-capability (ocap) model uses language-level object references as capabilities. In a true ocap language:
Languages with ocap properties: E (the original ocap language by Mark S. Miller), Newspeak (Gilad Bracha), Monte (descendant of E), and the WebAssembly Component Model. JavaScript approaches ocap through Hardened JS (SES -- Secure ECMAScript) using lockdown() and Compartment, deployed in production by Agoric for blockchain smart contracts and by MetaMask for secure plugin isolation.
The practical benefit of the ocap model: security analysis becomes tractable because authority flows are visible in the code structure. You can audit a module's authority by examining its constructor parameters and method arguments -- there is no hidden ambient access to search for. If a module's constructor does not receive a filesystem capability, it provably cannot access the filesystem, regardless of what code it contains.
Capability-based thinking improves API security even in systems that use ACLs as the primary authorization model:
Scoped API tokens: Instead of issuing a single API key with full account access, issue tokens scoped to specific resources and actions. GitHub's fine-grained personal access tokens are an example: each token specifies which repositories it can access and what operations it can perform.
Pre-signed upload URLs: Instead of giving the client credentials to upload to S3 directly, the server generates a pre-signed PUT URL scoped to a specific object key with a short expiration. The client uploads without ever possessing AWS credentials.
Invite links: Instead of adding a user to a resource's ACL and notifying them, generate a capability URL that grants specific access when followed. The link itself carries the authorization. The recipient does not need an account -- the link is the credential.
Delegated tokens for third-party integrations: When a user connects a third-party app to your service, issue a capability token scoped to exactly the data and actions the integration needs. OAuth 2.0 scopes are a coarse version of this; true capabilities would scope to specific resource instances, not just resource types.
Auditing capabilities requires different approaches than auditing ACLs:
Best practices for capability auditing: log every capability issuance with the scope, recipient, and expiration; log every capability exercise (successful use) with the resource accessed; alert on capabilities that are used after the expected session lifetime; and periodically enumerate all outstanding capabilities to identify over-permissioned or expired-but-not-revoked tokens.
Capabilities that cannot be revoked. A capability with no expiration and no revocation mechanism is a permanent, transferable, irrevocable grant of authority. If the token leaks (logged by a proxy, forwarded via email, scraped from a public page), the authority persists indefinitely. Always include either a short expiration, an active revocation mechanism, or both. The maximum acceptable lifetime depends on the sensitivity of the resource being protected.
Leaking capabilities through logs or URL parameters. Pre-signed URLs and capability tokens in URL paths are recorded by web servers, proxy servers, CDNs, analytics platforms, browser history, and browser extensions. Use POST request bodies or HTTP headers for capability transmission when the protocol allows it. When URLs must be used (sharing links, email links), enforce short expiration times and monitor access patterns for anomalies.
Ambient authority disguised as capabilities. An API key that grants access to all resources a user can reach is not a capability -- it is an identity credential with ambient authority formatted as a bearer token. True capabilities are scoped to a specific resource, a specific action, and ideally a specific time window. If revoking one token requires regenerating a single global key that breaks all integrations, the system uses ambient authority regardless of the token format.
Forgeable capabilities. A capability URL using sequential IDs (/share/1234, /share/1235) or predictable tokens (MD5 of the resource name, base64-encoded resource ID, timestamp-based generation) is trivially forgeable by enumeration or computation. Capabilities must be unguessable: 128+ bits of CSPRNG output for opaque tokens, or cryptographically signed structured payloads with tamper detection.
All-or-nothing permission scoping. A capability system that only offers "full access" and "no access" misses the fundamental value proposition. The power of capabilities lies in fine-grained scoping: read vs write vs delete, specific resource vs collection, time-limited vs permanent, single-use vs reusable, specific IP range vs anywhere. Design the capability model with the granularity that the application's security requirements demand -- then enforce it at the verification point.