Bearer tokens, JWTs and session cookies grant access to whoever presents them, and they leak constantly into application logs, traces, error reports, test fixtures and support files where far more people and systems can read them than should. Unlike a password, a stolen session token arrives after MFA has already been satisfied, so replaying it skips every login control. This guide treats tokens in code and logs as a credential exposure problem: where they appear, who can read them, how to detect them with Gitleaks, TruffleHog and GitHub secret scanning, how to triage a hit, how to redact at source and in the pipeline, and how to revoke. It is for application security, platform and SOC teams. Token design itself (algorithms, validation, lifetimes) is covered in the JWT Security Guide and the Token Lifetime Policy Design Guide.
Key takeaways
- Anyone who can read the log can become the user. Log access is therefore privileged access for as long as any token in it is valid.
- Keep tokens out of URLs. RFC 6750 says bearer tokens should not be passed in page URLs because the URL is highly likely to be logged, and OWASP ASVS 5.0 requirement V14.2.1 makes this a Level 1 control.
- Redact at the source, then again in the pipeline. Logging framework filters stop most leaks; collector and SIEM masking catch the rest. Log a salted hash of a session ID when you need correlation.
- JWTs are easy to find, hard to verify. The
eyJprefix makes JWTs simple to match, but HMAC-signed tokens cannot be verified by a scanner, so triage relies on decoding claims such asexp,issandaud. - Revocation differs by token type. Server-side sessions can be killed instantly; self-contained JWTs stay valid until expiry unless you rotate the signing key, deny-list the token ID or revoke the refresh token behind it.
How identity and access work for session tokens and JWTs
A session token is a reference: a random identifier whose meaning lives in a server-side session store. A JWT is usually self-contained: a base64url header, payload and signature that the receiving service validates without a lookup. Both are bearer credentials. The difference matters most when one leaks.
| Token type | Typical form | Where it leaks | Fastest effective revocation |
|---|---|---|---|
| Web session cookie | JSESSIONID, PHPSESSID, framework or product cookies such as _gitlab_session | Reverse proxy and WAF logs that record headers, HAR files, crash dumps | Invalidate the session server side; force sign-out for the user |
| OAuth access token (JWT) | eyJ... three dot-separated segments | Application debug logs, APM traces with Authorization headers, URLs with access_token= | Wait for expiry, deny-list its jti, or rotate the signing key for a large incident |
| Opaque access token | Random string, sometimes with a vendor prefix | Same as above | Revoke at the authorisation server |
| Refresh token | Opaque or JWT | Mobile and SPA logs, local storage dumps, support tickets | Revoke at the authorisation server; it is the long-lived one |
| ID token | JWT | Front-end logs and analytics | Usually short-lived; revoke the session it created |
| Service-to-service JWT and client assertions | Signed JWT from a workload or private_key_jwt assertion | CI logs, test fixtures committed to code | Expire quickly by design; rotate the signing key if the private key leaked |
OWASP's Session Management Cheat Sheet is explicit that session IDs placed in URLs are disclosed through web logs, browser history, bookmarks and the Referer header. RFC 6750 adds that clients using the URI query method should send Cache-Control: no-store and that the method should not be used unless there is no alternative.
Admin roles and privileged access
The people and systems that can read logs, traces and tickets effectively hold every valid token in them. Treat these as privileged roles:
- Log and SIEM platform users: analysts, developers with production log access, and any saved search shared widely. Restrict raw log access to the teams that need it, and give most users only redacted views.
- Observability and APM: tracing tools often capture full request headers by default. Anyone with access to traces can lift
Authorization: Bearervalues. - Error trackers and crash reporting: stack traces and request context can include cookies and tokens; OWASP ASVS V16.5.1 requires that errors returned to clients never include secret keys or tokens, and the same discipline should apply to what is sent to the tracker.
- Support staff and HAR files: browser HAR captures contain cookies and authorisation headers. Ask customers to sanitise them, strip tokens on upload and delete them after use.
- Session administration consoles: OWASP warns that interfaces which let support staff view or impersonate active sessions must be strongly protected, because they expose every current session.
- Log pipeline service accounts: collectors, forwarders and archive jobs read everything. Scope their credentials and protect archives as sensitive data. See the Log Management and Retention Guide.
Integrations, API tokens and service accounts
Machine-to-machine tokens leak in different places from user sessions. The common sources are:
- Test fixtures and sample requests: developers paste a real token into a unit test, Postman collection or README. Even expired ones reveal issuer, audience, claim structure and sometimes internal hostnames.
- CI logs: a debug step that prints the environment or runs
curl -vwritesAuthorizationheaders into build logs that many people can read. - HTTP client debug logging: wire-level logging in SDKs and HTTP clients records full headers; it is often enabled in staging and forgotten.
- Gateways and proxies: access logs that record full URLs or selected headers capture any token sent in a query string or custom header.
- Message queues and event payloads: tokens forwarded inside events end up in dead-letter queues and event archives.
- Agent and AI tooling: prompts, tool call logs and agent transcripts frequently contain tokens passed to tools. See the Infostealer Logs and Session Token Abuse Guide for how stolen session material is traded and replayed.
Design reduces exposure: short-lived access tokens (RFC 6750 recommends one hour or less for bearer tokens), audience-restricted tokens (ASVS V9.2.3) so a leaked token works against one service only, and sender-constrained tokens where supported so a copied token is useless without the client's key. See the DPoP Guide and the Device-Bound Session Credentials (DBSC) Guide.
Logging and detection
Scanner coverage for tokens
| Scanner | JWT detection | Session token detection | Verification |
|---|---|---|---|
| Gitleaks (default rules) | jwt rule matching ey... header and payload segments with an entropy threshold; jwt-base64 for JWTs that have been base64-encoded again | Product-specific rules only, such as gitlab-session-cookie | None |
| TruffleHog | JWT detector matching eyJ style tokens; records alg, iss and exp | Vendor detectors only | For asymmetric tokens, fetches the issuer's OIDC discovery document over HTTPS and checks the signature; HMAC tokens cannot be verified in general; expired tokens can be ruled out |
| GitHub secret scanning | No generic JWT pattern; vendor JWTs only (for example Atlassian, Frame.io, Palantir) | Some vendor session tokens; generic http_bearer_authentication_header pattern | Validity checks are not supported for generic patterns |
Checked on 27 October 2026. Scanners are tuned for repositories; for logs, run the same patterns inside the pipeline or SIEM. A practical search set is: eyJ followed by two more base64url segments; Authorization: Bearer; query parameters named access_token, id_token, token, session or sid; and your framework's session cookie names in header fields. See the Secret Scanner Rule Coverage Comparison Guide for the wider comparison.
Triage a hit without making it worse
- Decode locally: the header and payload of a JWT are base64url, not encrypted. Decode them with a local tool; never paste a live token into an online decoder.
- Read the claims:
exptells you whether it is still live;issandaudtell you which issuer and service it unlocks;suband scopes tell you whose access and how much. - Find the blast radius: how long the log has existed, who can read it, and whether it was exported to other systems.
- Revoke and purge: revoke what is still live, then delete or mask the log entries, including copies in archives and the SIEM.
- Fix the source: find the code path that logged it and add a filter or test.
Single token or mass exposure? For a handful of tokens, revoke the sessions and refresh tokens involved and let access tokens expire. When a log containing thousands of live JWTs has been exposed, rotating the issuer's signing key invalidates every outstanding token at once, at the cost of signing everyone out; publish the new key in the JWKS before retiring the old one so services do not reject freshly issued tokens.
Monitoring and metrics
- Token findings per week in logs and repositories, by source system (target: falling to near zero).
- Time from finding to revocation for live tokens.
- Coverage: share of services whose logging configuration includes header and parameter redaction, verified by a test.
- URL tokens: requests carrying
access_tokenor session parameters in query strings (target: zero). - Replay signals: the same session token used from two networks or user agents, which may indicate a token lifted from a log. See the Session Hijacking and Cookie Theft Guide.
Hardening baseline
Redaction at each layer
| Layer | Control | Notes |
|---|---|---|
| Application code | Never log raw request headers or cookies; use structured logging with an allowlist of fields; mask known keys | OWASP lists session identifiers and access tokens under data to exclude |
| Session correlation | Log a salted hash of the session ID instead of the ID | Recommended by the OWASP Session Management Cheat Sheet |
| HTTP and SDK clients | Disable wire logging in production; mask Authorization and Cookie in debug modes | Add a test that fails if a known header appears in output |
| Reverse proxy and gateway | Exclude query strings or known token parameters from access logs; do not log selected auth headers | Keep tokens out of URLs in the first place (ASVS V14.2.1) |
| Telemetry pipeline | OpenTelemetry Collector redaction processor: allowed_keys (fails closed), blocked_key_patterns such as .*token.*, blocked_values regexes, optional hash_function | Set summary to info or silent in production, since debug lists redacted key names |
| SIEM and archive | Ingest-time masking rules for JWT and bearer patterns; restricted raw indexes | Masking after storage still leaves the raw copy in hot and archive tiers |
| Code repositories | Pre-commit and push protection scanning with the JWT rules enabled | See the Git Secret Scanning Guide |
Rollout
- Measure first: run the search set above against 30 days of logs from your highest-traffic services and record findings by source.
- Fix the top sources: usually one gateway access log, one debug logger and one APM header capture account for most hits.
- Add pipeline redaction in report mode: configure collector or SIEM masking with a debug summary in a test environment, confirm nothing needed for investigations is removed, then switch summary off and enforce.
- Lock down access: split raw and redacted log views and remove broad raw access.
- Add regression tests: a unit test per service that issues a request with a canary token and asserts it never reaches log output.
- Purge history: mask or delete historic entries containing tokens, starting with logs that are still within token lifetimes.
Rollback for pipeline redaction is a configuration change; keep the previous collector configuration in version control. For small teams, steps 2, 5 and the gateway rule give most of the benefit. Large organisations should publish a logging standard with a mandatory field allowlist and enforce it in shared logging libraries. See the Logging and Monitoring Policy Template.
Framework mapping
| Control | OWASP ASVS 5.0 | NIST SP 800-53 Rev. 5 | Weakness and threat |
|---|---|---|---|
| No tokens in URLs | V14.2.1 | SC-23 | CWE-532; T1528 Steal Application Access Token |
| Exclude or mask tokens in logs | V16.2.5 | AU-9, SC-28 | CWE-532; T1552 Unsecured Credentials |
| No tokens in error output | V16.5.1 | SI-11 | CWE-532 |
| Short-lived, audience-bound tokens | V9.2.1, V9.2.3 | IA-5, SC-23 | T1550.004 Web Session Cookie |
| Session termination and renewal | V7.2.4, V7.4.1 | SC-23 | T1539 Steal Web Session Cookie |
Common misconfigurations
- Logging the whole request: a convenience middleware that dumps headers and cookies on every error.
- Tokens in query strings: download links, webhooks and single-page apps that pass
access_token=in URLs, which then appear in proxy logs, analytics andRefererheaders. - APM header capture left on: tracing configured to record all request headers in production.
- Patch without revoking: the CitrixBleed 2023 incidents showed that stolen session cookies bypass MFA and stay usable after the leak is fixed; the same applies when tokens are found in logs.
- Masking only in the dashboard: the raw event still sits in the index and archive, readable through the API.
- Long-lived refresh tokens in mobile logs: a debug build shipped with verbose logging leaks the most valuable token of all.
Practitioner checklist
- Search current logs, traces and tickets for JWTs, bearer headers, session cookies and token query parameters.
- Remove tokens from URLs across apps, links and webhooks.
- Add field allowlists and header masking to shared logging libraries, and disable wire logging in production.
- Log salted hashes of session IDs where correlation is needed.
- Configure collector or SIEM redaction for JWT and bearer patterns, with summaries off in production.
- Restrict raw log access and treat log readers as privileged users.
- Enable the Gitleaks
jwtrules or equivalent in pre-commit and CI. - Define revocation steps per token type, including signing key rotation for mass exposure.
- Add a canary-token regression test to each service.
Standards and references
- IETF: RFC 6750 The OAuth 2.0 Authorization Framework: Bearer Token Usage
- OWASP: Application Security Verification Standard 5.0
- OWASP: Logging Cheat Sheet
- OWASP: Session Management Cheat Sheet
- MITRE CWE: CWE-532 Insertion of Sensitive Information into Log File
- OpenTelemetry: Redaction Processor
- Gitleaks: Default rule configuration
- TruffleHog: JWT detector
Related NHI Mgmt Group resources: JWT Security Guide · Token Lifetime Policy Design Guide · Session Hijacking and Cookie Theft Guide · OAuth Token Theft Incident Playbook