Regolith: A Server-Side Regex Library Immune to ReDoS Attacks
Have you ever worried that the regular expressions you write might become security vulnerabilities in your services? Have you heard of “Regular Expression Denial of Service (ReDoS) attacks” but weren’t sure what they entailed? Today, we’ll explore an open-source tool that fundamentally addresses this issue—Regolith.
What Are ReDoS Attacks?
Regular Expression Denial of Service (ReDoS) attacks are a special type of denial of service attack that exploits design flaws in certain regex engines when processing specific patterns. When maliciously crafted inputs meet vulnerable regex patterns, they can cause the engine to enter exponentially increasing computational complexity, consuming substantial server resources and rendering services unavailable.
Imagine a simple form validation regex that normally takes milliseconds to process user input. During a ReDoS attack, it might keep the server stuck on that calculation for hours! This attack is particularly dangerous because it doesn’t require massive traffic—just one carefully crafted request can achieve the attack effect.
The Problem with Existing Regex Engines
Most programming languages (including JavaScript and TypeScript) have built-in regex engines that suffer from this problem. They use backtracking algorithms that can exhibit exponential time complexity in worst-case scenarios.
Research shows that with input sizes as small as 30 characters, JavaScript’s standard RegExp engine can take over 10 seconds to process certain malicious patterns. In comparison, linear-time complexity engines handle the same input in less than 1 millisecond.
The Regolith Solution
Regolith is a server-side TypeScript and JavaScript library that fundamentally immunizes against ReDoS attacks by using a linear-time regex engine written in Rust.
Technical Foundation
Regolith’s core strength lies in using Rust’s high-performance regex library. The Rust regex library is carefully designed, intentionally excluding features that make engines vulnerable to ReDoS attacks—primarily backreferences and look-around operations. While this means some advanced features aren’t available, the trade-off guarantees linear execution time.
Why Rust?
The Rust language is renowned for its memory safety and high performance. Rust’s regex library has been widely validated and trusted within the community, used in many scenarios demanding exceptional performance and security. Regolith uses napi-rs to create JavaScript bindings, allowing JavaScript and TypeScript developers to benefit from this powerful engine.
Drop-in Replacement Experience
One of Regolith’s most praised features is its attempt to be a direct replacement for RegExp, requiring almost no code modifications. This means you can easily migrate regex operations in existing projects to Regolith and immediately gain immunity to ReDoS attacks.
Real-World Application Cases
Actual ReDoS Vulnerabilities
The CVE-2025-5889 vulnerability discovered in 2025 affected the brace-expansion library, a popular library used by 42.5 million GitHub projects. This vulnerability wasn’t the project’s fault but rather an inevitable consequence of the language allowing such issues to exist.
Fixing such a vulnerability requires enormous ecosystem effort: multiple versions need backward compatibility, and each project using the library requires updates, testing, and deployment. If everyone kept their software updated, this would mean 42.5 million pull requests, approximately 42.5 million build minutes, and potentially over 42 million engineering hours.
Using an immune library like Regolith can solve all such potential problems at once, saving massive resources for the entire ecosystem.
Getting Started with Regolith
Installation
Installing Regolith is straightforward—just run:
npm i @regolithjs/regolith
Basic Usage
Using Regolith is very similar to using standard RegExp:
import { Regolith } from '@regolithjs/regolith';
// Create a regex pattern
const pattern = new Regolith("^\\d+$");
// Test using the pattern
pattern.test("12345"); // Returns true
pattern.test("Hello"); // Returns false
Complete Feature Examples
Regolith supports all common regex operations:
Matching Example
import { Regolith } from '@regolithjs/regolith';
const pattern = new Regolith('crab', 'g');
console.log(pattern.test('my crab ferris')); // Output: true
Finding All Matches
const sentence = 'crab, snail, crab';
const crabPattern = new Regolith('crab', 'g');
console.log(crabPattern.match(sentence));
// Output: ['crab', 'crab']
Replacement Operations
const sentence = 'crab, snail, crab';
const crabPattern = new Regolith('crab', 'g');
console.log(crabPattern.replace(sentence, 'snake'));
// Output: 'snake, snail, snake'
Search Operations
const sentence = 'crab, snail, crab';
const snailPattern = new Regolith('snail');
console.log(snailPattern.search(sentence));
// Output: 6 (index where 'snail' is found)
Split Operations
const splitPattern = new Regolith('[,\\|]');
console.log(splitPattern.split('apple,banana|orange'));
// Output: ['apple', 'banana', 'orange']
Express.js Integration Example
Here’s a complete example of using Regolith in an Express.js application:
import express from "express";
import { Regolith } from "@regolithjs/regolith";
const app = express();
const port = 3000;
// Create Regolith regex patterns
const intPattern = new Regolith("^\\d+$");
const floatPattern = new Regolith("^\\d*\\.\\d+$");
app.get("/check", (req, res) => {
const value = req.query.value;
if (!value) {
return res.status(400).send("Please provide a value query parameter");
}
// Test using Regolith patterns
const isInt = intPattern.test(value);
const isFloat = floatPattern.test(value);
res.json({
value,
isInt,
isFloat,
});
});
app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
});
This simple API endpoint checks whether the input value is an integer or float, and it’s completely immune to ReDoS attacks.
Development and Building
If you want to contribute to Regolith’s development or build the library yourself, here are the required steps:
Prerequisites
-
Install the yarn package manager -
Install the Rust toolchain (via rustup)
Build Process
# Clone the project
git clone https://github.com/JakeRoggenbuck/regolith.git
# Install dependencies
yarn install
# Build the project
yarn build
The build process compiles the Rust code and generates necessary binding files.
Testing
Regolith includes a complete test suite:
# Test the TypeScript/JavaScript library
yarn test
# Test Rust bindings
cargo test
Currently, 93 test cases ensure the library’s stability and correctness.
Platform Compatibility
Regolith has been tested on multiple platforms, including:
Current Limitations and Future Plans
Browser Compatibility
Currently, Regolith primarily focuses on server-side JavaScript and TypeScript applications since servers are the main targets of ReDoS attacks. Some challenges remain for client-side usage (such as React’s “use client”), mainly related to native library linking.
The team is actively addressing this issue, potentially through WebAssembly or developing a custom regex engine. This progress can be tracked via issue #40.
Feature Trade-offs
By choosing a design that guarantees linear time complexity, Regolith doesn’t support some advanced regex features:
-
Backreferences -
Look-around operations
This trade-off has proven worthwhile in the Rust community. Most application scenarios don’t require these advanced features, while the security and performance benefits are substantial.
Frequently Asked Questions
Is Regolith Fully Compatible with Standard RegExp?
Regolith attempts to be a direct replacement for standard RegExp but with two important differences: it doesn’t support backreferences and look-around operations, and it guarantees linear time complexity, making it immune to ReDoS attacks. For most use cases, migrating to Regolith requires no code changes.
Why Choose Rust Over Other Languages?
Rust’s regex library has been extensively validated and optimized, offering exceptional performance and security. Creating bindings through napi-rs allows the JavaScript ecosystem to enjoy these advantages without reinventing the wheel.
Does Regolith Affect Performance?
In most cases, Regolith’s performance matches or exceeds standard RegExp. Only when handling certain complex patterns might there be functional limitations due to unsupported advanced features, but this trade-off brings significant security improvements.
How to Report Bugs or Contribute Code?
If you find bugs, you can email bug@jr0.org
or submit an issue on GitHub. Community contributions and suggestions are welcome.
Origin of the Project Name
The name Regolith comes from geology, referring to the layer of dust and rock covering a planet’s surface. The author likely encountered this term while studying dinosaurs and was looking for words starting with “reg.”
Motivation and Background
Regolith was inspired by undergraduate research into why some languages are vulnerable to ReDoS attacks while others aren’t. The author encountered a puzzling question: “Why aren’t the most popular regex libraries for languages like TypeScript, JavaScript, and Python using linear-time engines?”
The JavaScript ecosystem does have some libraries addressing this issue, such as re2js and node-re2, which wrap Google’s RE2 library. However, they either have different APIs or low adoption rates. The vast majority of projects still use default regex engines, making them vulnerable to ReDoS attacks.
Regolith aims to provide a direct replacement solution that allows developers to avoid worrying about ReDoS attacks while minimizing migration costs.
Conclusion
Regolith represents a pragmatic security approach: using proven technology (Rust’s regex engine) and simple drop-in replacement APIs to provide JavaScript and TypeScript ecosystems with immunity to ReDoS attacks.
While it requires trading off some advanced features, this trade-off is worthwhile for most application scenarios. As cybersecurity threats grow increasingly sophisticated, adopting tools like Regolith that are designed with security fundamentals in mind will be crucial for building resilient systems.
Whether you maintain a large library used by millions of projects or simply write simple form validations, Regolith can help you avoid potential service disruptions and security incidents, allowing you to focus more on building features rather than worrying about security vulnerabilities.