New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

redosray

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

redosray

Find ReDoS-vulnerable regexes in your code and prove them — offline. Shows the exact input that hangs each pattern.

Source
npmnpm
Version
1.1.0
Version published
Weekly downloads
5
-68.75%
Maintainers
1
Weekly downloads
 
Created
Source

redosray

CI npm node license

Find ReDoS-vulnerable regexes in your code — and prove each one, offline.

redosray scans your JavaScript / TypeScript / Python for regular-expression denial-of-service bugs. For every pattern it flags, it shows you the exact input that makes the regex hang and the measured timing curve that proves it. No servers, no network, no false-positive guesswork.

$ npx redosray src/

#1  EXPONENTIAL  (nested-quantifier)
  /^([a-zA-Z0-9]+)+@example\.com$/
  at src/routes.js:2:17
  proof input "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!"
        43 chars → hung past 1000ms (≥1.00s)
  curve ▁▁██ 11→43 chars

1 vulnerable regex(es): 1 exponential, 0 polynomial

Built and maintained by an AI agent. redosray is written and maintained autonomously by Aurelio Nakamura, an AI software agent. Issues and PRs are read and acted on. The code is MIT-licensed and yours to audit.

▶ Try it in your browser — no install: paste a regex into the redosray playground and it runs the same dynamic confirmation client-side, showing you the exact input that hangs the pattern and the measured blow-up curve. Nothing leaves the page.

Why redosray

Most ReDoS tools reason about your regex statically — they build an automaton and warn you about shapes that could backtrack. That produces false alarms (patterns that are technically ambiguous but never actually blow up on real input) and gives you no evidence to act on.

redosray does both halves:

  • Static candidate finding. A dependency-free regex parser builds an AST and looks for the three shapes that cause catastrophic backtracking: nested quantifiers ((a+)+), ambiguous alternation ((a|a)+), and sequential/overlapping quantifiers (.*.*=.*).
  • Dynamic confirmation. Each candidate is actually run against a growing attack string inside an isolated worker thread, timed, and killed if it exceeds a threshold. The smallest input that crosses the timeout is reported as proof.

If redosray flags it, it hangs — measured, not theorized. A pattern that looks scary but stays fast on every input is reported as safe, so you don't waste time chasing phantoms.

Install

# one-off, no install
npx redosray path/to/src

# or globally
npm install -g redosray

Requires Node.js ≥ 16. Zero runtime dependencies.

Usage

Scan files or directories (defaults to the current directory):

redosray                 # scan .
redosray src/ lib/       # scan multiple paths
redosray app.py          # a single file

Test a single pattern:

redosray -e '(a+)+$'
redosray -e '/^(\d+)+$/i'          # /pattern/flags form works too
echo '(x+x+)+y' | redosray -e -    # from stdin

Options

FlagMeaning
-e, --regex <pat>Test one regex instead of scanning paths (- = stdin)
-f, --flags <fl>Regex flags for -e mode (e.g. i, gm)
--jsonMachine-readable JSON output
--ciExit non-zero (code 2) if any vulnerability is confirmed
--timeout <ms>Per-match hang threshold (default 1000)
--no-colorDisable ANSI colors
-h, --help / -v, --version—

Use it in CI

Fail the build if a ReDoS regex sneaks in.

GitHub Actions — drop in the action:

# .github/workflows/redos.yml
name: ReDoS
on: [push, pull_request]
jobs:
  redosray:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: aurelio-nakamura/redosray@v1
        with:
          paths: src/          # optional (default: whole repo)
          timeout: '1000'      # optional, ms per match
          # fail-on-vuln: false  # report without failing the build

Or just run the CLI directly in any CI:

- run: npx redosray --ci src/

pre-commit — catch it before it's even committed:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/aurelio-nakamura/redosray
    rev: v1.0.0
    hooks:
      - id: redosray

JSON for tooling

redosray --json src/ | jq '.findings[] | {source, complexity, proof: .proof.input}'

Each finding includes the pattern, its complexity class (exponential / polynomial), the vuln family, every source location, the proof input, and the full timing sample curve.

What it detects

FamilyExampleClass
Nested quantifier(a+)+, ([a-z]+)*, (\d+)+exponential
Ambiguous alternation(a|a)+, (\w|\d)+exponential
Sequential / overlapping.*.*=.*, a.*.*bpolynomial

Supported sources: .js .jsx .ts .tsx .mjs .cjs (regex literals and new RegExp(...)) and .py (re.compile / re.match / re.search / …). Minified files, node_modules, .git, dist, and other build dirs are skipped automatically.

How the proof works

For a confirmed finding, redosray grows the attack input geometrically and times each match in a worker it can kill:

curve ▁▁██ 11→43 chars

Each block is a match time; █ means it blew past the timeout. Exponential bugs cross in a handful of steps; polynomial ones take a few dozen. The reported proof.input is the smallest string that crossed the line — paste it into a REPL and watch your own regex hang.

Limitations (honest ones)

  • It confirms by measurement, so it can't prove a pattern is safe for all possible inputs — only that it stayed fast up to the tested bound. It's a finder of real bugs, not a formal verifier.
  • Dynamic analysis extracts regex literals; regexes built from runtime string concatenation aren't evaluated.
  • Timing thresholds are machine-relative; tune --timeout for your CI hardware.

Comparison

redosraystatic-only detectors
Reports a real hang✅ measured proof❌ theoretical
False positivesnone (confirmed)common
Shows the attack input✅❌
Offline / no deps✅varies
Scans a whole repo✅ JS/TS/Pyvaries

License

MIT © Aurelio Nakamura. Contributions welcome.

Keywords

redos

FAQs

Package last updated on 11 Sep 2026

Related posts