Skip to content

tool.invoke accepts another session's lease_id and inherits its authority #47

@nficano

Description

@nficano

src/Internal/Runtime/CredentialLifecycle.php:99 resolves the lease argument of an incoming tool.invoke by calling LeaseManager::get(new LeaseId($leaseArg)). src/Runtime/LeaseManager.php:39 indexes leases only by id and never records or checks the session or principal that the lease was granted to. A peer can therefore submit a tool.invoke whose arguments.lease (or arguments.lease.lease_id) names a lease that belongs to a completely different session and inherit that lease's permission, resource, operation, expiresAt, modelUse, and costBudget. The lease then becomes the base lease for the new job, overlaying it with the attacker's own cost.budget and model.use while keeping the victim's authority scope.

This is a privilege-escalation primitive in the credential-provisioning path: when a CredentialProvisioner is configured, the issued credentials are issued against the smuggled lease scope, and the runtime still routes credential rotation and revocation to the original session via the credential store. The bug is not surfaced by the current credential lifecycle integration tests because they all use one session.

Fix prompt: Record the granting session id (or principal) on each LeaseGranted registration in LeaseManager and have LeaseManager::get() (or a new getForSession() overload) refuse to return a lease that was not granted to the requesting session. In CredentialLifecycle::baseLease(), pass the active session through and translate any mismatch into PERMISSION_DENIED. Add an integration test that grants a lease in session A and asserts session B's tool.invoke with arguments.lease = {lease_id: ...} receives PERMISSION_DENIED.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingseverity:highHigh severity

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions