SPIFFE: Stopping an Agent: Expiry, Revocation, and Incident Containment
Disabling an agent is not one operation. The agent may possess an SVID, an OAuth token, an established connection, a queued job, and a refresh-capable authorization context. Incident containment must address each separately.
Credential lifecycle is not a revocation chain
Token exchange does not inherently consume the input credential. It also does not guarantee that revoking the subject or actor token invalidates every token previously issued from it. Build explicit relationships if downstream invalidation is required, and test them.
Disabling future issuance differs from rejecting existing credentials. A resource server validating a self-contained token from cached public keys may not learn that XYZ was disabled until some separate policy update reaches it. Introspection can expose current authorization-server state, but cache duration and resource-server behavior still determine enforcement latency. Revocation endpoint behavior must be understood for the actual token type and deployment.
An illustrative containment timeline
| Time | Action | What may remain usable |
| T+0 | Disable agent deployment and isolate compromised runtime | Stolen credentials elsewhere; active requests |
| T+1 minute | Deny XYZ at STS and stop relevant identity issuance | Previously issued tokens and SVIDs |
| T+2 minutes | Push resource-server denial for actor/delegation | Caches and requests beyond authorization check |
| T+3 minutes | Cancel jobs and review active sessions/connections | Committed changes; remote services not yet updated |
| T+token lifetime | Remaining token expiry reached | Long-lived sessions if independently authorized |
Times are examples, not product guarantees. A hypothetical five-minute access token with a one-minute cache does not imply six-minute universal containment: an already-authorized long-running operation or independently created session may last longer. Measure the actual behavior.
Containment runbook
- Preserve relevant identities, token IDs, approvals, policy versions, and execution evidence; do not collect raw credentials into ordinary logs.
- Isolate the runtime and prevent replacement workloads from reacquiring the same identity.
- Deny further exchange for the affected actor and revoke appropriate approval/refresh contexts.
- Apply API-level actor or delegation denial where supported; distribute it to every enforcement point.
- Suspend queued jobs and prevent a retry path from resurrecting authority.
- Determine whether active requests, sessions, or connections require termination.
- Review completed mutations and trigger business rollback or compensating actions where needed.
- Verify containment using previously issued credentials, not only new login attempts.
Avoid issuer-wide collateral damage
Removing an entire trust bundle or issuer can disrupt every workload under that authority and may still fail to stop cached or already-authorized activity immediately. Prefer a targeted actor/delegation deny mechanism when the issuer itself is not compromised. If signing authority is compromised, broader trust removal and key replacement may be justified; that is a different incident class.
An emergency deny-list is a proposed supplemental control. Define its authenticated distribution, cache lifetime, availability behavior, administrative ownership, and effect on already-running operations. A deny-list that is unavailable must not silently disappear from policy.
Recovery criteria
Recover the underlying workload and deployment authority before re-enabling issuance. Verify that the compromise cannot satisfy selectors again, clear unauthorized approvals, restore reviewed configuration, and rotate compromised keys where relevant. A new run identifier is not a remediation boundary if the same compromised workload can obtain the same identity.
Takeaway: the practical containment window is determined by every credential and enforcement cache, not by the shortest advertised token lifetime.
SPIFFE: Authenticated Agent, Malicious Instructions: Identity Versus Agent Safety
An authenticated agent can still be manipulated. Identity controls must work even when the workload holds valid credentials and makes a harmful request. The useful threat model is therefore not only an outsider forging XYZ’s token; it is XYZ itself attempting an operation Lisa did not approve.
A worked prompt-injection scenario
Lisa asks XYZ to resolve case 4821. XYZ retrieves a document containing instructions to export customer records and send them to another service. The agent’s runtime, SPIFFE identity, and signing authority are unchanged. If its delegated token permits broad exports, authentication can succeed throughout the attack. The failure is excessive or insufficiently enforced authority, not a broken signature.
There are three independent constraints to examine: the target application, the operation within that application, and the specific object or mutation. An audience restriction can prevent use at payroll while doing nothing to stop a broad export at the authorized case API. A write scope may permit more than Lisa’s intended single-field update.
Task authorization outside the agent’s assertions
Recommended pattern: a trusted authorization interaction records Lisa’s approval, the authorized agent, target, resource, permitted actions, field-level constraints, expiration, and any use count. At exchange, consult that record rather than accepting an agent-supplied statement that Lisa approved. At execution, compare the actual request with the approved constraints. Approval must not be editable through the same untrusted content channel that proposes tool actions.
{
"authorization_details": [
{
"type": "case_operation",
"actions": [
"update"
],
"case_ids": [
"4821"
],
"allowed_fields": [
"status"
],
"allowed_status_values": [
"resolved"
]
}
]
}
The array structure illustrates RFC 9396 authorization_details. The case_operation type and its fields are custom; issuer and API must agree on semantics. Rich Authorization Requests do not automatically make these constraints native to RFC 8693 exchange or to every IdP release. A protected approval identifier plus server-side enforcement may be more practical than embedding all constraints.
Threats, controls, and residual risk
| Threat | Recommended control | Residual risk |
| Injected tool instructions | Independent task/resource authorization | Allowed actions can still be abused within their bounds |
| Requested target substitution | STS audience-transition allowlist | Approved target might itself be overprivileged |
| Confused deputy tool | Bind delegated context to actual operation | Tool implementation bugs |
| Stolen bearer credential | Supported sender-constrained token | Key theft or compromised authorized runtime |
| Agent manufactures approval | Approval issued outside agent authority | Approval-service compromise or deceptive consent UI |
| Repeated approved mutation | Atomic use-count enforcement | Retry and transaction semantics require design |
What possession proofs do not prove
Sender constraint makes token use depend on a presenting key. It does not prove that Lisa requested the operation or that the key holder has safe reasoning. DPoP binds proofs to HTTP method and URI and, for protected-resource calls, the token; it does not generally bind the business request body. Application authorization must validate the actual mutation independently.
Full-rights delegation is a conscious risk decision. If XYZ can exercise every operation Lisa can exercise in the application, a surprising request may still be authorized by policy. Neither an actor claim nor additional authentication can recover a narrower intention never represented in the grant.
Engineering acceptance questions
- Can injected content change approval records, audiences, or requested scopes?
- Does the API validate the actual object and body rather than only token claims?
- Which destructive actions require fresh approval or step-up?
- Are tool-provided identifiers canonicalized before policy comparison?
- Can an authorized agent repeatedly execute a nominally one-time task?
Takeaway: workload identity authenticates the execution boundary. Task authorization constrains what that boundary may do.
Windows Defender Auto-Updates Fail
Windows Defender is supposed to automatically update itself. But I periodically experience these updates getting ‘stuck’. To force an update from the CLI:
cd “C:\ProgramData\Microsoft\Windows Defender\Platform”
dir
# REM cd into the latest iteration
cd 4.18.26060.3008-0
MpCmdRun.exe -removedefinitions -dynamicsignatures
MpCmdRun.exe -SignatureUpdate
-removedefinitions -dynamicsignaturesremoves only the dynamic security intelligence/signature content already present on the box. In practice, this is a rollback/flush step. It is commonly used when you want to clear bad/poisoned/cached dynamic detections.-SignatureUpdatedoes the fetch/install step: it contacts the configured update source and downloads the current antimalware definitions/security intelligence.
If all else fails, download latest from https://www.microsoft.com/en-us/wdsi/defenderupdates and manually install it
SPIFFE: Trusted Issuer Does Not Mean Trusted for Everything: Validation and Claim Mapping
A trusted signature answers a narrow question: did an accepted signing authority authenticate this token’s contents? It does not answer whether this token type belongs at this endpoint, whether its subject is eligible for exchange, or whether the requested target should trust the resulting authority.
Build explicit token-processing contracts
Use separate input contracts for human subject evidence and agent actor evidence. For JWT inputs, establish allowed issuers, issuer-associated verification keys, algorithms, expected profile, intended audience, required claims, and temporal rules. Do not select trust using an arbitrary key URL from the submitted token. JWT security guidance stresses algorithm verification, issuer/audience validation, and mutually exclusive rules where different token kinds could otherwise be confused.
An actor JWT-SVID and a human access token may both be signed JWTs, but they are not interchangeable. A user JWT should not satisfy the agent processor because it has a sub field. A workload credential should not become a human subject merely because its signature verifies.
IdP configuration review
Review the actual subject processor, actor processor, exchange policy, access token manager, and OAuth client configuration together. Verify the installed release’s behavior and extension capabilities. This guide does not prescribe unverified administrator UI paths or claim that all task constraints are natively implemented in an access token manager.
| Verified input | Policy decision | Output |
| User issuer and stable subject | Eligible user and tenant | Issuer-qualified user subject mapping |
| Actor issuer, SPIFFE subject, intended audience | Approved agent identity | act.sub from verified actor evidence |
| Authenticated OAuth client | Permitted client/actor relationship | client_id under issuer control |
| Requested audience/resource | Allowed exchange edge | Approved target audience |
| Requested scopes | Allowed operations and delegation limits | Granted scopes, never blind copying |
| Protected approval record | Task/resources still approved | Reference or enforced task constraints |
An illustrative policy contract
accept actor evidence only from configured agents.example.org authority map verified SPIFFE subject → current actor require approved (client, actor, user, tenant) relationship permit exchange only to reviewed resource identifiers grant permissions within subject rights AND delegation constraints require current approval for high-impact tasks reject caller-provided actor overrides record policy decision and output token identifier
Input audiences and output validation
An exchange can legitimately transform a credential intended for one context into authority for another. Therefore, define which input contexts the STS accepts and which output targets each exchange relationship permits. Do not accept arbitrary audiences simply because the token was issued by a trusted issuer. Do not assume an API-only token is automatically an eligible exchange credential.
Resource servers must independently validate the issued access token. If using the JWT access-token profile, RFC 9068 supplies recipient validation requirements, including token typing and audience checks. An opaque-token deployment instead depends on its agreed introspection profile. Neither approach removes application authorization.
The act claim records delegated actor attribution. may_act expresses actor eligibility, not universal permission or task approval. A submitted actor name must never override the identity obtained from verified evidence.
Review evidence
- Export effective configuration, not only screenshots of one processor.
- Demonstrate rejection of cross-profile tokens and unauthorized audience transitions.
- Test omitted, malformed, and unexpected actor claims.
- Verify scopes are granted by policy rather than echoed from requests.
- Identify which component enforces resource-level and approval-level restrictions.
Takeaway: verification, mapping, and authorization are separate operations. Each requires a testable contract.
Fedora: Disk Cleanup
Useful commands for disk cleanup …
Subfolder size excluding specific folders
[root@FVP05 ~]# du -shx --exclude=/mnt --exclude=/proc /* 0 /afs 0 /bin 312M /boot 2.1M /ca 8.0K /cacert.pem 4.0K /careq.pem 0 /certs 0 /crl 0 /dev 48M /etc 37M /home 0 /lib 0 /lib64 0 /media 0 /newcerts 0 /openhab 954M /opt 4.0K /private 457M /root 1.2M /run 120K /SampleCode 0 /sbin 0 /srv 0 /swapfile 0 /sys 227M /tmp 8.2G /usr 14G /var
List the largest n RPM installs
[root@FVP05 ~]# rpm -qa –qf ‘%{SIZE}\t%{NAME}\n’ | sort -nr | head -10
488208897 azure-cli 248737290 java-latest-openjdk-headless 238259971 glibc-all-langpacks 182326049 mesa-vulkan-drivers 147275895 llvm-libs 127750222 gcc 106627293 kernel-core 106091788 kernel-core 105915244 nvidia-gpu-firmware 105470864 kernel-modules
And clean up the journal logs
journalctl --vacuum-size=100M
DNF – Do I need to restart?
Corporate Greed?
Corporate greed is an easy, convenient answer to why things are so expensive … but I’ve tracked profits and revenue for the global “big oil” companies for a while now. Other than Armaco, and generally Petrobras, profits are under 10% of revenue. “Record profits” seem, generally, to come from record sales. We’re not going through record high profit percentages.
Now, a company that “only” profited five billion dollars on 380b isn’t doing badly and could probably have gotten by if they only made 2 billion – but that makes for an interesting study. Say oil is $100 per barrel. 380 billion dollars is 3.8 billion barrels sold (yes, I know many of these companies have other lines of business. This is a thought experiment, not a regulated financial filing). If they earned three billion dollars less that year, the price per barrel would only drop $0.79. Under 1% change. Now, if Armaco had only profited 3.4 billion last year instead of 93.4b, that would be a $20/barrel drop.
Raw data:
| Company | 2025 | 2024 | 2023 | 2022 | 2021 | 2020 | 2019 | 2018 | 2017 | 2016 | 2015 | 2014 | 2013 | 2012 | 2011 | 2010 | 2009 | 2008 | 2007 | 2006 | ||||||||||||||||||||
| Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | Revenue ($B) | Net profit ($B) | |
| 1. Saudi Aramco | 446 | 93.4 | 481 | 106.2 | 495 | 121.3 | 604 | 161.1 | 400 | 110.0 | 230 | 49.0 | 330 | 88.2 | 356 | 111.1 | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a |
| 2. PetroChina | 399 | 21.9 | 409 | 22.9 | 426 | 22.8 | 481 | 22.2 | 405 | 14.3 | 280 | 2.3 | 364 | 10.4 | 356 | 7.9 | 298 | 3.4 | 244 | 0.9 | 277 | 5.7 | 371 | 17.4 | 365 | 20.9 | 348 | 18.2 | 298 | 20.6 | 216 | 20.6 | 149 | 15.1 | 155 | 16.5 | 110 | 18.4 | 86 | 17.9 |
| 3. Sinopec | 388 | 4.4 | 428 | 7.0 | 454 | 8.5 | 493 | 9.9 | 435 | 9.5 | 305 | 4.8 | 430 | 8.3 | 437 | 9.2 | 349 | 7.6 | 291 | 7.0 | 324 | 5.3 | 459 | 8.8 | 465 | 10.3 | 457 | 10.1 | 388 | 9.8 | 283 | 9.3 | 197 | 8.6 | 209 | 6.8 | 157 | 7.0 | 131 | 6.4 |
| 4. ExxonMobil | 334 | 28.8 | 350 | 33.7 | 345 | 36.0 | 414 | 55.7 | 286 | 23.0 | 182 | -22.4 | 265 | 14.3 | 279 | 20.8 | 290 | 19.7 | 227 | 7.8 | 260 | 16.2 | 412 | 32.5 | 438 | 32.6 | 481 | 44.9 | 486 | 41.1 | 383 | 30.5 | 311 | 19.3 | 477 | 45.2 | 405 | 40.6 | 378 | 39.5 |
| 5. Shell | 274 | 17.8 | 289 | 16.1 | 323 | 19.4 | 386 | 42.3 | 273 | 20.1 | 183 | -21.7 | 352 | 15.8 | 397 | 23.4 | 312 | 13.0 | 240 | 4.6 | 272 | 1.9 | 431 | 14.9 | 460 | 16.4 | 482 | 26.7 | 484 | 30.8 | 378 | 20.1 | 285 | 12.5 | 458 | 26.3 | 356 | 31.3 | 319 | 25.4 |
| 6. TotalEnergies | 201 | 13.1 | 214 | 15.8 | 237 | 21.4 | 284 | 20.5 | 206 | 16.0 | 140 | -7.2 | 200 | 11.3 | 209 | 11.4 | 171 | 8.6 | 150 | 6.2 | 165 | 5.1 | 236 | 4.2 | 251 | 11.2 | 257 | 14.7 | 257 | 17.1 | 212 | 14.1 | 183 | 11.7 | 264 | 20.4 | 217 | 18.0 | 193 | 15.8 |
| 7. BP | 189 | 0.1 | 189 | 0.4 | 210 | 15.2 | 241 | -2.5 | 158 | 7.6 | 180 | -20.3 | 277 | 4.0 | 299 | 9.4 | 240 | 3.4 | 183 | 0.1 | 223 | -6.5 | 354 | 3.8 | 379 | 23.5 | 387 | 11.0 | 376 | 25.2 | 297 | -3.7 | 246 | 16.6 | 361 | 21.2 | 274 | 20.8 | 254 | 22.3 |
| 8. Chevron | 189 | 12.5 | 203 | 17.7 | 201 | 21.4 | 246 | 35.5 | 162 | 15.6 | 95 | -5.5 | 147 | 2.9 | 166 | 14.8 | 142 | 9.2 | 114 | -0.5 | 138 | 4.6 | 212 | 19.2 | 229 | 21.4 | 242 | 26.2 | 254 | 26.9 | 205 | 19.0 | 172 | 10.5 | 273 | 23.9 | 221 | 18.7 | 210 | 17.1 |
| 9. Rosneft | 101 | 3.6 | 109 | 11.7 | 107 | 14.9 | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | 92 | n/a | 63 | n/a | n/a | n/a | n/a | 11.1 | n/a | 6.5 | n/a | n/a |
| 10. Petrobras | 89 | 19.6 | 91 | 7.5 | 102 | 24.9 | 124 | 36.6 | 84 | 19.9 | 54 | -1.1 | 77 | 10.2 | 85 | 7.2 | 89 | 0.1 | 81 | -4.0 | 97 | -10.0 | 144 | -9.0 | 141 | 10.9 | 144 | 10.9 | 146 | 20.0 | 121 | 20.0 | 91 | 14.0 | n/a | n/a | n/a | n/a | n/a | n/a |
Data as available. Publicly traded companies in US and Europe are far more apt to have published , audited, probably somewhat accurate data.
Smithsonian Institute 3D Models!
This is amazing — and every one I’ve looked at so far includes a download option … https://3d.si.edu/explore
SPIFFE: OAuth Token Exchange: Verified Identity Is Not Unlimited Permission
An agent presents two credentials: one representing me and one identifying Agent XYZ. A token service returns an access token stating that Agent XYZ is acting on my behalf.
What prevents the agent from taking that token somewhere I never authorized?
Not the actor claim alone. Secure delegation requires verified input credentials, controlled issuance, restricted output tokens, and enforcement by the receiving application. OAuth token exchange supplies the protocol; it does not automatically determine what I intended.
The RFC behind token exchange
RFC 8693, OAuth 2.0 Token Exchange, defines an OAuth-based Security Token Service, or STS. A client submits existing security tokens and requests a new token suitable for a particular purpose. The exchange can change token format, target audience, or authorization context, including representing delegation or impersonation.
The distinction matters:
- Impersonation: the recipient sees the subject’s identity without necessarily distinguishing the intermediary.
- Delegation: the token preserves the subject and identifies the party acting for that subject.
For our agent scenario, delegation is the useful model: Lisa remains the authorization subject, while Agent XYZ is recorded as the actor.
How an exchange works
An illustrative request to an STS token endpoint contains:
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
subject_token=<Lisa’s eligible access token>
subject_token_type=urn:ietf:params:oauth:token-type:access_token
actor_token=<Agent XYZ’s supported identity token>
actor_token_type=urn:ietf:params:oauth:token-type:jwt
requested_token_type=urn:ietf:params:oauth:token-type:access_token
audience=case-management-api
scope=cases.read cases.update
The subject_token provides the subject’s security context; the optional actor_token identifies the proposed actor. audience, resource, and scope describe requested targets and permissions. These are requests, not issuer obligations. Client authentication is a separate consideration from submitting either token.
The conceptual flow is:
Existing credentials + requested target and permissions
|
v
Security Token Service
├─ Validate credentials
├─ Evaluate exchange policy
├─ Establish delegated authority
└─ Issue a constrained token
|
v
Resource API
├─ Validate issued token
└─ Authorize this operation
An exchange bridges security contexts; it is not simply a JWT re-signing operation. RFC 8693 explicitly limits its scope to the exchange protocol rather than defining every deployment’s trust and authorization policy.
The exchanger must verify—not believe—the inputs
The STS should not accept:
subject = Lisa
actor = Agent XYZ
trust_me = true
It must establish those identities from credentials validated under an explicitly configured trust relationship. Token-validation rules depend on the accepted token profile; the API must also validate the resulting token independently. For JWT access tokens using RFC 9068, validation includes the expected token type, issuer, audience, signature, and expiration. (datatracker.ietf.org)
For this deployment, I would require the following issuance controls:
| Boundary | Required decision |
| Input trust | Is this issuer permitted to supply this kind of identity evidence? |
| Credential validity | Is the token authentic, current, and acceptable in this exchange context? |
| Actor identity | Which actor does the verified credential actually identify? |
| Exchange eligibility | May this client or actor exchange this subject’s credential? |
| Target authorization | May this delegation reach the requested API? |
| Permission authorization | Which requested operations may the output token permit? |
| Output binding | Must the resulting token be bound to a particular presenting key? |
These are recommended policy requirements—not defaults guaranteed by enabling RFC 8693. Its may_act claim can express actor eligibility, but identifying an eligible actor is still different from authorizing every requested target or operation.
Crucially, the resulting token is normally issued for the resource server to validate, not merely for the exchanger to recognize later. A resource server that trusts the STS must still enforce the token’s intended use.
A signed actor claim is attribution, not consent
An illustrative delegated token might contain:
{
“iss”: “https://identity.example.org”,
“sub”: “user:lisa”,
“aud”: “case-management-api”,
“scope”: “cases.read cases.update”,
“act”: {
“sub”: “spiffe://agents.example.org/agent/xyz”
}
}
The issuer asserts that Lisa is the subject and Agent XYZ is the current actor. The signature protects that assertion against modification. The actor claim does not, by itself, establish that Lisa approved a specific case update or requested access to another application.
This is the central distinction:
Who is acting, whose authority applies, and which action was authorized are separate facts.
If the deployment intentionally gives Agent XYZ all of Lisa’s application rights, then an unexpected operation within those rights may be policy-authorized even though Lisa did not intend it. No token format can recover a narrower instruction that the authorization system never captured.
Preventing the “Lisa never asked for that” failure
There are several different failures hiding inside that example. They require different controls.
- Using the token at another application
Suppose Agent XYZ receives a token for the case-management API, then presents it to payroll.
Payroll must reject it because payroll is not its intended audience. Sharing an issuer or signing key does not make a token valid for every application. RFC 9700 recommends audience-restricted access tokens to limit this kind of reuse.
For this architecture, prefer one narrowly defined target per token and exact audience validation at each API.
- Exchanging it again for an unauthorized application
Audience validation does not help if the agent can ask an STS to convert its case-management token into a payroll token.
The recommended issuance policy is to authorize each permitted exchange edge explicitly:
Lisa delegation + Agent XYZ → case-management: allowed
Lisa delegation + Agent XYZ → payroll: denied
Changing audience is a legitimate purpose of exchange, so the defense is not “never change audience.” It is never let possession of an input token alone authorize an arbitrary audience transition. This follows from the protocol’s separation between the requested target and issuer policy.
- Performing an unintended action within the correct API
Audience restriction cannot distinguish “update case 4821” from “update every case Lisa can access.” A broad cases.update scope may be equally insufficient.
RFC 9396, Rich Authorization Requests, defines authorization_details for expressing finer-grained authorization requirements using structured JSON. The application-specific authorization type must define what those details mean and how they are enforced.
For example, a proposed—not standardized—authorization object could be:
{
“type”: “case_operation”,
“actions”: [“update”],
“case_ids”: [“4821”],
“allowed_fields”: [“status”],
“allowed_status_values”: [“resolved”]
}
In this design, Lisa approves that operation through a trusted authorization interaction. The STS issues authority no broader than the approved operation, and the API checks the actual resource and requested mutation against it.
RFC 9396 does not automatically add this object to RFC 8693 exchanges. Supporting it requires an agreed issuer/API profile and enforcement implementation. Structured authorization is useful only when the resource server understands and checks it.
- Stealing and replaying the token
A bearer token can be used by whoever possesses it. A signed act claim can therefore attribute a stolen token to Agent XYZ even when another party presents it.
Sender-constrained tokens address that problem by requiring proof of possession of an associated key. RFC 9700 recommends these alongside audience restrictions.
RFC 9449, DPoP, provides application-layer sender constraint. The client supplies signed proofs, and the recipient validates the proof and its relationship to the access token.
DPoP proofs include request method and URI information, token binding through ath for protected-resource requests, and freshness/replay controls. But DPoP does not ordinarily bind the business request body or establish Lisa’s approval of its contents.
A legitimate—or compromised—agent holding the bound key can still generate proofs for operations its token permits. Sender constraint prevents a different presenter from simply replaying the token; it does not make the authorized presenter trustworthy.
A practical task-bound delegation design
For the Lisa/Agent XYZ scenario, I would implement the following:
- Capture approval outside the agent’s assertions. Store an approved delegation identifying Lisa, Agent XYZ, target application, operations, resources, and expiry.
- Require that approval during exchange. Validate both credentials and check the requested output against the stored grant.
- Issue narrowly. Restrict audience, operations, object identifiers, lifetime, and presenting key where supported.
- Enforce at the API. Validate the token, then compare the actual operation and affected object with the grant.
- Control further exchange. Deny unapproved target transitions and privilege expansion.
- Record execution. Log subject, actor, delegation identifier, target, resource, authorization decision, and outcome.
- Use state where necessary. For one-time approval, atomically consume the authorization at the operation boundary; a unique token identifier alone does not make a token single-use.
This is a proposed deployment architecture combining token exchange, constrained access tokens, and fine-grained authorization—not a claim that RFC 8693 implements these controls automatically.
The takeaway
Token exchange can turn verified credentials into a token trusted by another system. It must not turn identity evidence into unrestricted authority.
For the threat in question, insist on four distinct properties:
- Verified subject and actor.
- Authorized issuance for the requested target.
- Permissions bounded by the approved delegation.
- Resource-server enforcement of those bounds.
“Agent XYZ acting for Lisa” explains attribution. “Agent XYZ may perform this operation on this resource for Lisa” is the authorization boundary.


Sure, it sucks to vote for the “least bad”, but that is better than being governed by the worst.
Vote for the person who is closer to where you think we should be instead of the waiting for your perfect candidate.