Verify session identity in self-hosted environments changedself-hosted-environments-identity
Nearest release: v2.1.287, published 12 hours before upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
Upstream edited this page at 2 Oct 2026 05:28 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 2 Oct 2026 05:37 UTC.
Upstream edited
Recorded here
Lines+3added
Lines−3removed
From line
171
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits7to this page, all time
The whole hunk
from line 171, old and new numbered
/
from line 171
171171
172172[Wrapper scripts](/docs/en/self-hosted-environments-configuration#wrapper-scripts) run inside the session, before Claude starts. Instead of calling a JWT library, they can run the runner binary's `self-hosted-runner decode-token` subcommand. The subcommand reads the token from a positional argument, from `CLAUDE_CODE_SESSION_ACCESS_TOKEN`, or from piped stdin, in that order, then strips the prefix, verifies the signature against the JWKS endpoint, checks expiry, and prints the claims as JSON. The subcommand performs the signature and expiry checks only; it doesn't check `iss`, `aud`, or `ccr:role`. When your wrapper's auth decision depends on those claims, read them from the printed JSON and compare them explicitly.
173173
174This command extracts the creator identity, preferring the SSO provider's subject, then the email address, then the creator's `act.sub` subject, `user:<id>` or `agent:<id>`:
174This command extracts the creator identity, preferring the email address, then the creator's `act.sub` subject, `user:<id>` or `agent:<id>`:
175175
176176```bash theme={null}
177"$CLAUDE_RUNNER_CLAUDE_BIN" self-hosted-runner decode-token | jq -re '.act.attested_by.sub // .act.email // .act.sub'
177"$CLAUDE_RUNNER_CLAUDE_BIN" self-hosted-runner decode-token | jq -re '.act.email // .act.sub'
178178```
179179
180180Wrappers receive the absolute path to the runner's own binary in `CLAUDE_RUNNER_CLAUDE_BIN`; use that path rather than a PATH-resolved `claude` so the decode runs on the same binary the runner itself uses.
from line 211
211211| :- | :- |
212212| `act.sub` | The creating user's Anthropic user ID, in the form `user:<id>`, or `agent:<id>` when your organization's service identity created the session, as it does for Claude Tag channel sessions. |
213213| `act.email` | The creating user's email address, when one was recorded at session creation. Don't require it; key on `act.sub`. |
214| `act.attested_by` | The upstream identity provider's attestation for the creating user, when available. `act.attested_by.sub` is the subject your SSO provider, such as Google or Okta, issued. Prefer this over `act.email` when mapping to identities in your own systems. |
214| `act.attested_by` | Reserved for the upstream identity provider's attestation for the creating user. Expect it to be absent, and don't depend on it. Key on `act.sub`. If you need an address, read `act.email` when it's present. |
215215| `act.act` | The runner that spawned the session. `act.act.sub` is `ccr:runner:<runner_id>`. |
216216| `act.act.act` | The environment. `act.act.act.sub` is `ccr:pool:<pool_id>`. |
217217| `act.act.act.act` | The identity that created the environment secret the runner registered with. The chain ends here. |
No line in this hunk matches that.