The developer adds ?api_key= to the URL because it is the simplest way to test an endpoint. The credential works. The endpoint returns data. What the developer does not see: that token was written into six distinct stores. It was also queued for transmission to a third-party monitoring service. The assumption that a query parameter token is "just a temporary credential" ignores where it goes before the server even processes it. When a client sends GET /api/data?token=sk_live_abc123, the credential has already been copied to six distinct stores. One Request, Six Copies A URL-embedded token is not one secret transmitted once. It is one secret distributed to every system that touches the HTTP request before and after the server receives it. 1. Server access log. Nginx and Apache write the full URI, including the query string, to access.log by default. Nginx's default log format records $request: method, full path with parameters, and protocol. 2. CDN and proxy logs. Cloudflare, Fastly, and Akamai log the full request URL for traffic passing through them. These logs sit in infrastructure you do not control, with their own retention policies. 3. Browser history. Any visited URL is stored in the browser's local history database. Chrome's SQLite history file records the full URL including query parameters, with a timestamp for each visit. 4. Referer header. If the authenticated page loads any external resource (image, script, font, analytics pixel), the browser sends Referer: https://app.example.com/data?token=sk_live_abc123 to the external server. This happens before any other code runs. 5. Analytics platforms. Google Analytics, Datadog RUM, and Segment collect page URLs with query parameters as pageview metadata. This data lands on third-party servers under contracts you did not negotiate for API credentials. 6. Web archives. CommonCrawl and the Wayback Machine index publicly reachable URLs. Truffle Security found 2.76 million pages with exposed credentials in a single CommonCrawl dataset. The credential's effective lifetime is the maximum of the retention periods across all six stores. Not the TTL you configured on the server. The Referer Vector The Referer header is the most immediate of the six vectors. The credential exits your infrastructure silently and lands on a server you do not control. Consider a page at https://app.example.com/report?token=sk_live_abc123 that loads a Google Fonts stylesheet. The browser sends the full page URL to Google's servers in the Referer header before any application code runs. The Portainer advisory GHSA-jvp4-q659-95mj documented exactly this vector: a JWT passed as a query parameter was accessible to any script with document.referrer access. Princeton's "Third-Party Web Tracking" study found that 85% of the top 10,000 websites load at least one external resource. Each of those requests is a potential Referer leak. The receiving server logs the Referer in its own access log. The token now exists in third-party infrastructure with no audit trail on your side. The document.referrer property also exposes the header to JavaScript on the destination page. Any third-party JavaScript with DOM access on the referenced page can read the token directly. The Spec Said Not to Do This in 2012 RFC 6750 (2012), Section 2.3: "query component parameters are often logged by origin servers as part of the request URI... implementations SHOULD NOT send bearer tokens in query strings." RFC 9700 (2023), Section 4.3.2: "Access tokens MUST NOT be transmitted in the URI query string." The language changed from SHOULD NOT to MUST NOT. The prohibition is 13 years old. Most APIs that accept ?token= or ?api_key= were written after both RFCs. The spec was clear; adoption skipped it. OWASP API Security Top 10 2023 classifies this under API2 (Broken Authentication). Credentials transmitted via insecure channels are among the most frequently observed subcategories. OSINT at Scale: CommonCrawl as a Credential Database CommonCrawl is a public web crawl corpus. For anyone who knows how to query it, it is also a credential database. Truffle Security extracted 11,908 live API keys from the CommonCrawl dataset, verified against provider validation endpoints. A single WalkScore API key appeared 57,029 times across 1,871 distinct subdomains before the Truffle Security team discovered it, a concrete demonstration of how URL-embedded credentials outlive the service that issued them. CommonCrawl's index API allows querying specific URL patterns across the 400 TB corpus. Searching for ?api_key= or ?access_token= in the dataset is a documented OSINT technique with active tooling. The MAGO Intel tool (intel.mago.team) includes CommonCrawl-indexed credential pattern detection during external attack surface enumeration. No credential in a public URL is private. CommonCrawl has likely already indexed it. Two Incidents Where the Teams Did Not Map the Full Log Pipeline RubyGems (July 2020). API keys passed as ?api_key= in RSS feed customization URLs were written to Fastly and Nginx logs. Those logs were forwarded to Honeycomb, creating a telemetry dataset with 407 keys accessible to anyone with query access. The dataset was reachable for 22 months, from October 2018 to July 2020. Bulk rotation was necessary because the keys had propagated into systems the team did not control. Portainer GHSA-jvp4-q659-95mj. Portainer's container management UI passed a JWT as a query parameter to the Docker API proxy endpoint. The token appeared in Nginx access logs on the host. An attacker with log read access, obtained via lateral movement or a separate container escape, could use the harvested JWT to call POST /exec on running containers and achieve remote code execution on the host filesystem. The JWT was valid for 8 hours. Log rotation was irrelevant: the credential was already used. Both incidents required bulk rotation, not patching. The code was correct. The protocol choice was the vulnerability. Remediation Move credentials to the Authorization header: Authorization: Bearer sk_live_abc123. Access logs in common log format do not record request headers. CDN logs require explicit header logging configuration to capture them. Browsers never include request headers in the Referer. Analytics platforms do not collect request headers. The attack surface drops from six stores to near zero. If query parameters are unavoidable (callback URLs, email confirmation links, SAML assertions), set TTL under 5 minutes. Bind to the requesting IP when possible and invalidate immediately after first use. RubyGems adopted scoped, short-lived tokens for RSS feeds after the incident. Set Referrer-Policy: no-referrer on all responses from pages that handle tokens in URLs. This instructs browsers to omit the Referer header on cross-origin requests entirely. For log scrubbing: add redaction rules for credential patterns before log storage. AWS CloudWatch Logs supports data protection policies that redact patterns matching [A-Za-z0-9]{20,} in query parameters. Datadog supports sensitive data scanner rules with equivalent patterns. The six stores do not care about the token's intended lifetime. An access_token= from a one-hour session continues to exist in the CDN log, the Honeycomb dataset, and the Wayback Machine index. Rotate the credential. But first, find out where it already went.