CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-27959

Hostile Takeover: Dissecting Koa's Host Header Injection

Alon Barad
Alon Barad
Software Engineer

Feb 27, 2026·6 min read·50 visits

Executive Summary (TL;DR)

Koa versions < 2.16.4 and < 3.1.2 utilized a flawed string-splitting method to parse the HTTP Host header. Attackers can inject an '@' symbol to trick the parser into identifying a malicious domain as the hostname. This enables URL spoofing attacks, notably compromising password reset flows.

A high-severity Host Header Injection vulnerability in the popular Node.js framework Koa allows attackers to manipulate context.hostname via malformed headers. By exploiting Koa's naive string-splitting logic, attackers can spoof the hostname used by the application for critical functions like URL generation and routing, leading to password reset poisoning and potential cache poisoning.

The Hook: Minimalism vs. Reality

Koa is often touted as the "elegant," "minimalist" successor to Express. It strips away the bloat, giving you a bare-bones context (ctx) and a promise-based middleware stack. It’s beautiful code. But in the world of security, "minimalism" is often a polite synonym for "we didn't implement the safety rails because they looked ugly."

Here is the problem with minimalism: The HTTP specification is not minimal. It is a sprawling, ancient beast full of optional parameters, legacy authentication schemes, and edge cases that haven't been relevant since the 90s but are still technically valid. Koa's developers fell into a classic trap: assuming that a Host header is always just hostname:port.

CVE-2026-27959 is the result of that assumption. It’s a logic error that allows an attacker to lie to the application about where it is running, simply by confusing the parser with a character that virtually no modern web app expects to see in a Host header: the @ symbol.

The Flaw: Split Decisions

To understand this vulnerability, we have to look at how Koa handles the ctx.hostname property. When a request comes in, the application often needs to know its own hostname to generate absolute URLs (e.g., for email links or OAuth callbacks). Koa derives this from the Host header (or X-Forwarded-Host if trusted).

The vulnerability lies in lib/request.js. The developers needed to strip the port number from the Host header to get the clean hostname. Their logic was effectively this:

// The naive implementation
const host = this.get('Host'); // e.g., "localhost:3000"
if (!host) return '';
if ('[' === host[0]) return this.URL.hostname || ''; // IPv6 handling
return host.split(':', 1)[0];

Do you see the issue? split(':', 1)[0] takes everything before the first colon. This works perfectly for google.com (no colon) and google.com:443 (returns google.com).

But RFC 3986 defines the authority component of a URI as: [ userinfo "@" ] host [ ":" port ]

This means user:password@domain.com is a valid structure. If an attacker sends Host: evil.com:junk@victim.com, Koa's naive parser sees the colon after evil.com, splits there, and returns evil.com. It ignores the fact that evil.com:junk is actually the userinfo part of the authority, and the real host is victim.com.

The Code: The Smoking Gun

Let's look at the actual diff that fixed this. The patch didn't just tweak the regex; it completely capitulated to the complexity of the spec by delegating parsing to the WHATWG URL API.

The Vulnerable Code (simplified):

// Old logic
get hostname() {
  const host = this.get('Host');
  // ... IPv6 checks ...
  return host.split(':', 1)[0]; // The fatal flaw
}

The Fix (v2.16.4 / v3.1.2):

// New logic
get hostname() {
  let host = this.get('Host');
  // ... IPv6 checks ...
  
  // Handle Userinfo confusion
  if (host.includes('@')) {
    try {
      // Wrap in a protocol to make it a valid URL string for parsing
      const url = new URL(`http://${host}`);
      host = url.hostname;
    } catch (e) {
      // If parsing fails, fail safe
      return '';
    }
  } else {
    // Safe to split if no '@' is present
    host = host.split(':', 1)[0];
  }
  return host;
}

The fix explicitly checks for the @ symbol. If present, it stops playing string-manipulation games and constructs a full URL object to parse the string correctly. This is computationally more expensive, but it prevents the bypass.

The Exploit: Stealing Tokens

How do we weaponize this? The most common impact of Host Header Injection is Password Reset Poisoning. Developers love to use ctx.hostname (or req.hostname in Express) to build the link sent in password reset emails.

The Scenario:

  1. Vulnerable Code:

    router.post('/forgot', async (ctx) => {
      const token = generateToken();
      // VULNERABLE: Relies on ctx.hostname
      const link = `${ctx.protocol}://${ctx.hostname}/reset?token=${token}`;
      await sendEmail(ctx.request.body.email, link);
    });
  2. The Attack: The attacker triggers the password reset flow for the victim's email address, but modifies the Host header.

    POST /forgot HTTP/1.1
    Host: attacker.com:xy@victim-site.com
    Content-Type: application/json
     
    { "email": "ceo@victim-site.com" }
  3. The Execution:

    • Koa sees attacker.com:xy@victim-site.com. It splits at the first colon.
    • ctx.hostname becomes attacker.com.
    • The link generated is http://attacker.com/reset?token=....
    • The Email Server receives this link and sends it to the CEO.
  4. The Payoff: The CEO sees an email from the legitimate victim-site.com (because the email sender wasn't spoofed). They click the link, expecting to reset their password. Instead, their browser sends a GET request to attacker.com with the valid reset token in the URL query string. The attacker logs the token, uses it on the real site, and takes over the account.

The Impact: Why Panic?

While this isn't Remote Code Execution (RCE) out of the box, the Integrity impact is high. Host Header Injection is a facilitator vulnerability—it turns innocent features against the user.

  • Password Reset Poisoning: As described above, this is the primary vector. It allows full account takeover without user interaction beyond a click.
  • Cache Poisoning: If a caching proxy sits in front of Koa and keys the cache based on the actual host (victim-site.com) but serves the response generated by Koa (which thinks it's attacker.com), you could poison the cache. Every subsequent user visiting victim-site.com could be served content containing malicious links to attacker.com.
  • OAuth/SSO Redirection: If ctx.hostname is used to validate redirect_uri in OAuth flows, an attacker could bypass whitelist checks or steal authorization codes.

> [!WARNING] > Even with the patch, beware of ctx.origin. The patch fixes ctx.hostname, but ctx.origin (which is often protocol + '://' + host) might still return the raw, tainted header in some contexts or frameworks. Always validate.

The Fix: Remediation

The immediate fix is simple: Upgrade.

  • If you are on Koa v2, upgrade to 2.16.4 or higher.
  • If you are on Koa v3 (beta), upgrade to 3.1.2 or higher.

Defense in Depth: Don't rely solely on the framework to parse headers correctly. The Host header is user input. Treat it like toxic waste.

  1. Configure your Reverse Proxy: Nginx or Apache should be your first line of defense. Configure them to only accept requests for specific, whitelisted server_name entries. If Nginx receives a request for attacker.com, it should drop it before it ever reaches Node.js.
  2. Hardcode URLs: If your app lives at api.example.com, put that in your ENV variables (BASE_URL=https://api.example.com). Use that variable to generate links, not ctx.hostname. Trusting the client to tell you who you are is like trusting a stranger to hold your wallet.

Official Patches

koajsPatch commit for Koa v2

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
EPSS Probability
0.05%
Top 83% most exploited

Affected Systems

Koa Framework (Node.js)

Affected Versions Detail

Product
Affected Versions
Fixed Version
koa
koajs
< 2.16.42.16.4
koa
koajs
>= 3.0.0 < 3.1.23.1.2
AttributeDetail
Attack VectorNetwork (Remote)
CVSS v3.17.5 (High)
ImpactIntegrity (High)
Exploit StatusPoC Available
WeaknessImproper Input Validation
EPSS0.05%

MITRE ATT&CK Mapping

T1566.002Phishing: Spearphishing Link
Initial Access
T1190Exploit Public-Facing Application
Initial Access
CWE-20
Improper Input Validation

Known Exploits & Detection

GitHub AdvisoryAdvisory detailing the PoC logic for Host Header Injection

Vulnerability Timeline

Initial documentation PRs identified issue
2025-11-04
Advisory Published (GHSA-7gcc-r8m5-44qm)
2026-02-25
Patched versions 2.16.4 and 3.1.2 released
2026-02-25
CVE-2026-27959 Published
2026-02-26

References & Sources

  • [1]GitHub Advisory: Host Header Injection in Koa
  • [2]RFC 3986: URI Generic Syntax (Authority)

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•3 minutes ago•GHSA-365W-HQF6-VXFG
9.8

GHSA-365w-hqf6-vxfg: Multiple Critical Vulnerabilities in Crawl4AI Docker API Server

The Crawl4AI Docker API server, in versions 0.8.6 and prior, contains multiple critical vulnerabilities including improper path sanitization, missing authentication on administration routes, hardcoded JWT secrets, and SSRF. These vulnerabilities allow remote, unauthenticated attackers to write arbitrary files, execute arbitrary code, and pivot into private cloud environments.

Amit Schendel
Amit Schendel
0 views•7 min read
•about 3 hours ago•GHSA-534H-C3CW-V3H9
5.5

GHSA-534h-c3cw-v3h9: Local Information Disclosure via Abstract-Namespace Socket in Nuxt Dev Server

A local security vulnerability in the Nuxt development server (nuxt dev) allows local unprivileged users to access sensitive configuration files and source code. On Linux environments running Node.js 20+, Nuxt bound its internal vite-node IPC server to an abstract-namespace Unix socket without any peer authentication, enabling co-resident local users to connect and request module code directly.

Amit Schendel
Amit Schendel
4 views•5 min read
•about 4 hours ago•GHSA-8RFP-98V4-MMR6
0.0

GHSA-8RFP-98V4-MMR6: Protocol-Filtering Bypass via Unicode Obfuscation in Mozilla Bleach

Mozilla Bleach is an open-source HTML sanitizing library for Python. Versions up to and including 6.3.0 contain an incomplete filtering implementation in the URI validation logic ('sanitize_uri_value'). This logic fails to detect disallowed protocols, such as 'javascript:', if they contain Unicode invisible characters, whitespace characters, or characters with a code point greater than U+00A0. While standard-compliant web browsers do not directly execute invalid URI schemes containing these non-standard characters, downstream systems that normalize Unicode text by stripping invisible or non-ASCII characters can unintentionally reactivate the 'javascript:' prefix, causing Cross-Site Scripting (XSS). Additionally, this behavior violates Bleach's core sanitization contract by outputting URIs that bypass protocol allowlists configured by the caller.

Amit Schendel
Amit Schendel
4 views•7 min read
•about 4 hours ago•GHSA-G75F-G53V-794X
4.3

GHSA-G75F-G53V-794X: CPU Exhaustion via Unbounded Email Regular Expression Scanning in Bleach

An uncontrolled resource consumption vulnerability exists in the Python package Bleach when parsing text to linkify email addresses. When `parse_email=True` is enabled, the regular expression engine is forced into a quadratic-time complexity scan on specially crafted payloads lacking an '@' symbol. This causes immediate CPU exhaustion and blocks application server worker processes.

Amit Schendel
Amit Schendel
4 views•6 min read
•about 5 hours ago•GHSA-GR75-JV2W-4656
4.7

GHSA-GR75-JV2W-4656: Path Traversal and Sandbox Escape in LangChain File-Search Middleware and Loaders

A path traversal and sandbox escape vulnerability in LangChain and LangChain-Anthropic Python packages allows unauthenticated local attackers to access files outside the restricted directory via crafted input, symbolic links, or prefix bypasses.

Alon Barad
Alon Barad
3 views•8 min read
•about 5 hours ago•GHSA-M557-WRGG-6RP4
5.8

GHSA-m557-wrgg-6rp4: Server-Side Request Forgery via Authority Information Access (AIA) Chasing in phpseclib

The PHP Secure Communications Library (phpseclib) contains a Server-Side Request Forgery (SSRF) vulnerability due to an insecure default implementation of Authority Information Access (AIA) certificate chasing. This flaw allows remote, unauthenticated attackers to coerce applications validating user-supplied X.509 certificates into generating arbitrary outbound HTTP requests to internal networks or local interfaces.

Amit Schendel
Amit Schendel
4 views•6 min read