Skip to content

Fix exponential memory exhaustion in regex combination generator #153

Description

@progprnv

Summary

This PR fixes an uncontrolled memory/CPU consumption issue in the regex generation engine used by the origins plugin.

Previously, _gen_combinator() fully materialized the Cartesian product of regex alternation branches into memory using:

list(map(_merge_variants, itertools.product(...)))

A crafted regex with many alternation groups could therefore trigger exponential memory growth (K^N combinations), causing the gixy process to consume excessive RAM or terminate via OOM.

This PR introduces a hard cap on generated combinations and removes redundant recomputation in BranchToken.generate().


Root Cause

The vulnerable flow was:

origins.audit()
  -> Regexp.generate()
      -> InternalSubpatternToken.generate()
          -> _gen_combinator()
              -> itertools.product()
              -> list(...)

Because the Cartesian product iterator was eagerly materialized, patterns like:

(a|b)(c|d)(e|f)... repeated N times

generated exponentially many strings in memory.


Changes

1. Limit Cartesian product expansion

Before

producted = itertools.product(*res)

return list(
    six.moves.map(_merge_variants, producted)
)

After

MAX_COMBINATIONS = 1000

producted = itertools.islice(
    itertools.product(*res),
    MAX_COMBINATIONS
)

return list(
    six.moves.map(_merge_variants, producted)
)

This prevents unbounded expansion from attacker-controlled regex input.


2. Fix redundant branch recomputation

Before

values = child.generate(context)

if isinstance(values, list):
    res.extend(child.generate(context))

After

values = child.generate(context)

if isinstance(values, list):
    res.extend(values)

The previous implementation unnecessarily recomputed child branches, doubling CPU work for some patterns.


Security Impact

This issue could be abused in environments where untrusted users can submit nginx configurations for analysis, including:

  • CI/CD pipelines
  • shared linting infrastructure
  • config auditing services
  • multi-user development systems

A single crafted regex could exhaust memory and crash the analysis process.


Classification

  • CWE-400 — Uncontrolled Resource Consumption
  • CWE-770 — Allocation of Resources Without Limits or Throttling
  • CWE-407 — Algorithmic Complexity

Compatibility

The change preserves existing functionality while preventing pathological expansion cases.

Large regex expansions are now safely truncated to a bounded number of generated combinations.


Testing

Verified against crafted regex payloads containing many alternation groups.

Previously:

  • excessive RAM growth
  • process termination / OOM

After patch:

  • bounded memory usage
  • stable execution

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions