Skip to content

Commit

Permalink
Fix reach template regex for timing (#371)
Browse files Browse the repository at this point in the history
  • Loading branch information
devinivy authored Sep 27, 2021
1 parent 4c05eee commit 82504b7
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/reachTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const internals = {};

module.exports = function (obj, template, options) {

return template.replace(/{([^}]+)}/g, ($0, chain) => {
return template.replace(/{([^{}]+)}/g, ($0, chain) => {

const value = Reach(obj, chain, options);
return (value === undefined || value === null ? '' : value);
Expand Down
24 changes: 24 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2069,6 +2069,30 @@ describe('reachTemplate()', () => {

expect(Hoek.reachTemplate(obj, template, '/')).to.equal('4:9:1::');
});

it('isn\'t prone to ReDoS given an adversarial template', () => {

const sizes = [0, 1, 2, 3, 4]; // Should be evenly-spaced
const times = [];
const diffs = [];

for (const size of sizes) {
const start = Date.now();
Hoek.reachTemplate({}, '{'.repeat(size * 10000));
times.push(Date.now() - start);
}

for (let i = 1; i < times.length; ++i) {
diffs.push(times[i] - times[i - 1]);
}

// Under ReDoS, as the size of the input increases the timing accelerates upwards,
// i.e. each timing diff would be greater than the last.

const diffsMonotonic = diffs[0] < diffs[1] && diffs[1] < diffs[2] && diffs[2] < diffs[3];

expect(diffsMonotonic, 'Timing diffs monotonic').to.be.false();
});
});

describe('assert()', () => {
Expand Down

0 comments on commit 82504b7

Please sign in to comment.