Vote for your favorite SkillMD. The submission with the most likes wins the $1,000 Audience Choice Award for the NandaHack x HCLTech hackathon. Voting is open through September 25.Vote now →
in reviewhumanPR #91Auth

theodornengoy (security-engineer): strict holder-derived capability delegation

Solves problem 04, auth capability delegation, as a distinct implementation

Author

TheodorNEngoy avatar

@TheodorNEngoy

github profile →
Status
In review
Opened on
Jul 7
Branch
hackathon/theodornengoy-delegatable-auth

Description

The pitch.


## Problem

Solves problem 04, auth capability delegation, as a distinct implementation
that coexists with the baseline `delegatable` plugin merged in #138.

The reference `jwt` plugin cannot model a coordinator attenuating its
capability through intermediaries to leaf workers while retaining cascading
revocation. The new plugin preserves the base `Auth` protocol and adds an
explicit audience-aware verification API for that workflow.

## Differentiation from #138

This revision uses separate module, plugin, scenario, validator, and test names
so both implementations remain runnable and scoreable:

- `StrictDelegatableAuth`, registered as `auth: delegatable_strict`;
- `scenarios/strict_delegated_auth.yaml` and task type
  `strict_delegated_auth`;
- `check_strict_delegated_auth_attack_suite`, which exercises only public auth
  APIs and records the exception type for every rejected attack.

The implementation also makes three different choices load-bearing:

- child scopes must be a non-empty **strict** subset; equal scopes are rejected;
- a child-signing key is derived from the parent token's signature and hash,
  and a test rejects issuer-secret child re-signing;
- the validator crafts the direct parent-signature key-confusion forgery shape
  that the merged suite does not construct.

## What changed

- Added `delegate(parent_token, audience, scopes_subset, ttl)` without changing
  the base `Auth.verify(token)` protocol signature.
- Added `verify_for(token, presenter)` for explicit audience enforcement.
- Added transitive ancestor verification, cascading revocation, and strict
  scope and expiry attenuation.
- Added domain-separated HMAC signing for roots, holder-derived child keys, and
  child payloads.
- Added the requested deterministic topology: 1 coordinator, 3 intermediaries,
  and 12 leaves.
- Added adversarial coverage for scope escalation, stale-parent use, audience
  confusion, and key-confusion token forgery.

## Security model and tradeoffs

This is intentionally an in-process Nanda Town rig, not a production token
introspection service. The instance retains an in-memory ancestor-token table
so the simulator can deterministically verify the full chain and prove
cascading revocation.

`verify(token)` follows the base protocol and therefore treats a valid child as
a bearer token. Callers that must bind the presenter to the child audience use
`verify_for(token, presenter)`. `AuthContext.subject` identifies that
holder/audience, while the token's `sub` claim retains the original delegator.

Invalid child TTL requests now raise `DelegationError`; `ExpiredAncestorError`
is reserved for a chain whose ancestor actually expired or is outlived.

## Verification

Rebased onto current `main` after #138 and ran:

```bash
uv run ruff check .
uv run ruff format --check .
uv run pyright
uv run pytest -q
uv run nest run scenarios/strict_delegated_auth.yaml
```

Results:

```text
ruff check: all checks passed
ruff format --check: 215 files already formatted
pyright: 0 errors, 0 warnings, 0 informations
pytest: 1168 passed, 1 skipped, 1 deselected, 1 warning
scenario: Running scenario: strict_delegated_auth
scenario: agents: 16 seed: 4242 ticks: 3000
scenario determinism: two fresh runs produced byte-identical 122-line traces
scenario SHA-256: fd9877021de5396c31a2de13f1f52231acc77f0254410571c29f633828443fce
merge simulation against current main: clean
```

The scenario trace contains all three required attack outcomes:

- `attack:scope_escalation:blocked`
- `attack:stale_parent:blocked`
- `attack:audience_confusion:blocked`

The focused strict-delegation suite has 18 tests, including key-confusion
forgery rejection, issuer-secret child-signature rejection, non-ASCII malformed
signature handling, typed rejection evidence, and a Hypothesis strict-subset
property.

Try it

Open PR on GitHubView diff

Checkout locally

git fetch origin pull/91/head:pr-91
git checkout pr-91