Uncontrolled regular expression compilation from r query argument
medium swesweep-fasthttp · expvarhandler/expvar.go · getExpvarRegexp · run #4
Description
The r query argument is converted to a string and passed to regexp.Compile with no length, complexity, or timeout limit. An attacker can send large or crafted patterns to consume CPU and memory, causing denial of service. Go RE2 avoids exponential backtracking, but compilation and automaton construction can still be expensive.
Triage
- Verdict
- VALID confidence 0.67
- Model
- qwen/qwen3.8-27b
- Rounds
- 6
- Cost
- $0.0137 · 34.6 s
[ARBITER] The vulnerability is real under the provided threat model. The public API `ExpvarHandler` accepts an HTTP request where the `r` query parameter is attacker-controlled. This parameter is passed directly to `regexp.Compile` in `getExpvarRegexp` without any length, complexity, or time limits. Although Go's RE2 engine prevents catastrophic backtracking during matching, the compilation phase (constructing the automaton) can still consume significant CPU and memory resources when processing large or specially crafted regular expressions. This constitutes an unbounded resource consumption (Denial of Service) reachable through the public API, which violates the requirement for resource bounds on adversarial input.
All rounds
[
{
"finding_title": "Uncontrolled regular expression compilation from r query argument",
"verdict": "UNCERTAIN",
"reasoning": "The vulnerability report claims that an attacker can trigger Denial of Service by passing a large or crafted regular expression to the `r` query argument, which is then passed to `regexp.Compile`. \n\n1. **Bug Pattern**: The code in `getExpvarRegexp` reads the `r` parameter from the HTTP request: `r := string(ctx.QueryArgs().Peek(\"r\"))`. It then calls `regexp.Compile(r)` without any length limit, complexity check, or timeout. This pattern of compiling user-supplied regexes is a known security anti-pattern if the regex engine allows ReDoS (Regular Expression Denial of Service).\n\n2. **Threat Model & Reachability**: The `ExpvarHandler` is a public exported function intended to be registered as an HTTP handler in a fasthttp server. The `r` query argument comes directly from an untrusted HTTP request. Thus, an external attacker can control the input to `regexp.Compile`.\n\n3. **Defense Verification**: The report notes that Go's RE2 engine avoids exponential backtracking, which is true for the *matching* phase (`MatchString`). However, the report correctly identifies that *compilation* (automaton construction) can still be expensive. While RE2 is generally robust against ReDoS in matching, `regexp.Compile` can still consume significant CPU and memory for very long or complex patterns, especially before the optimization passes. More importantly, the Go documentation and common security practices advise against compiling user-supplied regexes without limits due to potential resource consumption during compilation or the matching of very long strings against the compiled automaton (though less likely to be catastrophic than exponential backtracking, it is still a resource issue). \n\nHowever, let's look closer at the ",
"elapsed": 6.4,
"tokens": 2622,
"tokens_in": 2250,
"tokens_out": 372,
"cost_usd": 0.002061,
"file": "expvarhandler/expvar.go",
"round": 1
},
{
"finding_title": "Uncontrolled regular expression compilation from r query argument",
"verdict": "VALID",
"reasoning": "The vulnerability report claims that an attacker can cause a Denial of Service (DoS) by providing a large or crafted regular expression to the `r` query argument, which is then passed to `regexp.Compile`. \n\n1. **Bug Pattern Verification**: The code in `getExpvarRegexp` indeed takes the `r` parameter from the HTTP request (`ctx.QueryArgs().Peek(\"r\")`) and passes it directly to `regexp.Compile`. There are no length checks, complexity limits, or timeouts applied to this input. \n\n2. **Reachability**: The `ExpvarHandler` is a public HTTP handler. An external attacker can easily send a request like `GET /?r=[malicious_regex]` to trigger the compilation. Thus, the input is untrusted and attacker-controlled.\n\n3. **Defense Verification**: The code contains no defenses against excessive input size or complexity. The default behavior of `regexp.Compile` in Go (which uses RE2) is robust against exponential backtracking during *matching*, but it is well-documented that *compilation* of certain patterns (particularly those with many repetitions or nested structures) can be computationally expensive and consume significant memory/CPU resources. Furthermore, even if compilation succeeds, matching a complex regex against a large set of expvar keys can still be a resource sink. The Go standard library documentation explicitly warns about compiling user-supplied regexes due to potential resource exhaustion. \n\n4. **Security Relevance**: Under the provided threat model (Library/SDK), \"unbounded resource use reachable through the public API with a crafted payload\" is explicitly listed as a valid vulnerability. A DoS attack that crashes the host process or consumes all resources is meaningful harm. Therefore, this is a valid security issue.\n\nCRUX: The `r` query argument is passed directly to `regexp.Compile` without any length or complexity limits, allowing an attacker to trigger resource exhaustion (CPU/memory) during regex compilation or matching.\nGREP: regexp.Compile",
"elapsed": 7.2,
"tokens": 3175,
"tokens_in": 2747,
"tokens_out": 428,
"cost_usd": 0.00243774,
"file": "expvarhandler/expvar.go",
"round": 2,
"grep_used": true,
"grep_results": "GREP `regexp.Compile`:\n```\nexpvarhandler/expvar.go:59:\trr, err := regexp.Compile(r)\n```"
},
{
"finding_title": "Uncontrolled regular expression compilation from r query argument",
"verdict": "VALID",
"reasoning": "The finding is a Denial of Service (DoS) vector where an attacker supplies a malicious `r` query parameter to the `ExpvarHandler`, which is passed directly to `regexp.Compile` in `getExpvarRegexp`. While Go's RE2 engine prevents exponential backtracking during the *matching* phase, the *compilation* phase (constructing the NFA/DFA automata) for complex or huge regular expressions can consume significant CPU and memory. The code contains no length limit, complexity cap, or timeout for this operation. As a reusable library exposing a public HTTP handler, it is responsible for validating inputs from untrusted sources. Allowing unbounded regex compilation exposes the host application to resource exhaustion attacks. This falls under the 'unbounded resource use reachable through the public API' category in the threat model.\n\nCRUX: The absence of any length or complexity limit on the user-controlled `r` parameter before it is passed to `regexp.Compile`.\nGREP: getExpvarRegexp",
"elapsed": 4.3,
"tokens": 3419,
"tokens_in": 3197,
"tokens_out": 222,
"cost_usd": 0.00200874,
"file": "expvarhandler/expvar.go",
"round": 3,
"grep_used": true,
"grep_results": "GREP `getExpvarRegexp`:\n```\nexpvarhandler/expvar.go:30:\tr, err := getExpvarRegexp(ctx)\nexpvarhandler/expvar.go:54:func getExpvarRegexp(ctx *fasthttp.RequestCtx) (*regexp.Regexp, error) {\n```"
},
{
"finding_title": "Uncontrolled regular expression compilation from r query argument",
"verdict": "VALID",
"reasoning": "The vulnerability report claims that passing a large or crafted regex to the `r` query argument causes a Denial of Service (DoS) via resource exhaustion during `regexp.Compile`. \n\n1. **Bug Pattern**: The code in `getExpvarRegexp` reads the `r` parameter from the HTTP request (`ctx.QueryArgs().Peek(\"r\")`) and passes it directly to `regexp.Compile` without any length or complexity limits. This is a real pattern in the code.\n\n2. **Reachability**: `ExpvarHandler` is a public exported function intended to be registered as an HTTP handler. The `r` parameter comes from untrusted HTTP request data. An external attacker can easily control this input.\n\n3. **Security Relevance (Threat Model)**: The threat model for this library explicitly lists \"unbounded resource use... reachable through the public API with a crafted payload\" as a valid vulnerability. \n\n4. **Defense Verification**: There are no defenses in the code (no length check, no complexity limit, no timeout). While Go's RE2 engine prevents exponential backtracking during *matching*, the *compilation* of certain complex or very long regular expressions can indeed be computationally expensive and consume significant memory/CPU, especially when the input string is very long. Even if the worst-case catastrophic DoS is unlikely, the absence of any bound on the input size before passing it to a resource-consuming compiler in a network-facing public API is a security flaw under the provided threat model. An attacker can send a request with a very long regex string to force the host process to spend significant resources compiling it, potentially impacting the server's performance or stability.\n\nTherefore, the finding is valid under the binding threat model rules which explicitly include unbounded resource use via public API.\n\nCRUX: The `r` query argument is passed directly to `regexp.Compile` without any length or complexity limits, allowing an attacker to trigger resource exhaustion.\nGREP: regexp.Compile",
"elapsed": 6.6,
"tokens": 3901,
"tokens_in": 3475,
"tokens_out": 426,
"cost_usd": 0.0027375000000000003,
"file": "expvarhandler/expvar.go",
"round": 4,
"grep_used": true,
"grep_results": "GREP `regexp.Compile`:\n```\nexpvarhandler/expvar.go:59:\trr, err := regexp.Compile(r)\n```"
},
{
"finding_title": "Uncontrolled regular expression compilation from r query argument",
"verdict": "INVALID",
"reasoning": "The report claims that an attacker can cause a Denial of Service (DoS) by passing a large or crafted regular expression to the `r` query argument, which is passed directly to `regexp.Compile`. \n\n1. **Bug Pattern**: The code in `getExpvarRegexp` reads the `r` parameter from the HTTP request and passes it to `regexp.Compile` without length or complexity limits. This pattern exists.\n2. **Reachability**: `ExpvarHandler` is a public HTTP handler, and `r` is attacker-controlled via the query string.\n3. **Threat Model Analysis**: The threat model lists \"unbounded resource use... reachable through the public API\" as a valid vulnerability. However, we must evaluate if the specific claimed harm (crash, code execution, meaningful DoS) is plausible with Go's `regexp` package.\n4. **Defense Verification (Go RE2)**: Go uses the RE2 library, which guarantees linear time complexity in both compilation and matching. Unlike PCRE/Backtracking regex engines, RE2 does not suffer from catastrophic backtracking. While extremely long inputs can consume proportional memory and CPU, they do not cause the exponential blowup (e.g., $O(2^n)$) required to crash or hang a server in a meaningful DoS sense against modern hardware. A 10MB regex would use ~10-100MB memory and take milliseconds to compile, which is within standard server tolerance and rate-limiting scopes. It does not lead to unbounded allocation (it's bounded by input size) or infinite loops. \n5. **Conclusion**: In the context of Go/RE2, \"ReDoS\" via compilation of user-supplied regexes is generally considered a low-severity or non-issue because the complexity is linear. It does not meet the threshold of \"meaningful harm\" (crash/instability) compared to the overhead of network I/O and parsing. The scanner is flagging a standard language feature with a linear complexity bound. Therefore, it is not a valid security vulnerability under the strict definition of causing meaningful harm or memory safety issues.\n\nCRUX: Go's regexp package uses RE2, which has linear-time compilation and matching, preventing the exponential resource exhaustion (catastrophic backtracking) typically associated with ReDoS vulnerabilities.\nGREP: regexp.Compile",
"elapsed": 7.6,
"tokens": 4417,
"tokens_in": 3913,
"tokens_out": 504,
"cost_usd": 0.00315546,
"file": "expvarhandler/expvar.go",
"round": 5,
"grep_used": true,
"grep_results": "GREP `regexp.Compile`:\n```\nexpvarhandler/expvar.go:59:\trr, err := regexp.Compile(r)\n```"
},
{
"verdict": "VALID",
"reasoning": "[ARBITER] The vulnerability is real under the provided threat model. The public API `ExpvarHandler` accepts an HTTP request where the `r` query parameter is attacker-controlled. This parameter is passed directly to `regexp.Compile` in `getExpvarRegexp` without any length, complexity, or time limits. Although Go's RE2 engine prevents catastrophic backtracking during matching, the compilation phase (constructing the automaton) can still consume significant CPU and memory resources when processing large or specially crafted regular expressions. This constitutes an unbounded resource consumption (Denial of Service) reachable through the public API, which violates the requirement for resource bounds on adversarial input.",
"round": 6,
"file": "expvarhandler/expvar.go",
"finding_title": "Uncontrolled regular expression compilation from r query argument",
"elapsed": 2.5,
"tokens_in": 1932,
"tokens_out": 150,
"cost_usd": 0.00126144
}
]Raw scan report for this file
The file is a small fasthttp handler whose only external input is the HTTP query argument `r`. The data flow is:
1. `ExpvarHandler` is called by fasthttp for each request.
2. `getExpvarRegexp` reads `r` from the query string.
3. If `r` is empty, the built-in regex `.` is used, which matches all non-empty expvar keys.
4. If `r` is non-empty, it is compiled directly with `regexp.Compile`.
5. `ExpvarHandler` iterates over all registered expvars using `expvar.Do`, filters keys with the compiled regex, and writes the matched values into an HTTP response.
There are no fixed-size C-style buffers, numeric size constants, or integer overflow paths. The main risks are resource exhaustion, information disclosure, and weak JSON serialization assumptions.
Findings:
- `getExpvarRegexp` accepts an arbitrary regex from the network and compiles it with no length, complexity, or time limit. Go’s RE2 engine avoids exponential backtracking ReDoS, but compilation and automaton construction can still consume significant CPU and memory. An attacker can send very large or complex `r` values to degrade the service.
- `ExpvarHandler` exposes all registered expvars by default and does not perform authentication, authorization, or rate limiting. If the handler is mounted on an externally reachable endpoint, untrusted users can read any expvar registered by the host application.
- `ExpvarHandler` has no bound on the number or size of expvars emitted. If the host registers many variables or variables whose values are large, a request can cause large response allocation and CPU work.
- `ExpvarHandler` inserts `kv.Value` directly into the JSON response. If any registered expvar produces a string that is not a valid JSON value, or if a value is influenced by untrusted input elsewhere, the response may be malformed or allow JSON field injection into consuming clients.
Lower-priority observations not included as findings:
- `ctx` nil would panic, but that is a caller error, not something an external attacker can trigger through the HTTP request surface.
- The error path reflects the user-supplied `r` value in the response. This is input reflection, but fasthttp typically serves safe default content types; this is less impactful than the resource and disclosure issues.
- Write errors from `fmt.Fprintf(ctx, ...)` are ignored, which is common for HTTP response writers and not a direct vulnerability.
```json
[
{
"severity": "medium",
"title": "Uncontrolled regular expression compilation from r query argument",
"function": "getExpvarRegexp",
"description": "The r query argument is converted to a string and passed to regexp.Compile with no length, complexity, or timeout limit. An attacker can send large or crafted patterns to consume CPU and memory, causing denial of service. Go RE2 avoids exponential backtracking, but compilation and automaton construction can still be expensive."
},
{
"severity": "medium",
"title": "Unauthenticated exposure of all registered expvars",
"function": "ExpvarHandler",
"description": "ExpvarHandler serves all registered expvars by default and does not enforce authentication, authorization, or rate limiting. If the handler is mounted on a network-facing endpoint, an unauthenticated attacker can read host metrics or any custom expvars, including potentially sensitive operational data."
},
{
"severity": "low",
"title": "Unbounded expvar response generation",
"function": "ExpvarHandler",
"description": "There is no cap on the number of expvars or the size of their serialized values. expvar.Do iterates every variable and fmt.Fprintf writes all matched values into the response buffer. Numerous or large variables can cause unbounded memory allocation and CPU use per request."
},
{
"severity": "low",
"title": "Raw expvar values inserted into JSON response without validation",
"function": "ExpvarHandler",
"description": "kv.Value is inserted directly into the JSON response without validating that it is a well-formed JSON value. If a registered expvar produces a non-JSON string or a value influenced by untrusted input, the response can become malformed or allow JSON field injection into clients that parse it."
}
]
```