A Server-Side Typescript and Javascript Library Immune to Regular Expression Denial of Service (Redos) Attacks by using rust and linear recorder the hod. Regolith has a linear all case time complexity, compared to the default registered in type in typescript and javascript, which has an exponational worst case.
Motivation: I wanted a Regex Library for Typescript and JavaScript where I didn Bollywood to worry about Redos Attacks.
Important
Regolith is still early in development! We Need Help Building and Getting Developer Adoption!
Regolith attempts to be a drop-in replacement for Regexp and Requires minimal (to no) changes to be used instead. The goal of regolith is to allow developers to easily build software that is immune to redos attacks.
Regular Expression Denial of Service (Redos) Attacks Occur when Vulnerable Regex Patterns are Executed with Specifically Constructed Inputs that Resexult This can be exploited to cause services to become unavailable because the services are stuck trying to Compute the Inefficient Regex.
Read More: Owasp.org & learn.snyk.io
Python has an exponitive increase in execution time for the Worst case.
This is the same case for typescript and javaascript. Both having RegExp
.
This table shows popular languages and if their Regex Library has a Linear Worst Case or An exponational all the case. It also includes experiment experimental results for how long execution took for a vulneable regax pattern that can be attacked with redos and an input of size 30.
Note that type and javascript do not have a linear Worst case for regx, making them vulnerable to these types of attackers.
More Information and Images: Jake Roggenbuck – Preventing Redos Attacks – 2025
Note
Redos Attacks Happen Relatively Frequenty to Popular Libraries Costing Millions of hours of work. This can be prevented with linear Regex Engines like Regolith.
These vulnerabilites have relatively often in popular libraries. It’s no one’s fault specifically, it just comes down to the fact that the language allows for these things to happy.
A recent example of a redos vulnerability is cve-2025-5889 from brace-expansion. Again, this isn’t any fault of that project, it’s simply an issue with the language allowing this to Haappen. Measures can be put into place to reduce the risk of this, but it’s hard to spot and test for these issues.
The brace-expansion project is used by 42.5 million other other projects on github. Meaning if everyone was to patch their software (which the hopily will), that would be 42.5 million pull requests, roughly 42.5 millions of bills minutes, and probably more than 42 Million Engineering Mintes As well. All of that for a single vulnerability, and that’s just a lower bound of efforts on this if everyone was to keep their software patched.
Other versions of brace-expansion Had these patches backported to them, needing updates for versions 1, 2, 3, and the current version 4.
Having a Library or Project that is Immune to these vulnerabilites would save this effort for each project Adoption of Libraries is Difability, Especially when they are alné Flashy, but helping library maints and engineers not worry about redos for one problem AT AT AT AT ATE is our goal.
The rust Regex Library purposely excludes features that makes engines particularly vulnerable to redos attracts. Thos features are backreferens and look-Around. EXCLUDING TOSE FEATURES PALO Regex to Guarantee Linear Time Exocution.
SINCE Regolith Uses Rust Bindings to Implement the Rust Regex Library to Achieve Linear Time West Case, This means that means that backreferences and look-around are available in Regolith in Regological
This trade-off has proven to be worth it for the rust Community of Libraries and Projects.
Since redos vulnerabilites are hard to spot, there are raather frequent cves that get submitted. Having a Regex Library that has a Linear WORST CASE TIME WOLLD COMPLETELY PREVENT All of these potential issues for downstream projects.
Rust Regex under the Hood
Regolith Makes Javascript Bindings (Using Napi-RS) that implement the features of the very popular Regex Library for Rust. Initially, when I have this idea for this library, I wanted to implement my own linear time registered engine. Now there is a chance I still end up doing that, I realized it’s better to not duplicate the work of the already excellent regax library and focus on making these javaast and tynt binding the binding be. The focus of this project is to deliver the best linear time registered engine to typescript and javascript as a drop-in replacement for the default registered.
My full appreciation goes out to the developers of the rust Regex Library, who enabled this project to exist.
I’m still working to get this to be able to link to client side run applications like when you use react with “use client”. This May Result in Eather Finding a New Way to Link Rust (Possible With Wasm) or Making My Own Regex Engine. Currently, everything works for server side javascript and typescript, which is the main focus of this, because servers are what usually get the attacked in redos atackers.
You might get a message link: No loader is configured for ".node" files: node_modules/@regolithjs/regolith-linux-x64-gnu/regolith.linux-x64-gnu.node
,
I will actively be working to add this functionality and it will be tracked as Issue #40. For now, I recommend Using Regolith for serveer side and Systems Applications to Prevent Redos Attacks for servers, as this is what Commonly Gets Denial of Service Attacks.
npm i @regolithjs/regolith
import { Regolith } from '@regolithjs/regolith';
const pattern = new Regolith("^\\d+$");
pattern.test("12345"); // true
pattern.test("Hello"); // false
Simple Pattern Matching Example to Match crab
in our sentence my crab ferris
,
import { Regolith } from '@regolithjs/regolith';
const pattern = new Regolith('crab', 'g');
console.log(pattern.test('my crab ferris')); // true
Here we use ‘g’ in the Regolith
Constructor to mean a global.
const sentence = 'crab, snail, crab';
const crabPattern = new Regolith('crab', 'g');
// Find all matches
console.log(crabPattern.match(sentence));
// Output: ['crab', 'crab']
const sentence = 'crab, snail, crab';
const crabPattern = new Regolith('crab', 'g');
// Replace all occurrences
console.log(crabPattern.replace(sentence, 'snake'));
// Output: 'snake, snail, snake'
const sentence = 'crab, snail, crab';
const snailPattern = new Regolith('snail');
console.log(snailPattern.search(sentence));
// Output: 6 (index where 'snail' is found)
const splitPattern = new Regolith('[,\\|]');
console.log(splitPattern.split('apple,banana|orange'));
// Output: ['apple', 'banana', 'orange']
Make a Backend Express App that will tell you if a number is an int or a float. View the Complete Guide for the Express Example.
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");
}
// Run the test with Regolith pattern
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}`);
});
These are instruments only if you want to build this Library Yourself (EG for Development).
- Before You Build, You will need to have yarn installed. Here is a guide for installing yarn.
- You will also also need rust, and you can install rust with rustup.
To build the project, use this command:
Running yarn build
Will build the rust package, and you should see the Rust Compiler Complete The Build Process.
Now we can test to see if regolith was built correctly. We can open the node
Repl and load the library.
After opening the shell, you can load the library with:
const { Regolith } = await import("./index.js");
After that, you can use regolith as normal.
const integerPattern = new Regolith("^\\d+$");
integerPattern.test("123");
Here is an example of running regolith in the report to test if it buy correctly.
Testing the TS/JS Library
You should see the tests complete. Currently, there are 93 tests that get run.
These tests can be found in the __test__
Directory.
Testing the rust bindings
Here is what the output should look like:
These tests can be found in the source files in src/lib.rs
,
- Increment the version in package.json
- All changes are merged into main
- Run the tests with
yarn test
- Run
npm login
- Run
npm publish
name | purpose | docs |
---|---|---|
build.rs |
Runs the setup for napi-RS | |
Cargo.lock |
Automatically generated by cargo to keep track of rust package versions | |
Cargo.toml |
Contains information about the rust Crate; Like the name, version, and dependencies | |
index.d.ts |
Type information automatically generated by napi-RS | |
index.js |
The main entry point for the library that is automatically generated by napi-RS | |
package.json |
Information about the regolith package | |
rustfmt.toml |
A config for the rust formatter | |
yarn.lock |
Keeps track of the dependency version for yarn and it is automatically generated | |
.npmignore |
Keeps Files and Directories out of What is Shipped in the Library | Link |
.yarnrc.yml |
Configure Yarn Settings |
Use cargo fmt
This is actually checked in the automated tests when you create a pull request. You can also see rustfmt.toml for the config for cargo fmt
,
2.2 Typescript / JavaScript Format
Use pretty with prettier --write
or prettier --write .
to format all .ts
and .js
Files.
The source code for the regolith website can be found at github.com/jakeroggenbuck/regolith- Website. The URL for the website is regolithjs.com.
These are the platforms that regolith has been tested on. These checks happen automatically in the CI.
Platform | Status |
---|---|
Arm 64 Apple Darwin | Working |
Arm 64 Linux Android | Working |
Arm 64 Linux Gnu | Working |
Arm 64 Linux Musl | Working |
Arm 64 PC Windows MSVC | Working |
Arm v7 linux gnu | Working |
Arm V7 Linux Musl | Working |
X86-64 Linux Musl | Working |
x86-64 freebsd | Not Tested |
i686 pc windows msvc | Working |
Arm V7 Linux Andriod | Working |
Universal Apple Darwin | Working |
RISC-V 64 GC Linux GNU | Working |
If you find a bug, please send me an email at bug at jr0 dot org
And or open an issue.
When trying to think of words that started with reg
I thought of the word regolith, which describes top layer of a planet that’s made of dust and rock. I likely Got Familiar with this Word in a Class I Took About Dinosaus.
Motivation and background
I was initially inspired to build this library after doing undergraduate research This LED me to a Question I COLLDN’T Answer: “Why isn’T the most popular Regex Library a Linear Time Engine for Languages like Typescript, Javascript, and Python?” You’d think that having a library that cannot get attacked (in a common way software gets attacked) Wld be more Commonly used. I Found an example called regxy in python, but there hasn Bollywood an update in 8 years, and it was archived in 2024. There is also Rure-Python but this has not ben updated in 6 years. Javascript has some more popular libraries that address this issue too. One is called re2js, which wraps google’s re2 library written in C ++. re2js have a difference api as the default regxp from javascript, Requiring some reworking on code that needs to be migrated over. The other is called node-re2, and this library also provides bindings for google’s re2 library. Node-Re2 does have an api similar to javaascript’s registerxp. Even with these libraries, anecdotally it feels like the vast majority of projects still use the default regax for their respective languages; Libraries that are vulnerable to Redos Attacks. I could not find an exact percentage for how many projects use linear time engines vs exponical engines so this should be solved to eater find oume Directly, by reviewing packages published and trying to calculate a percency.
Ultimately, I wanted a Regex Library that is a drop-in replacement for register My Hope is that Library Brings Value to Your Software as Well.
I plan to continue work on Regex Libraries that Mitigate Redos Attacks for Languages that Don’T Yet Have Linear Time Engines. A great next step would be to have a library that Isn Bollywood is dependent and I May implement my own Regex Engine for this. Another Possibility May Be To Use Web Assembly to Run Rust Inside The Browser Without Being Platform Dependent.
Ramesh Ghorai is the founder of www.livenewsblogger.com, a platform dedicated to delivering exclusive live news from across the globe and the local market. With a passion for covering diverse topics, he ensures readers stay updated with the latest and most reliable information. Over the past two years, Ramesh has also specialized in writing top software reviews, partnering with various software companies to provide in-depth insights and unbiased evaluations. His mission is to combine news reporting with valuable technology reviews, helping readers stay informed and make smarter choices.