# Leaked JWT Token? Invalidate It and Rotate the Key

> JWT token exposed on GitHub? Find out what it grants, make it expire, rotate the signing key and check logs. Step-by-step guide.

Source: https://leakwatch.net/secrets/jwt-token

---

[LeakWatch](/)

[Product](/product)[Live feed](/leaks)[Guides](/secrets)[Blog](/blog)[Free scan](/)

1.  [Home](/)
2.  [Secrets](/secrets)
3.  JWT (JSON Web Token)

Databases & keys · Secret guide

# Leaked JWT (JSON Web Token): what to do in the first hour

Medium severityDetected onlyLast verified October 19, 2026 · 6 min read

A JSON Web Token, or JWT, is a signed string that a server hands out to say “this request comes from this user, with these rights”. Whoever holds a valid one can present it as a bearer credential until it expires, with no password and no second factor. There is no provider to ask for a new one: a token is valid because of its signature and its expiry date, so the way to stop it is to make it expire or to change the key that signs it. First find out what the token grants, because the answer ranges from nothing to full admin access.

[Check your GitHub account for leaked secrets — free](/)

Provider

Other

Severity

Medium

Impact

SaaS account access and billing

Checked live by LeakWatch

No

## What a JWT looks like

A JWT is three parts separated by dots. The first two are base64 text that start with `eyJ`, because they encode a JSON object that begins with `{"`:

```text
eyJ…header.eyJ…payload.signature   JWT: header, payload, signature
```

The header and the payload are **encoded, not encrypted**: anyone can read them. The payload usually holds the user or service it was issued to (`sub`), who issued it (`iss`), its audience (`aud`) and when it expires (`exp`). Those claims tell you what the token is worth. The third part is the signature, which is what stops anyone from changing the claims. A variant that LeakWatch also reports is the same token encoded once more in base64, which begins with `ZXlK`.

Do not paste a live token into an online decoder to read it. Decode it locally, or use the claims you can read in your own code. A token that expired long ago, or one that carries only a public role, is far less serious than one that is still valid and carries an admin role.

## How JWTs get leaked

-   **Hardcoded in test code and fixtures.** A real token copied from a browser session to make a test pass.
-   **Saved API requests.** Exported Postman collections, `curl` commands with an `Authorization: Bearer` header, HAR files and HTTP client history.
-   **Logs and error reports.** A request logged with its headers, then pasted into an issue or a public build log.
-   **Environment files.** Service tokens and API keys that are themselves JWTs, copied into `.env` files and CI settings in a repository.
-   **Client-side code.** A token embedded in a mobile app or in front-end JavaScript. Some are meant to be public, and some are not: see the FAQ.

## What to do in the first hour

1.  **Read the claims locally.** Decode the payload on your own machine. Note who it was issued to, its role or scope, the issuer, and the `exp` date. If it has already expired and carries no long-lived rights, the urgency drops, but the places it came from still need checking.
2.  **Identify the issuer.** Find which service signs it: your own backend, an identity provider, or a platform such as a backend-as-a-service. The fix is made there, not at the place where you found the token.
3.  **Make it unusable.** Choose the strongest option your system offers: revoke the session or the refresh token the JWT came from, add its identifier (`jti`) to a deny list if you keep one, or sign out the user everywhere. If the token is a long-lived service token, delete or regenerate it in the service that issued it.
4.  **Rotate the signing key if the exposure is serious.** Changing the key invalidates **every** token signed with it, including the leaked one. This logs everybody out, so plan for it. If your system uses key identifiers (`kid`), publish a new key and retire the old one. If the key itself leaked, rotation is not optional.
5.  **Shorten token lifetimes.** A token valid for a few minutes costs little when it leaks, and a token valid for a year is a standing credential. Use short expiries with refresh tokens that you can revoke.
6.  **Look for use you did not make.** Search the logs for the token’s subject, session or `jti` around and after the exposure: requests from unfamiliar addresses, unusual endpoints, data exports.
7.  **Clean the repository**: remove the token, add the file to `.gitignore`, and rewrite history if you want to. See [I accidentally pushed an API key to GitHub](/blog/i-accidentally-pushed-an-api-key-to-github).

Not sure what else leaked from the same repository? [Run a free scan](/).

[Not sure what else leaked? Run a free scan.](/)

## Revoke it at the issuer

A JWT has no central revocation list: it is checked by its signature, not by a lookup. Revoking one therefore happens at whatever issued it. For a session token, end the session or revoke the refresh token in your identity provider. For a service or API token, delete or regenerate it in that service’s dashboard. For a token you sign yourself, rotate the signing key, or keep a deny list of identifiers that your servers check on every request. Which of these applies depends on how your application is built, which is why step 2 comes first.

## How LeakWatch detects it

LeakWatch has two rules, JWT and JWT Base64. The first matches the three-part shape, with a header and a payload that both begin with `ey`. The second matches the base64-wrapped form. The severity is **medium**: a JWT is a credential, but its value depends entirely on what it grants and when it expires, and the rule cannot know either. **This type is not checked live**, because a token can only be tested against the service that issued it, and LeakWatch does not know which one that is. Treat a detected token as exposed until you have read its claims and checked its expiry.

LeakWatch detects this format but does **not** check it live: it can tell you the key is exposed, not whether it still works. Assume it does until you have revoked it.

## FAQ

Is a JWT in a public repository always a problem?

No. Some JWTs are public by design. A backend-as-a-service often gives you an “anon” or “public” key that is itself a JWT, meant to sit in client code and protected by access rules on the server. A key with an admin or `service_role` claim, or a user’s session token, is not public. Read the claims before you decide.

Can I just wait for the token to expire?

Only if it expires soon and carries limited rights. A token valid for days or months, or one that grants write access, should be invalidated now. Waiting for the expiry date is waiting for the attacker’s access to run out.

The payload is readable. Does that mean the token is not secret?

The claims are not secret, but the token as a whole still is. Possession of the full string is what grants access, so a token you would not post in public is one you should not commit either.

## Related

-   [SSH / RSA Private Key](/secrets/ssh-private-key)
-   [Database Connection String](/secrets/database-connection-string)
-   [Google API Key](/secrets/google-api-key)
-   [I accidentally pushed an API key to GitHub](/blog/i-accidentally-pushed-an-api-key-to-github)
-   [Which vendors leak most this week](/leaks/trends)
-   [All secret guides](/secrets)

[Get alerted next time a secret leaks — create a free account](/)

LeakWatch is not affiliated with Other.

![Gabriel Diyan, founder of LeakWatch](/brand/Photo-Gabriel-Diyan.webp)

Gabriel Diyan (0xCr0c0)

Cybersecurity student, founder of LeakWatch. I built and run the scanner described here — the detection patterns, the false-positive classifier and the provider validators are mine. [More about who I am](/about).

[GitHub](https://github.com/Leakwatch-Scan) · [X](https://x.com/LeakwatchScan) · [LinkedIn](https://www.linkedin.com/in/gabriel-diyan-80a378375) · [GitHub (personal)](https://github.com/crocogab)

LeakWatch

Secrets leak into public commits every minute. This watches the forges for yours. Built and run by [Gabriel Diyan](/about), a cybersecurity student — [why LeakWatch exists](/about).

Scan

-   [Product](/product)
-   [Live feed](/leaks)
-   [Trends](/leaks/trends)
-   [API docs](/docs)
-   [CI/CD](/docs?tab=ci)

Read

-   [Blog](/blog)
-   [Secret guides](/secrets)
-   [Changelog](/changelog)
-   [About](/about)

Verify

-   [Security](/security)
-   [Privacy](/privacy)
-   [Terms](/terms)
-   [Legal](/legal)
-   [Contact](/contact)
-   [Status](https://status.leakwatch.net)

© 2026 LeakWatch

[GitHub](https://github.com/Leakwatch-Scan)[X](https://x.com/LeakwatchScan)
