Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

safe-regex

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

safe-regex - npm Package Compare versions

Comparing version 2.0.2 to 2.1.0

bin/cli.js

18

CHANGELOG.md

@@ -5,20 +5,4 @@ # v2

### v2.0.2
## v2.0.0
1. Update regex-tree to address transitive dep DoS vector
2. Update tape to address DoS vector
Contributors:
- [teppeis](https://github.com/teppeis)
- [davisjam](https://github.com/davisjam)
### v2.0.1
1. Fix parsing bug introduced during switch to regexp-tree.
Contributors:
- [davisjam](https://github.com/davisjam)
### v2.0.0
1. Update README.

@@ -25,0 +9,0 @@ 2. Switch AST library from ret to regexp-tree.

@@ -1,22 +0,26 @@

const regexpTree = require('regexp-tree');
const analyzer = require('./lib/analyzer');
const analyzerFamily = require('./lib/analyzer-family');
module.exports = function (re, opts) {
if (!opts) opts = {};
const replimit = opts.limit === undefined ? 25 : opts.limit;
const DEFAULT_SAFE_REP_LIMIT = 25;
const RET_IS_SAFE = true;
const RET_IS_VULNERABLE = false;
// Build an AST
let myRegExp = null;
let ast = null;
class Args {
constructor(regExp, analyzerOptions) {
this.regExp = regExp;
this.analyzerOptions = analyzerOptions;
}
}
function safeRegex(re, opts) {
try {
// Construct a RegExp object
if (re instanceof RegExp) {
myRegExp = re;
} else if (typeof re === 'string') {
myRegExp = new RegExp(re);
const args = buildArgs(re, opts);
const analyzerResponses = askAnalyzersIfVulnerable(args);
// Did any analyzer say true?
if (analyzerResponses.find((isVulnerable) => isVulnerable)) {
return RET_IS_VULNERABLE;
} else {
myRegExp = new RegExp(String(re));
return RET_IS_SAFE;
}
// Build an AST
ast = regexpTree.parse(myRegExp);
} catch (err) {

@@ -26,26 +30,45 @@ // Invalid or unparseable input

}
}
let currentStarHeight = 0;
let maxObservedStarHeight = 0;
function buildArgs(re, opts) {
// Build AnalyzerOptions
if (!opts) opts = {};
const heuristic_replimit = opts.limit === undefined ? DEFAULT_SAFE_REP_LIMIT : opts.limit;
let repetitionCount = 0;
const analyzerOptions = new analyzer.AnalyzerOptions(heuristic_replimit);
regexpTree.traverse(ast, {
'Repetition': {
pre ({node}) {
repetitionCount++;
// Build RegExp
let regExp = null;
// Construct a RegExp object
if (re instanceof RegExp) {
regExp = re;
} else if (typeof re === 'string') {
regExp = new RegExp(re);
} else {
regExp = new RegExp(String(re));
}
currentStarHeight++;
if (maxObservedStarHeight < currentStarHeight) {
maxObservedStarHeight = currentStarHeight;
}
},
return new Args(regExp, analyzerOptions);
}
post ({node}) {
currentStarHeight--;
}
function askAnalyzersIfVulnerable(args) {
let analyzerSaysVulnerable = [];
// Query the Analyzers
let Analyzer;
for (Analyzer of analyzerFamily) {
try {
const analyzer = new Analyzer(args.analyzerOptions);
analyzerSaysVulnerable.push(analyzer.isVulnerable(args.regExp));
} catch (err) {
/* istanbul ignore next */ // No need to worry about code coverage here.
analyzerSaysVulnerable.push(false);
}
});
}
return (maxObservedStarHeight <= 1) && (repetitionCount <= replimit);
};
return analyzerSaysVulnerable;
}
// Export
module.exports = safeRegex;
{
"name": "safe-regex",
"version": "2.0.2",
"version": "2.1.0",
"description": "detect possibly catastrophic, exponential-time regular expressions",

@@ -10,18 +10,29 @@ "main": "index.js",

"devDependencies": {
"tape": "^4.10.1"
"jest": "^24.9.0"
},
"scripts": {
"test": "tape test/*.js"
"test": "jest"
},
"testling": {
"files": "test/*.js",
"browsers": [
"ie/8",
"ie/9",
"ie/10",
"firefox/latest",
"chrome/latest",
"opera/latest",
"safari/latest"
]
"jest": {
"moduleFileExtensions": [
"js"
],
"testRegex": "test.*\\.spec\\.js$",
"collectCoverage": true,
"coverageReporters": [
"text-summary",
"html",
"lcov"
],
"collectCoverageFrom": [
"*.js"
],
"coverageThreshold": {
"global": {
"statements": 100,
"branches": 100,
"functions": 100,
"lines": 100
}
}
},

@@ -28,0 +39,0 @@ "repository": {

@@ -12,6 +12,4 @@ # safe-regex

[![browser support](https://ci.testling.com/substack/safe-regex.png)](https://ci.testling.com/substack/safe-regex)
[![Build Status](https://travis-ci.com/davisjam/safe-regex.svg?branch=master)](https://travis-ci.com/davisjam/safe-regex)
[![build status](https://secure.travis-ci.org/substack/safe-regex.png)](http://travis-ci.org/substack/safe-regex)
# Example

@@ -62,4 +60,18 @@

# Versioning
This project follows [Semantic Versioning 2.0 (semver)](https://semver.org/).
Here are the project-specific meanings of MAJOR, MINOR, and PATCH updates:
- MAJOR: "Incompatible" API changes were introduced. There are two types in this module:
- Changes that modify the interface
- Changes that cause any regexes to be marked as unsafe that were formerly marked as safe
- MINOR: Functionality was added in a backwards-compatible manner. There are two types in this module:
- Refactoring the analyses but not changing their results
- Modifying the analyses to reduce false positives, without affecting negatives (false or true)
- PATCH: I don't anticipate using PATCH for this module
# License
MIT
[MIT](https://github.com/davisjam/safe-regex/blob/master/LICENSE)

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc