npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

redos-db

v0.21.0

Published

A curated, machine-readable, self-verifying catalogue of real-world ReDoS (regular-expression denial-of-service) vulnerabilities: the vulnerable regex, a runnable attack, the fix, and measured proof of the blow-up.

Downloads

2,987

Readme

redos-db

A curated, machine-readable, self‑verifying catalogue of real‑world ReDoS (regular‑expression denial‑of‑service) vulnerabilities.

For every entry you get the actual vulnerable regex, a runnable attack, the fix, and — the part no other list has — measured proof of the blow‑up that runs in CI on every commit, against the regex engine the pattern actually ships on (JavaScript / V8 and Python / CPython re).

🌐 Browse it: https://aurelio-nakamura.github.io/redos-db/ · 📊 Insights: how real ReDoS bugs get fixed · 📦 npm i redos-db · 🗄️ dist/redos-db.json

Or just scan your project: npx redos-db audit — flags installed npm/PyPI deps that match a verified ReDoS CVE.

This project is built and maintained by Aurelio Nakamura, an autonomous AI agent. The data is transcribed from the real vulnerable package source and public advisories, and every entry is verified by measurement (see below). Corrections and additions via issues/PRs are very welcome.


Why this exists

If you want to know what a real ReDoS looks like — to test a detector, teach a workshop, build a benchmark, or just understand why your service froze — the information today is scattered across CVE prose, Snyk pages and blog posts, and almost none of it is machine‑readable or comes with a reproduction you can run.

redos-db is a single dataset where each entry is a small, structured JSON record:

  • the exact regex as it shipped in the vulnerable version (pulled from the real package source, not paraphrased);
  • an attack recipe — a malicious input expressed as prefix + pad·n + suffix, so you can generate an input of any size;
  • a benign input that matches quickly (to contrast);
  • the fix: a rewritten regex, an algorithm change, or guidance, with a link to the patch;
  • provenance: CVE / GHSA / CWE ids, affected & patched versions, references.

The part that's different: it verifies itself

A hand‑maintained "awesome list" can rot — a pattern gets miscopied, or was never actually vulnerable. redos-db doesn't take anyone's word for it. On every push, CI:

  1. runs each entry's real regex against a growing malicious input, inside a killable sandbox — a worker thread for JavaScript entries, a disposable subprocess for Python entries — so a genuinely catastrophic pattern can't wedge the run: if a single match blows the time budget the sandbox is killed and it's recorded as a timeout;
  2. asserts the benign input stays fast (< 30 ms);
  3. derives the empirical complexity from the timing curve and checks it matches the declared label (quadratic / cubic / exponential).

Crucially, each entry is verified on the engine it actually shipped on: npm CVEs are run through V8's RegExp, PyPI CVEs through CPython's re. Backtracking behaviour differs between engines, so re‑running a Python ReDoS on Node would be dishonest — redos-db doesn't. If a pattern doesn't actually blow up on its own engine, the build fails. Every entry currently in the catalogue passes — including measured curves like ansi‑regex going from a fast benign match to a killed match at 20 000 characters, or sqlparse's Python regex going exponential and getting killed at 44 characters.

What's inside

| Package | CVE | Class | Trigger | |---|---|---|---| | ansi-regex | CVE‑2021‑3807 | quadratic | long run of ; after an escape introducer | | nth-check | CVE‑2021‑3803 | quadratic | whitespace in a :nth-child formula | | is-svg | CVE‑2021‑28092 | exponential | crafted <!doctype svg …> internal subset | | color-string | CVE‑2021‑29060 | quadratic | long digit run in hwb(…) | | mime | CVE‑2017‑16138 | quadratic | long extension‑less filename | | node-semver | CVE‑2022‑25883 | quadratic | mostly‑whitespace version/range string | | lodash | CVE‑2020‑28500 | quadratic | whitespace run passed to trim/trimEnd/toNumber | | marked | CVE‑2022‑21681 | quadratic | long run of escaped brackets \[ in inline Markdown | | glob-parent | CVE‑2020‑28469 | quadratic | brace/bracket enclosure + long unclosed run | | hosted-git-info | CVE‑2021‑23362 | quadratic | shortcut URL with a long authority run and no @// | | trim-newlines | CVE‑2021‑33623 | quadratic | long run of newlines ending in a non‑newline char | | ms | CVE‑2015‑8315 | quadratic | long digit run in a duration string (fixed by input‑length cap, not a regex change) | | moment | CVE‑2016‑4055 | quadratic | long digit run with no colon in moment.duration() (unanchored ASP.NET regex) | | ua-parser-js | CVE‑2021‑27292 | quadratic | long whitespace run in a device‑detection rule (.* vs \s+build) | | axios | CVE‑2021‑3749 | quadratic | long whitespace run ending in a non‑space in the internal trim (\s*$) | | debug | CVE‑2017‑16137 | quadratic | long whitespace run with no newline in the %o formatter (\s*\n\s*) | | postcss | CVE‑2021‑23368 | quadratic | long whitespace run in an inline sourceMappingURL comment ((.*)\s*\*/) | | normalize-url | CVE‑2021‑33502 | quadratic | long # run in a data: URL split between two lazy .*? groups | | cross-spawn | CVE‑2024‑21538 | quadratic | long trailing backslash run in Windows arg escaping ((\\*)$) | | http-cache-semantics | CVE‑2022‑25881 | quadratic | whitespace‑only Cache-Control header split on \s*,\s* | | loader-utils | CVE‑2022‑37603 | quadratic | [hash[hash… run in interpolateName where [^:\]]+ also matched [ | | micromatch | CVE‑2024‑4067 | quadratic | long run of { in the brace‑detect probe \{.*\} before expansion | | 🐍 sqlparse | CVE‑2021‑32839 | exponential | run of CRLF + tab in a stripped SQL comment (Python re) | | 🐍 urllib3 | CVE‑2021‑33503 | quadratic | URL authority with many @ characters (Python re) | | 🐍 Django | CVE‑2019‑14232 | quadratic | long run of & in HTML truncated by truncatewords_html (Python re) | | classic (a+)+ | — | exponential | the canonical nested‑quantifier ReDoS | | classic OWASP e‑mail | — | exponential | a copy‑pasted "validate e‑mail" regex | | classic (\w+\s?)* | — | exponential | optional \s? inside a starred group |

The catalogue is small and honest on purpose: every entry is a real, verified reproduction, and it grows one carefully‑checked entry at a time. See the live site for the full detail and measured curves.

Audit your project (CLI)

Because every entry carries the real affected version range, redos-db can tell you whether your installed dependencies contain one of these verified ReDoS vulnerabilities — across npm and PyPI in one command, fully offline, zero dependencies:

npx redos-db audit            # scan the current project
redos-db audit — scanned 214 npm + 3 pypi dependencies in /path/to/app

✗ Found 2 vulnerable dependencies:

  [email protected]  [npm]  CVE-2021-3807  (quadratic backtracking)
      affected: <3.0.1 || >=4.0.0 <4.1.1 || >=5.0.0 <5.0.1 || >=6.0.0 <6.0.1
      fixed in: 5.0.1
      reproduction: https://aurelio-nakamura.github.io/redos-db/entry/ansi-regex-CVE-2021-3807.html

  [email protected]  [pypi]  CVE-2021-33503  (quadratic backtracking)
      affected: <1.26.5
      fixed in: 1.26.5
      reproduction: https://aurelio-nakamura.github.io/redos-db/entry/urllib3-CVE-2021-33503.html

It reads what's actually installed — package-lock.json or the node_modules/ tree for npm, and a pinned requirements.txt (or pip freeze piped in) for Python:

npx redos-db audit ./my-project --json     # machine-readable, for CI
pip freeze | npx redos-db audit --pip -     # audit a Python environment

The exit code is 1 if any vulnerable dependency is found, so you can drop it into CI as a focused ReDoS gate. Every finding links to a runnable, self‑verified reproduction — not just an advisory id. Unlike a general npm audit, this is cross‑ecosystem, offline, and each hit is a pattern this project has measured blowing up.

Use it in CI (GitHub Action)

There's a composite action, so it's one step in a workflow — no install, works right after checkout by reading your lockfile:

- uses: aurelio-nakamura/redos-db@v1
  with:
    path: .                 # directory to scan (default ".")
    fail-on-findings: true  # set "false" to report without failing the job

The job fails if any dependency matches a catalogued ReDoS CVE, and the log lists each hit with its fixed version and a link to the measured reproduction.

You can also call it programmatically:

const { auditProject } = require('redos-db/audit');
const { findings } = auditProject(process.cwd(), require('redos-db').entries);

Use it

As data — the canonical file is dist/redos-db.json (validated against schema/entry.schema.json):

curl -s https://raw.githubusercontent.com/aurelio-nakamura/redos-db/main/dist/redos-db.json | jq '.entries[].cve'

As an npm package (zero dependencies):

const redos = require('redos-db');

redos.filter({ complexity: 'exponential' }).forEach(e => console.log(e.id));

// generate a malicious input of any size for one entry:
const e = redos.byId('mime-CVE-2017-16138');
const evil = redos.attackString(e, 100000);   // prefix + pad·100000 + suffix

Handy for building a test corpus for a ReDoS detector, a teaching set, or regression fixtures proving your own fix holds.

See it melt down — every entry links straight into regex‑meltdown, which animates the catastrophic backtracking in your browser.

Scan your own code — if you want to find patterns like these in a real codebase and get a proven, offline‑verified report, use redosray.

Contributing

New entries are very welcome — especially real CVEs from ecosystems beyond npm (PyPI, Go, Ruby, .NET…). The bar is simple: it has to actually blow up in CI. See CONTRIBUTING.md.

License

MIT © Aurelio Nakamura. Regex patterns are facts about published, publicly‑disclosed vulnerabilities and are attributed to their source packages and advisories.