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-77281

CVE-2026-77281: Rewrite Placeholder Re-expansion Vulnerability in Caddy Web Server

Amit Schendel
Amit Schendel
Senior Security Researcher

Sep 18, 2026·8 min read·30 visits

Executive Summary (TL;DR)

Caddy's rewrite engine double-evaluates placeholder expressions when rewrite directives end with a literal question mark. Remote attackers can exploit this by injecting placeholder tokens via HTTP headers to extract internal environment variables or read local system files.

A critical double-evaluation vulnerability exists in the rewrite module of the Caddy web server. Under specific configurations where a rewrite directive ends with a literal question mark and processes client-controlled headers, the system performs a secondary expansion pass. This allows attackers to evaluate arbitrary internal placeholder variables, leading to unauthorized disclosure of sensitive environment variables and system files.

Vulnerability Overview

Caddy is an extensible web server written in Go that relies on a structured modular architecture to process incoming HTTP traffic. A core mechanism within this architecture is the Replacer, which dynamically evaluates variable placeholders wrapped in curly braces. This mechanism is frequently used in routing configurations, reverse proxy operations, and rewrite directives to interpolate properties such as request headers, client IP addresses, or environment variables. This dynamic substitution provides administrators with configuration flexibility but also expands the attack surface if user-controlled input flows into the evaluation context.

The vulnerability classified as CVE-2026-77281 resides specifically within the request rewrite processing logic, implemented in modules/caddyhttp/rewrite/rewrite.go. Under typical operations, a rewrite directive modifies the URI of an active request before sending it to downstream handlers. When the rewrite rules utilize client-controlled variables, such as values parsed directly from incoming HTTP headers, Caddy is designed to perform a single substitution pass. However, a structural logic error allows an attacker to bypass this boundary.

By manipulating input headers and exploiting specific rewrite configurations that terminate with a literal question mark, an attacker can coerce the rewrite engine into performing a secondary evaluation pass. This secondary pass treats the resolved string as executable placeholder syntax rather than safe, static text. Consequently, any nested template token injected by the client is processed by the internal evaluation system. The primary impact of this flaw is unauthorized information disclosure, enabling attackers to leak cryptographic secrets, environment variables, or local files.

Root Cause Analysis

The root cause of CVE-2026-77281 is a double-evaluation flaw inside the query parameter separation logic of Caddy's rewrite module. When Caddy processes a rewrite directive, it initializes the Replacer engine to evaluate all defined placeholders. This step converts configuration parameters like {http.request.header.X-Fwd} into their literal string representations. If the rewrite path template terminates with a literal question mark, Caddy's parser performs a string-split operation to isolate the path from the query string.

The split mechanism is designed to handle rewrites where query parameters must be appended or overwritten. When a literal question mark is found, the parser divides the intermediate, post-evaluation URI into two distinct string variables: newPath and injectedQuery. If the configuration did not explicitly define an independent query string, the handler assigns the extracted injectedQuery to the request's internal query variable. This state transition is critical because the newly isolated query string contains raw, un-sanitized client input that has already undergone the first phase of template resolution.

Because of this architectural routing, the extracted query variable is subsequently passed to the buildQueryString function. The primary implementation defect exists here: buildQueryString executes a secondary ReplaceAll call on the query parameters. This secondary evaluation pass operates under the assumption that the input contains un-evaluated configuration-level placeholders. In reality, because of the split operation, the input now contains string content originating from the client, including any curly brace delimiters. Consequently, the Replacer parses these delimiters and evaluates the contained instructions.

Code and Data Flow Analysis

To understand the technical flow, it is helpful to analyze the structural changes applied to modules/caddyhttp/rewrite/rewrite.go. In the vulnerable implementation, the split output was directly assigned to the query variable without modification. The following code comparison highlights the vulnerability and the subsequent sanitation logic introduced in the fix.

// Vulnerable Implementation
newPath, injectedQuery = before, after
if query == "" {
    query = injectedQuery
}

In this state, any opening and closing curly braces present within injectedQuery remained unchanged. When query was evaluated in the downstream function, these characters triggered the Replacer's parser, which extracted the inner key and looked it up against registered system providers. The patched version mitigates this behavior by performing a global string replacement on the extracted substring before assigning it to the query variable.

// Patched Implementation (Caddy v2.11.4)
newPath, injectedQuery = before, after
if query == "" {
    // The injected query came from the first-pass placeholder
    // expansion above, which means any '{' or '}' bytes in it
    // must have come from replacement values (e.g. a request
    // header), not from operator-written placeholder syntax.
    // Escape them so buildQueryString does not re-expand them.
    injectedQuery = strings.ReplaceAll(injectedQuery, "{", "%7B")
    injectedQuery = strings.ReplaceAll(injectedQuery, "}", "%7D")
    query = injectedQuery
}

By replacing the literal curly braces with their percent-encoded representations (%7B and %7D), the patch ensures that the downstream evaluation pass is unable to recognize the character sequence as placeholder delimiters. The Replacer treats the percent-encoded values as safe, static string literals, preventing secondary execution. The following diagram illustrates this data flow during an exploitation attempt:

Exploitation and Proof-of-Concept Analysis

Exploitation of CVE-2026-77281 requires an attacker to satisfy two primary conditions. First, the target Caddy server must be configured with a rewrite rule that ends in a literal question mark and references a client-controlled variable. A common example is a reverse proxy or path router that utilizes incoming request headers to determine backend paths. Second, the attacker must have network access to transmit HTTP requests containing specifically formatted headers to the exposed Caddy listener.

The exploitation technique involves sending an HTTP request where the target header contains a nested placeholder string positioned immediately after a query delimiter. For example, an attacker targeting a header named X-Fwd would construct a payload value such as ok?key={env.CADDY_REWRITE_TEST_SECRET}. When the first-pass expansion occurs, this entire string is resolved as a path element. The split logic then extracts key={env.CADDY_REWRITE_TEST_SECRET} and treats it as a query parameter.

During the second evaluation pass within buildQueryString, Caddy's engine identifies the {env.CADDY_REWRITE_TEST_SECRET} syntax. It queries the system environment variables and replaces the token with the corresponding plaintext secret. If the rewritten request is subsequently forwarded to an upstream server controlled by the attacker, or if the server returns detailed error logs, the sensitive credentials are leaked. This allows unauthenticated, remote attackers to retrieve critical environmental configuration data without authorization.

Impact Assessment and Threat Modeling

The security impact of this vulnerability is primarily classified as low-to-medium-severity information disclosure, reflecting its CVSS score of 6.5. Although the flaw does not directly permit arbitrary code execution on the underlying operating system, the capability to leak environment variables significantly undermines system security. In modern cloud-native deployments, environment variables are frequently used to store sensitive configurations, including database connection strings, third-party API keys, and cryptographic secret keys.

Furthermore, the impact is compounded if specific optional modules are enabled on the Caddy server. For instance, if the local file provider is registered within Caddy's template engine, an attacker can use placeholders such as {file./etc/passwd} to read arbitrary local files. This escalates the vulnerability from basic environment variable disclosure to local file inclusion, potentially exposing sensitive system configuration files, private keys, or application source code.

The CVSS vector for this vulnerability (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:L) underscores that the exploit is highly accessible. It requires no privileges, no user interaction, and has low technical complexity. While the integrity impact is rated as none, the availability impact is rated as low due to potential overhead or crash vectors associated with malformed placeholder parsing inside the core web server loop.

Remediation and Defensive Actions

The definitive resolution for CVE-2026-77281 is upgrading Caddy to version v2.11.4 or later. The patch introduces robust sanitization of the injected query string, preventing any secondary placeholder evaluation. Security administrators should prioritize updating their binary installations using official Caddy distribution channels to ensure all active rewrite loops are secured.

In scenarios where immediate patching is not technically feasible due to production change freezes or compatibility validations, administrative workarounds can be applied. Administrators should inspect their active Caddyfiles to locate rewrite directives that end with a literal question mark and rely on request variables. Modifying these rules to avoid passing client-supplied headers directly into the rewrite path terminates the attack vector.

Additionally, defense-in-depth measures can be deployed at the network layer. Web Application Firewalls (WAFs) should be configured to detect and block incoming HTTP requests containing curly braces inside common headers. A regular expression match targeting patterns like \{[a-zA-Z0-9_\.]+\} in request headers such as User-Agent, Referer, and custom routing headers can effectively neutralize incoming exploitation payloads before they reach the Caddy web server handler.

Official Patches

CaddyserverCaddy Security Advisory for GHSA-j8px-rmrx-76h9
CaddyserverCaddy Pull Request #7761

Fix Analysis (1)

Technical Appendix

CVSS Score
6.5/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:L

Affected Systems

Caddy Web Server

Affected Versions Detail

Product
Affected Versions
Fixed Version
Caddy
Caddyserver
>= 2.8.3, < 2.11.42.11.4
AttributeDetail
CWE IDCWE-94
Attack VectorNetwork (AV:N)
CVSS Base Score6.5
Exploit StatusPoC-stage (Regression tests)
Affected ComponentCaddy rewrite module
ImpactInformation Disclosure (Environment variables, local files)

MITRE ATT&CK Mapping

T1059Command and Scripting Interpreter
Execution
T1203Exploitation for Client Execution
Execution
CWE-94
Improper Control of Generation of Code ('Code Injection')

The software constructs code or execution logic using externally-influenced input, allowing attackers to execute arbitrary instructions or directives.

Known Exploits & Detection

GitHubOfficial regression test cases proving the double placeholder expansion payload behavior.

Vulnerability Timeline

Vulnerability identified and initial fix committed internally.
2026-05-26
Coordinated vulnerability disclosure of GHSA-j8px-rmrx-76h9 / CVE-2026-77281.
2026-09-17
Caddy version 2.11.4 released with the security fix.
2026-09-17

References & Sources

  • [1]https://github.com/caddyserver/caddy/security/advisories/GHSA-j8px-rmrx-76h9
  • [2]https://nvd.nist.gov/vuln/detail/CVE-2026-77281
  • [3]https://github.com/caddyserver/caddy/releases/tag/v2.11.4

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

•2 days ago•CVE-2026-118777
4.8

CVE-2026-118777: Prototype Pollution in Forge HTTP Client Cookie Management

CVE-2026-118777 is a prototype pollution vulnerability (CWE-1321) in the Forge JavaScript cryptography and networking library (distributed on npm as node-forge) prior to version 1.4.1. The flaw resides in the forge.http client subsystem, where incoming HTTP cookie names and paths parsed from Set-Cookie response headers are stored directly into standard JavaScript objects without key validation or property isolation. By returning crafted Set-Cookie headers containing keys such as __proto__ or constructor, a malicious HTTP server can inject arbitrary properties into Object.prototype, attach attributes to the global Object constructor, or delete built-in prototype methods to cause an application-wide denial of service.

Amit Schendel
Amit Schendel
9 views•10 min read
•2 days ago•CVE-2026-118775
3.7

CVE-2026-118775: ASN.1 OID First Arc Truncation and Ambiguity in node-forge

CVE-2026-118775 (GHSA-4642-5mcj-2rqw) is an integer overflow and validation flaw in the ASN.1 serialization module of Forge (node-forge) prior to version 1.4.1. The asn1.oidToDer() function fails to validate the range of the first two arcs of an Object Identifier (OID) and truncates the packed initial subidentifier to a single 8-bit integer. Applications that perform policy checks on untrusted OID strings before encoding them into Distinguished Encoding Rules (DER) format can be tricked into emitting DER bytes that correspond to a completely different, restricted OID.

Amit Schendel
Amit Schendel
10 views•10 min read
•2 days ago•CVE-2026-119194
7.5

CVE-2026-119194: Algorithmic Complexity Denial of Service in pyasn1 Schemaless ASN.1 Decoder

CVE-2026-119194 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting versions 0.3.3 through 0.6.4. The flaw resides in the schemaless decoding routine ConstructedPayloadDecoderBase._decodeComponentsSchemaless used across BER, CER, and DER codecs. By sending an ASN.1 container populated with child components whose tag identifiers are separated by multiples of CPython's integer hash modulus (sys.hash_info.modulus), an unauthenticated attacker can force worst-case hash collisions in an unbounded Python set, degrading decoding performance from O(N) to O(N^2) and causing a Denial of Service (DoS).

Alon Barad
Alon Barad
8 views•9 min read
•2 days ago•CVE-2026-119195
7.5

CVE-2026-119195: Quadratic-Time Denial of Service in pyasn1 BER/CER/DER Decoders

CVE-2026-119195 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting all versions prior to 0.6.5. When decoding constructed strings or indefinite-length ANY types across BER, CER, and certain DER code paths, the payload decoders repeatedly concatenate incoming fragments onto an immutable bytes object using the += operator. Because Python bytes objects cannot be resized in-place, each fragment iteration allocates a new buffer and copies all previously accumulated bytes, resulting in quadratic O(N^2) time and memory copy complexity. An unauthenticated remote attacker can supply a highly fragmented ASN.1 stream to exhaust CPU cycles and stall application worker threads.

Amit Schendel
Amit Schendel
9 views•10 min read
•2 days ago•CVE-2026-119197
7.5

CVE-2026-119197: Quadratic Algorithmic Complexity Denial of Service in pyasn1 REAL Mantissa Decoder

An algorithmic complexity vulnerability (CWE-407) in pyasn1 versions prior to 0.6.5 allows unauthenticated attackers to cause a Denial of Service (DoS) via crafted ASN.1 payloads. The flaw resides in the binary-encoded ASN.1 REAL mantissa deserialization routine within RealPayloadDecoder.valueDecoder. By performing iterative byte-string slicing and repeated bitwise shifts on a growing arbitrary-precision integer, the decoder exhibits quadratic time and memory allocation complexity relative to the mantissa length. Supplying a BER-, CER-, or DER-encoded payload with a large REAL mantissa causes excessive CPU consumption and blocks application worker processes.

Amit Schendel
Amit Schendel
9 views•10 min read
•2 days ago•CVE-2026-119196
7.5

CVE-2026-119196: Quadratic CPU Consumption in pyasn1 Constructed BIT STRING Decoding

A vulnerability classified under CWE-407 (Inefficient Algorithmic Complexity) exists in the pyasn1 library prior to version 0.6.5. When parsing constructed ASN.1 BIT STRING payloads under BER, CER, or schema-driven DER encoding rules, the BitStringPayloadDecoder repeatedly shifts and copies the entire accumulated bit value for each incoming fragment. Processing inputs with a large number of small constructed fragments induces quadratic CPU consumption, allowing unauthenticated remote attackers to cause a denial of service via resource exhaustion during the initial decoding phase.

Alon Barad
Alon Barad
11 views•10 min read