The internet never forgets. That is usually said as a warning to people who post things. It is also a warning to applications that put secrets in their URLs.
In our latest batch of assessments, 36 percent of the companies we attacked had tokens, keys, or signed links that were recoverable from public web archives. This is the seventh finding in our field series, after endpoints that skip authentication, exposed internal tools, forgotten staging environments, secrets in JavaScript bundles, exposed origins, and dead subdomains. This one is about time: a credential that never expires, in a place that never deletes.
What a token in a URL is
A token in a URL is a credential carried in the address itself, where it gets logged, shared, and archived. MITRE tracks it as CWE-598, Use of GET Request Method With Sensitive Query Strings. The URL is not a private channel. It is copied into browser history, server logs, analytics, referrer headers, and, often, the public archives of the web.
A token in a URL is usually there for a good reason: password reset links, magic login links, file shares, order confirmations. The problem is not the feature. The problem is the lifetime and the record.
What an attacker does with it
The attacker does not break anything. They search. Real findings from recent engagements, anonymized:
- A document-handling service issued bearer tokens for orders, quotes, and file shares that never expired. The Wayback Machine had archived real responses containing them: customer details, document filenames, and signed links to the files themselves. Anyone who found the archive had permanent access to real customers' documents.
- A company's authentication tokens, for confirming accounts, magic login, password reset, and invites, were recoverable from public web archives. Tokens that should live for minutes were readable years later.
- Signed storage links sat in archived URLs long after the files they pointed to should have been private.
The search is not sophisticated. It is a query against an archive, or a look at a referrer log, or a shared link in a support ticket that got indexed. The token does the rest, because the token never stopped working.
Worth saying: the applications themselves usually held up. Authentication worked, authorization worked. The leak was in the links the applications handed out, and in the time those links were allowed to live.
Why this is a real problem
A token that never expires is a password that never changes. Put it in a URL, and it is a password that gets written down everywhere: in logs, in history, in analytics, in the archive. The application keeps accepting it, years later, because nobody told it to stop.
The consequences scale with what the token opens. A magic login token is the user's account. A password reset token is the account plus the password. A signed file link is the document. A share token is every document in the share. For a company handling sensitive documents, an archived token is a data breach with a search box.
There is a subtler cost too. These tokens bypass the controls the team built. The application has authentication, authorization, audit logging. The token skips the login page, and the audit trail says "valid token" without saying whose. When the breach is found, the team cannot tell who used the token, or when, or how many times.
Why teams put tokens in URLs
The reason is that the URL is the easiest transport. A link works in an email, a chat message, a support ticket, a browser. There is no API to call, no form to fill. The user clicks, and the feature works. That convenience is real, and it is why the pattern survives.
The mistake is not the URL. It is the combination: a secret in a public channel, with no expiry, and no single-use. Each of those three is a decision made for convenience. Together they are a credential that outlives the customer's relationship with the company.
And the archive is the part nobody planned for. Teams reason about the user, the email, the browser. They do not reason about a crawler saving the response, and a service that never deletes it, and an attacker searching it years later.
How to fix tokens in URLs
The fix is to make the token useless after its moment. Four steps.
Step one. Expire every token. Every token gets a short lifetime: minutes for login and reset, hours for shares, days at most for anything else. The server enforces it, not the client. A token that has no expiry is a credential that never retires.
Step two. Make tokens single-use. A reset link works once. A magic login works once. After use, the token is dead. This turns a leaked token into a race the attacker usually loses, instead of a permanent key.
Step three. Move the secret out of the URL. Put the token in the request body or a header where the transport allows it. Where a link is unavoidable, keep the secret short-lived and single-use, and design the page so the token is exchanged for a session immediately, then gone from the address bar.
Step four. Check the archives. Search public web archives for your own domain and look for tokens, signed links, and query strings that should never have been public. If you find them, revoke the token class, not just the one instance. Then re-check on a schedule, because new links ship with every feature. This is how we work: the check returns when the software changes.
Frequently asked questions
Why are tokens in URLs a security problem?
The URL is a public channel: it lands in browser history, server logs, analytics, referrer headers, and public web archives. A token in a URL is a secret written down everywhere, and if it never expires, it keeps working for anyone who finds a copy.
What is the Wayback Machine?
A public archive that crawls and stores web pages over time. If a page containing a token or signed link was ever public, the archive may hold a copy years later. Attackers search it for credentials the same way they search code repositories.
How long should an authentication token live?
Minutes for login, reset, and confirmation tokens. Hours to days for file shares and invites, with single-use where possible. The rule is simple: a token should expire before an attacker can reasonably find and use a leaked copy.
How do I check if my tokens are in public archives?
Search public web archives for your domain and look for query strings that contain tokens, signed links, or identifiers. Also check your own server logs and analytics for tokens in referrer headers. Anything found is compromised, and the token class should be revoked.
What is a single-use token?
A token that stops working after its first successful use. A reset link works once, then dies. A magic login works once, then dies. Single-use turns a leaked token into a race the attacker usually loses, instead of a permanent credential.
The point
We keep finding tokens in URLs because the URL is convenient and the archive is invisible. The token outlives the email, the session, and sometimes the company that issued it.
If you want to know where you stand, it takes a few minutes. Search a public web archive for your own domain and look for anything that looks like a credential in a query string. Then check whether your tokens expire. If they do not, that is the finding.
And if you would rather have someone search the archives, the logs, and the links for you, and keep searching as new features ship, that is exactly what we do.
Related reading: Everything Your JavaScript Bundle Tells an Attacker — the other place secrets end up in public. And The Finding We Report More Than Any Other — what happens when the token is not even checked.