Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
Change Log

v5.10.0
---
* Replaced `multimatch` with `minimatch@11` for the CLI `--exclude` option, resolving the `minimatch` denial of service advisory `GHSA-g3hv-75wg-m249`
* Require Node.js 20 or newer, as `minimatch@11` does
Comment on lines +3 to +6

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically it's a breaking change, but Node 20 is already EOL'ed + it fixes a scanner issue, so it is done as a minor version


v5.9.1
---
* Fixed `splitStrings`/`stringArray` breaking a quoted `constructor` class key. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/1464
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
- **License**: BSD-2-Clause
- **Repository**: https://github.com/javascript-obfuscator/javascript-obfuscator
- **Homepage**: https://obfuscator.io/
- **Node Requirement**: >=18.0.0
- **Node Requirement**: >=20.0.0

## Key Features

Expand Down
10 changes: 3 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "javascript-obfuscator",
"version": "5.9.1",
"version": "5.10.0",
"description": "JavaScript obfuscator",
"keywords": [
"obfuscator",
Expand All @@ -12,7 +12,7 @@
"js obfuscator"
],
"engines": {
"node": ">=18.0.0"
"node": ">=20.0.0"
},
"main": "dist/index.js",
"browser": "dist/index.browser.js",
Expand All @@ -38,7 +38,7 @@
"inversify": "7.11.0",
"js-string-escape": "1.0.1",
"md5": "2.3.0",
"multimatch": "5.0.0",
"minimatch": "11.0.4",
"process": "0.11.10",
"reflect-metadata": "0.2.2",
"string-template": "1.0.0",
Expand All @@ -58,7 +58,6 @@
"@types/js-string-escape": "1.0.3",
"@types/md5": "2.3.6",
"@types/mocha": "10.0.10",
"@types/multimatch": "4.0.0",
"@types/node": "22.10.2",
"@types/rimraf": "3.0.2",
"@types/sinon": "17.0.4",
Expand Down Expand Up @@ -101,9 +100,6 @@
"webpack-cli": "6.0.1",
"webpack-node-externals": "3.0.0"
},
"resolutions": {
"multimatch/minimatch/brace-expansion": "^1.1.12"
},
"repository": {
"type": "git",
"url": "git+https://github.com/javascript-obfuscator/javascript-obfuscator.git"
Expand Down
31 changes: 29 additions & 2 deletions src/cli/utils/SourceCodeFileUtils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as fs from 'fs';
import * as path from 'path';
import multimatch from 'multimatch';
import { minimatch, MinimatchOptions } from 'minimatch';

import { TInputCLIOptions } from '../../types/options/TInputCLIOptions';

Expand Down Expand Up @@ -39,14 +39,41 @@ export class SourceCodeFileUtils {
}

const fileName: string = path.basename(filePath);
const isExcludedFilePathByGlobPattern: boolean = !!multimatch([filePath], excludePatterns).length;
const isExcludedFilePathByGlobPattern: boolean = SourceCodeFileUtils.isMatchedByGlobPatterns(
filePath,
excludePatterns
);
const isExcludedFilePathByInclusion: boolean = excludePatterns.some(
(excludePattern: string) => filePath.includes(excludePattern) || fileName.includes(excludePattern)
);

return isExcludedFilePathByInclusion || isExcludedFilePathByGlobPattern;
}

/**
* Patterns are applied in order: a matching pattern includes the path,
* a matching `!`-prefixed pattern removes it again
*
* @param {string} filePath
* @param {string[]} globPatterns
* @returns {boolean}
*/
private static isMatchedByGlobPatterns(filePath: string, globPatterns: string[]): boolean {
// keeps `\` in patterns as a path separator on Windows
const minimatchOptions: MinimatchOptions = { windowsPathsNoEscape: path.sep === '\\' };

return globPatterns.reduce((isMatched: boolean, globPattern: string) => {
const isNegatedPattern: boolean = globPattern.startsWith('!');
const pattern: string = isNegatedPattern ? globPattern.slice(1) : globPattern;

if (!minimatch(filePath, pattern, minimatchOptions)) {
return isMatched;
}

return !isNegatedPattern;
}, false);
}

/**
* @param {string} filePath
* @returns {boolean}
Expand Down
97 changes: 97 additions & 0 deletions test/unit-tests/cli/utils/SourceCodeFileUtils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,103 @@ describe('SourceCodeFileUtils', () => {
fs.unlinkSync(inputPath);
});
});

describe('Variant #4: exclude by `glob` pattern without globstar', () => {
const tmpFileName: string = 'test.js';
const inputPath: string = path.join(tmpDirectoryPath, tmpFileName);

let testFunc: () => void;

before(() => {
fs.writeFileSync(inputPath, fileContent);
testFunc = () =>
new SourceCodeFileUtils(inputPath, {
exclude: ['test/tmp/*.js']
}).readSourceCode();
});

it('should throw an error if `inputPath` is the excluded file path', () => {
assert.throws(testFunc, expectedError);
});

after(() => {
fs.unlinkSync(inputPath);
});
});

describe('Variant #5: negated `glob` pattern does not match `inputPath`', () => {
const tmpFileName: string = 'test.js';
const inputPath: string = path.join(tmpDirectoryPath, tmpFileName);

let testFunc: () => void;

before(() => {
fs.writeFileSync(inputPath, fileContent);
testFunc = () =>
new SourceCodeFileUtils(inputPath, {
exclude: ['**/*.js', '!**/foo.js']
}).readSourceCode();
});

it('should throw an error if `inputPath` is the excluded file path', () => {
assert.throws(testFunc, expectedError);
});

after(() => {
fs.unlinkSync(inputPath);
});
});

describe('Variant #6: negated `glob` pattern precedes the matching pattern', () => {
const tmpFileName: string = 'test.js';
const inputPath: string = path.join(tmpDirectoryPath, tmpFileName);

let testFunc: () => void;

before(() => {
fs.writeFileSync(inputPath, fileContent);
testFunc = () =>
new SourceCodeFileUtils(inputPath, {
exclude: [`!**/${tmpFileName}`, '**/*.js']
}).readSourceCode();
});

it('should throw an error if `inputPath` is the excluded file path', () => {
assert.throws(testFunc, expectedError);
});

after(() => {
fs.unlinkSync(inputPath);
});
});
});

describe('Variant #3: `inputPath` is re-included by negated `glob` pattern', () => {
const tmpFileName: string = 'test.js';
const inputPath: string = path.join(tmpDirectoryPath, tmpFileName);
const expectedFilesData: IFileData[] = [
{
content: fileContent,
filePath: inputPath
}
];

let filesData: IFileData[];

before(() => {
fs.writeFileSync(inputPath, fileContent);
filesData = new SourceCodeFileUtils(inputPath, {
exclude: ['**/*.js', `!**/${tmpFileName}`]
}).readSourceCode();
});

it('should return valid files data', () => {
assert.deepEqual(filesData, expectedFilesData);
});

after(() => {
fs.unlinkSync(inputPath);
});
});
});
});
Expand Down
68 changes: 27 additions & 41 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,11 @@
wrap-ansi "^8.1.0"
wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"

"@isaacs/nonrecursive-glob-match@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@isaacs/nonrecursive-glob-match/-/nonrecursive-glob-match-1.0.3.tgz#7f6724fd8a6ca315d6bb7f63f0e4d079060da246"
integrity sha512-SI7kyKHq4XXDRozw+r9GlRZkia1ZkFrpLW98r2IC2Bpr8YkFGE3fvjzmxCG0x78A++69HmDNrDvSMYBZmHGpKA==

"@istanbuljs/load-nyc-config@^1.0.0":
version "1.0.0"
resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz"
Expand Down Expand Up @@ -711,7 +716,7 @@
resolved "https://registry.yarnpkg.com/@types/md5/-/md5-2.3.6.tgz#db6901a9fc1d95eeed851a62c5ce5dedfac8ff9a"
integrity sha512-WD69gNXtRBnpknfZcb4TRQ0XJQbUPZcai/Qdhmka3sxUR3Et8NrXoeAoknG/LghYHTf4ve795rInVYHBTQdNVA==

"@types/minimatch@*", "@types/minimatch@^3.0.3":
"@types/minimatch@*":
version "3.0.3"
resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz"
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
Expand All @@ -721,13 +726,6 @@
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.10.tgz#91f62905e8d23cbd66225312f239454a23bebfa0"
integrity sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==

"@types/multimatch@4.0.0":
version "4.0.0"
resolved "https://registry.npmjs.org/@types/multimatch/-/multimatch-4.0.0.tgz"
integrity sha512-xS26gtqY5QASmfU/6jb5vj7F0D0SctgRGtwXsKSNng1knk/OewjISlkMwGonkMCbZCqSoW3s6nL0sAtTlzbL/g==
dependencies:
multimatch "*"

"@types/node@*":
version "13.9.3"
resolved "https://registry.npmjs.org/@types/node/-/node-13.9.3.tgz"
Expand Down Expand Up @@ -1199,11 +1197,6 @@ array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2:
call-bound "^1.0.3"
is-array-buffer "^3.0.5"

array-differ@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz"
integrity sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==

array-filter@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz"
Expand Down Expand Up @@ -1274,11 +1267,6 @@ arraybuffer.prototype.slice@^1.0.4:
get-intrinsic "^1.2.6"
is-array-buffer "^3.0.4"

arrify@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz"
integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==

assert@2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd"
Expand Down Expand Up @@ -1331,12 +1319,17 @@ balanced-match@^1.0.0:
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=

balanced-match@^4.0.2:
version "4.0.4"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-4.0.4.tgz#bfb10662feed8196a2c62e7c68e17720c274179a"
integrity sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==

baseline-browser-mapping@^2.8.19:
version "2.8.21"
resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.8.21.tgz#2f9cccde871bfa4aec9dbf92d0ee746e4f1892e4"
integrity sha512-JU0h5APyQNsHOlAM7HnQnPToSDQoEBZqzu/YBlqDnEeymPnZDREeXJA3KBMQee+dKteAxZ2AtvQEvVYdZf241Q==

brace-expansion@^1.1.12, brace-expansion@^1.1.7:
brace-expansion@^1.1.7:
version "1.1.16"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.16.tgz#723d3a30c0558c225abc9fc479a73e14e26c3c2f"
integrity sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==
Expand All @@ -1351,6 +1344,13 @@ brace-expansion@^2.0.1:
dependencies:
balanced-match "^1.0.0"

brace-expansion@^5.0.12:
version "5.0.12"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-5.0.12.tgz#995fbb4750a77c4d16a7dc942ff2ca6ef8e675ec"
integrity sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==
dependencies:
balanced-match "^4.0.2"

braces@^3.0.1:
version "3.0.2"
resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz"
Expand Down Expand Up @@ -3849,6 +3849,14 @@ min-indent@^1.0.0:
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==

minimatch@11.0.4:
version "11.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-11.0.4.tgz#3ed156790c2754647ee94dab305a3f93cd16481e"
integrity sha512-/UJ1dEoVQTjPNDh6SGlUo+ueLMmoHTas4q+8yaAR/5t6nLAIiBDJtoYUh20IYleix7ehiQkgczb84PE3uzHkxg==
dependencies:
"@isaacs/nonrecursive-glob-match" "^1.0.3"
brace-expansion "^5.0.12"

minimatch@9.0.1:
version "9.0.1"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.1.tgz#8a555f541cf976c622daf078bb28f29fb927c253"
Expand Down Expand Up @@ -3936,28 +3944,6 @@ ms@^2.1.3:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==

multimatch@*:
version "4.0.0"
resolved "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz"
integrity sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==
dependencies:
"@types/minimatch" "^3.0.3"
array-differ "^3.0.0"
array-union "^2.1.0"
arrify "^2.0.1"
minimatch "^3.0.4"

multimatch@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-5.0.0.tgz#932b800963cea7a31a033328fa1e0c3a1874dbe6"
integrity sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==
dependencies:
"@types/minimatch" "^3.0.3"
array-differ "^3.0.0"
array-union "^2.1.0"
arrify "^2.0.1"
minimatch "^3.0.4"

natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
Expand Down
Loading