Safeguard
Vulnerability Analysis

CVE-2018-18074: requests library leaks Authorization head...

The Python requests library leaked Authorization headers on same-host HTTPS-to-HTTP redirects, exposing credentials to sniffing before v2.20.0.

Vikram Iyer
Security Researcher
8 min read

In October 2018, maintainers of the Python requests library shipped a fix for a quiet but serious credential-exposure bug: under certain redirect conditions, requests would continue sending the Authorization header even after a request was redirected from HTTPS to plain HTTP on the same host. The issue was assigned CVE-2018-18074, and it's a textbook example of how convenience defaults in HTTP client libraries can turn into a python requests authorization header leak that silently exposes API tokens, bearer credentials, and basic-auth secrets to anyone positioned to observe network traffic.

requests is one of the most widely used libraries in the Python ecosystem — it sits underneath countless SDKs, CLI tools, CI/CD scripts, and backend services that talk to internal and third-party APIs. A bug in its redirect handling doesn't just affect one application; it affects every dependency tree that touches it, which is precisely why this CVE is worth revisiting even years later. Supply chain risk isn't only about malicious packages — it's also about widely-vendored, quietly-outdated versions of trusted libraries still running in production.

What Went Wrong

When an HTTP client follows a redirect, it has to decide which headers from the original request to carry forward to the new request. Carrying forward headers like Authorization is sometimes necessary for legitimate same-host redirect flows (for example, a server normalizing a URL path), but it becomes dangerous the moment the redirect target differs from the original request in a security-relevant way — most obviously, when the protocol changes from HTTPS to HTTP.

According to the public vulnerability description, versions of requests prior to the fix would send the Authorization header to an http:// URI following a same-hostname HTTPS-to-HTTP redirect. In other words, even though the hostname didn't change, the protocol did — and requests did not strip the credential header before making that downgraded, unencrypted request.

The practical impact is straightforward: an attacker capable of observing network traffic (a classic man-in-the-middle or SSL-stripping position — on a shared Wi-Fi network, a compromised router, or a malicious intermediate proxy) could force or wait for a same-host redirect from HTTPS to HTTP and then sniff the Authorization header in plaintext off the wire. For applications authenticating to APIs with long-lived bearer tokens or static API keys, that's a direct credential theft path — no exploitation of the target service itself required, just a favorable position on the network path.

This is also a good example of why "credential leak" bugs in HTTP libraries are disproportionately dangerous compared to their apparent simplicity: the vulnerable code path doesn't require an attacker to compromise your application or your server. It only requires them to be somewhere on the path between your client and the destination host, and for your code to be relying on the library's default redirect-following behavior — which almost all requests-based code does, since allow_redirects=True is the default for most request methods.

Affected Versions and Components

  • Component: requests (the requests PyPI package for Python), maintained by the Python Software Foundation-adjacent open source community (originally authored by Kenneth Reitz).
  • Affected versions: Versions of requests prior to 2.20.0.
  • Fixed version: 2.20.0, released in October 2018, which corrected the redirect header-stripping logic so that Authorization (and related sensitive headers) are no longer forwarded across a same-host HTTPS-to-HTTP downgrade.
  • Indirect exposure: Any project pinning requests<2.20.0 directly, or depending on it transitively through an SDK, CLI tool, or framework that vendors or pins an old version, inherits the vulnerability. Given how foundational requests is in the Python packaging ecosystem, this includes a long tail of internal tooling, data pipelines, and third-party client libraries that may still be running old pinned versions years after the fix shipped.

If your organization has legacy services, data science notebooks, ETL jobs, or internal automation scripts written years ago and never touched since, there's a real chance some of them still resolve to a pre-2.20.0 requests version in a frozen requirements.txt, a vendored venv, or a container image built from an old base layer.

Severity: CVSS, EPSS, and KEV Context

Public vulnerability databases classify CVE-2018-18074 as a Medium-severity issue. The risk calculus reflects the fact that exploitation isn't remote-code-execution or unauthenticated takeover — it requires a network position capable of intercepting traffic and a same-host redirect from HTTPS to HTTP actually occurring in the target application's traffic pattern. That's a real-world constraint: well-behaved APIs that only ever redirect within HTTPS, or that don't redirect at all, are not exposed by this specific code path even on a vulnerable requests version.

That said, "Medium severity" understates the value of what's actually at risk in the worst case: a leaked Authorization header can mean a leaked API key, OAuth bearer token, or basic-auth credential — any of which can be replayed by the attacker to impersonate the original client against the target service, independent of any other vulnerability.

CVE-2018-18074 is not listed in CISA's Known Exploited Vulnerabilities (KEV) catalog, and there is no public evidence of widespread active exploitation campaigns targeting it specifically. It's the kind of vulnerability that is more often surfaced today by dependency and SCA (software composition analysis) scanners flagging an old pinned version than by incident responders finding it as the root cause of a breach — which makes proactive dependency hygiene the most effective control here, rather than reactive detection.

Timeline

  • Pre-2018: The redirect-handling logic in requests' sessions.py forwards the Authorization header on same-host redirects without accounting for an HTTPS-to-HTTP protocol downgrade.
  • 2018: The issue is identified and reported to the requests maintainers as a security concern affecting credential confidentiality during redirects.
  • October 2018: requests 2.20.0 is released, fixing the header-stripping behavior so that sensitive headers are no longer sent across a same-host scheme downgrade during redirect handling.
  • CVE-2018-18074 is published in the National Vulnerability Database, formalizing the public record of the issue for tracking and dependency-scanning purposes.
  • Ongoing: The fix has shipped in every requests release since 2.20.0. The residual risk today is entirely a function of organizations still running or transitively depending on pre-2.20.0 versions.

Remediation Steps

  1. Upgrade requests to 2.20.0 or later. This is the definitive fix. Check pip show requests (or your lockfile) across every service, script, and container image in your environment — not just your primary application repos.
  2. Audit transitive dependencies. Many SDKs and internal libraries pin their own requests version. Run pip list --outdated or a dependency graph tool (pipdeptree, pip-audit) to find indirect installations of old requests versions hiding inside other packages.
  3. Rebuild and redeploy stale container images. If your Docker images were built from a base layer with an old requests version baked in months or years ago, a code change alone won't fix it — the image needs to be rebuilt against updated dependencies.
  4. Enforce HTTPS-only communication where possible. Independent of this specific CVE, configure clients and servers to avoid HTTP fallback entirely, and use HSTS on server-side endpoints so browsers and HTTP clients refuse to downgrade in the first place.
  5. Rotate credentials if exposure is plausible. If you find evidence of a vulnerable requests version having been in production alongside untrusted network paths (public Wi-Fi-adjacent infrastructure, shared cloud tenancy, compromised proxies), treat any Authorization tokens used during that window as potentially exposed and rotate them.
  6. Add dependency scanning to CI. Tools like pip-audit, safety, or a broader SCA platform should fail builds when a known-vulnerable version of a core library like requests is present in the resolved dependency tree, so this class of issue doesn't silently persist for years.

How Safeguard Helps

CVE-2018-18074 is a good illustration of a recurring supply chain security problem: the vulnerable component isn't a niche package nobody has heard of — it's one of the most trusted, widely-used libraries in the Python ecosystem, and the risk comes almost entirely from staleness, not from anything wrong with how the ecosystem maintains it today.

Safeguard's software composition analysis continuously inventories every dependency across your codebases, container images, and build artifacts — including transitive dependencies buried three or four layers deep inside an SDK you didn't even know pinned an old requests version. Rather than relying on point-in-time audits, Safeguard flags known-vulnerable versions like pre-2.20.0 requests as soon as they're detected, maps which services and deployment artifacts are actually affected, and prioritizes remediation based on real exposure — for example, distinguishing a service that authenticates to external APIs over redirect-prone connections from one that never redirects at all.

Safeguard also helps close the gap between "patched in the manifest" and "patched in production." Because vulnerabilities like this one frequently persist in frozen container base images or unrebuilt deployment artifacts long after the source repository has been updated, Safeguard's pipeline and registry scanning verifies that fixed versions have actually propagated into what's running, not just what's declared in a requirements.txt. For SOC 2-minded engineering teams, that closes a real audit gap: demonstrating not just that a vulnerability was identified, but that it was verifiably remediated across every environment where the affected library shipped.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.