You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Sandbox admission JWTs currently use the generic JWT JOSE type (or may be untyped), while extension credentials use openshell-ext+jwt. PR #2638 prevents cross-domain replay by rejecting extension-token types at the sandbox authentication boundary and reserving the gateway sandbox audience, but sandbox credentials still lack their own explicit type.
An explicit sandbox token type adds defense in depth and enables the gateway to validate the sandbox trust domain independently of claims. Strict enforcement cannot be enabled immediately because supervisors may retain legacy tokens across a gateway upgrade, and sandbox JWTs may be configured as non-expiring.
Proposed Design
Introduce openshell-sandbox+jwt for gateway-minted sandbox admission tokens.
Phase 1 — compatible rollout:
Define the sandbox token type in the gateway sandbox-authentication module rather than openshell-extension-core.
Set typ: openshell-sandbox+jwt on every newly minted sandbox JWT.
Accept openshell-sandbox+jwt, legacy JWT, and missing typ during validation.
Add tests for the new minting header, new-token authentication, legacy JWT authentication, untyped-token authentication, and extension-token rejection.
Document the compatibility window and expose enough diagnostics to determine whether legacy tokens are still presented.
Phase 2 — strict validation:
Require typ: openshell-sandbox+jwt exactly.
Remove legacy JWT and untyped acceptance only after a defined cutover mechanism guarantees old credentials have been replaced. Token TTL alone is insufficient because gateway_jwt.ttl_secs = 0 permits non-expiring credentials.
Use either an explicit compatibility setting/deprecation cycle or a restart/refresh mechanism that reissues credentials for all active sandboxes before strict mode becomes the default.
Alternatives Considered
Keep rejecting only openshell-ext+jwt: this closes the known replay path but leaves sandbox credentials without a positive trust-domain discriminator.
Enforce the new type immediately: simpler validation, but it can break running supervisors holding tokens minted before a gateway upgrade.
Put the constant in openshell-extension-core: rejected because sandbox admission is gateway-internal authentication, not extension-facing functionality.
Use a separate signing key immediately: stronger trust-domain separation, but substantially broader than token typing and can remain a later key-rotation design.
SandboxJwtIssuer::mint currently constructs a generic EdDSA header and sets only kid; jsonwebtoken::Header::new supplies the legacy JWT type. SandboxJwtAuthenticator::validate_bearer now rejects openshell-ext+jwt before key fallback but otherwise accepts the legacy header shape. The gateway is both issuer and validator, while supervisors transport and may cache the opaque credential, making additive minting safe but immediate strict validation unsafe across rolling upgrades.
Problem Statement
Sandbox admission JWTs currently use the generic
JWTJOSE type (or may be untyped), while extension credentials useopenshell-ext+jwt. PR #2638 prevents cross-domain replay by rejecting extension-token types at the sandbox authentication boundary and reserving the gateway sandbox audience, but sandbox credentials still lack their own explicit type.An explicit sandbox token type adds defense in depth and enables the gateway to validate the sandbox trust domain independently of claims. Strict enforcement cannot be enabled immediately because supervisors may retain legacy tokens across a gateway upgrade, and sandbox JWTs may be configured as non-expiring.
Proposed Design
Introduce
openshell-sandbox+jwtfor gateway-minted sandbox admission tokens.Phase 1 — compatible rollout:
openshell-extension-core.typ: openshell-sandbox+jwton every newly minted sandbox JWT.openshell-sandbox+jwt, legacyJWT, and missingtypduring validation.openshell-ext+jwtunconditionally, as implemented by fix(security): authenticate extension services #2638.JWTauthentication, untyped-token authentication, and extension-token rejection.Phase 2 — strict validation:
typ: openshell-sandbox+jwtexactly.JWTand untyped acceptance only after a defined cutover mechanism guarantees old credentials have been replaced. Token TTL alone is insufficient becausegateway_jwt.ttl_secs = 0permits non-expiring credentials.Alternatives Considered
openshell-ext+jwt: this closes the known replay path but leaves sandbox credentials without a positive trust-domain discriminator.openshell-extension-core: rejected because sandbox admission is gateway-internal authentication, not extension-facing functionality.Agent Investigation
Related work: #2623 and PR #2638.
SandboxJwtIssuer::mintcurrently constructs a generic EdDSA header and sets onlykid;jsonwebtoken::Header::newsupplies the legacyJWTtype.SandboxJwtAuthenticator::validate_bearernow rejectsopenshell-ext+jwtbefore key fallback but otherwise accepts the legacy header shape. The gateway is both issuer and validator, while supervisors transport and may cache the opaque credential, making additive minting safe but immediate strict validation unsafe across rolling upgrades.