eslint-plugin-node-security 4.9.0 → 4.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-node-security",
3
- "version": "4.9.0",
3
+ "version": "4.9.1",
4
4
  "description": "ESLint plugin for Node.js security — detects command injection, path traversal, SSRF, zip slip, and weak crypto (MD5/SHA-1, ECB, static IV) in fs, child_process, vm, and crypto.",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -78,7 +78,7 @@
78
78
  "node": ">=18.0.0"
79
79
  },
80
80
  "dependencies": {
81
- "@interlace/eslint-devkit": "^1.11.0"
81
+ "@interlace/eslint-devkit": "^1.13.0"
82
82
  },
83
83
  "peerDependencies": {
84
84
  "eslint": "^8.40.0 || ^9.0.0 || ^10.0.0"
package/src/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.configs=exports.plugin=exports.rules=void 0;exports.rules={get"detect-child-process"(){return require("./rules/detect-child-process").detectChildProcess},get"detect-eval-with-expression"(){return require("./rules/detect-eval-with-expression").detectEvalWithExpression},get"detect-non-literal-fs-filename"(){return require("./rules/detect-non-literal-fs-filename").detectNonLiteralFsFilename},get"no-unsafe-dynamic-require"(){return require("./rules/no-unsafe-dynamic-require").noUnsafeDynamicRequire},get"no-buffer-overread"(){return require("./rules/no-buffer-overread").noBufferOverread},get"no-deprecated-buffer"(){return require("./rules/no-deprecated-buffer").noDeprecatedBuffer},get"no-unsafe-buffer-alloc"(){return require("./rules/no-unsafe-buffer-alloc").noUnsafeBufferAlloc},get"no-toctou-vulnerability"(){return require("./rules/no-toctou-vulnerability").noToctouVulnerability},get"no-zip-slip"(){return require("./rules/no-zip-slip").noZipSlip},get"no-arbitrary-file-access"(){return require("./rules/no-arbitrary-file-access").noArbitraryFileAccess},get"no-data-in-temp-storage"(){return require("./rules/no-data-in-temp-storage").noDataInTempStorage},get"no-ssrf"(){return require("./rules/no-ssrf").noSsrf},get"no-shell-injection"(){return require("./rules/no-shell-injection").noShellInjection},get"no-dynamic-command-string"(){return require("./rules/no-dynamic-command-string").noDynamicCommandString},get"no-dynamic-algorithm-selection"(){return require("./rules/no-dynamic-algorithm-selection").noDynamicAlgorithmSelection},get"detect-suspicious-dependencies"(){return require("./rules/detect-suspicious-dependencies").detectSuspiciousDependencies},get"lock-file"(){return require("./rules/lock-file").lockFile},get"no-dynamic-dependency-loading"(){return require("./rules/no-dynamic-dependency-loading").noDynamicDependencyLoading},get"require-dependency-integrity"(){return require("./rules/require-dependency-integrity").requireDependencyIntegrity},get"require-secure-credential-storage"(){return require("./rules/require-secure-credential-storage").requireSecureCredentialStorage},get"require-secure-deletion"(){return require("./rules/require-secure-deletion").requireSecureDeletion},get"require-storage-encryption"(){return require("./rules/require-storage-encryption").requireStorageEncryption},get"no-dynamic-require"(){return require("./rules/no-dynamic-require").noDynamicRequire},get"no-cryptojs"(){return require("./rules/no-cryptojs").noCryptojs},get"no-cryptojs-weak-random"(){return require("./rules/no-cryptojs-weak-random").noCryptojsWeakRandom},get"no-deprecated-cipher-method"(){return require("./rules/no-deprecated-cipher-method").noDeprecatedCipherMethod},get"no-ecb-mode"(){return require("./rules/no-ecb-mode").noEcbMode},get"no-insecure-key-derivation"(){return require("./rules/no-insecure-key-derivation").noInsecureKeyDerivation},get"no-insecure-rsa-padding"(){return require("./rules/no-insecure-rsa-padding").noInsecureRsaPadding},get"no-math-random-crypto"(){return require("./rules/no-math-random-crypto").noMathRandomCrypto},get"no-self-signed-certs"(){return require("./rules/no-self-signed-certs").noSelfSignedCerts},get"no-sha1-hash"(){return require("./rules/no-sha1-hash").noSha1Hash},get"no-static-iv"(){return require("./rules/no-static-iv").noStaticIv},get"no-timing-unsafe-compare"(){return require("./rules/no-timing-unsafe-compare").noTimingUnsafeCompare},get"no-weak-cipher-algorithm"(){return require("./rules/no-weak-cipher-algorithm").noWeakCipherAlgorithm},get"no-weak-hash-algorithm"(){return require("./rules/no-weak-hash-algorithm").noWeakHashAlgorithm},get"prefer-native-crypto"(){return require("./rules/prefer-native-crypto").preferNativeCrypto}};exports.plugin={meta:{name:"eslint-plugin-node-security",version:"4.9.0"},rules:exports.rules};const recommendedRules={"node-security/detect-child-process":"error","node-security/detect-eval-with-expression":"error","node-security/detect-non-literal-fs-filename":"warn","node-security/no-unsafe-dynamic-require":"error","node-security/no-buffer-overread":"warn","node-security/no-deprecated-buffer":"error","node-security/no-unsafe-buffer-alloc":"warn","node-security/no-toctou-vulnerability":"error","node-security/no-zip-slip":"error","node-security/no-arbitrary-file-access":"error","node-security/no-data-in-temp-storage":"error","node-security/no-ssrf":"warn","node-security/no-shell-injection":"error","node-security/no-dynamic-command-string":"error","node-security/no-dynamic-algorithm-selection":"error","node-security/no-timing-unsafe-compare":"warn","node-security/detect-suspicious-dependencies":"warn","node-security/lock-file":"warn","node-security/require-dependency-integrity":"error","node-security/no-weak-hash-algorithm":"error","node-security/no-weak-cipher-algorithm":"error","node-security/no-static-iv":"error","node-security/no-ecb-mode":"error","node-security/no-math-random-crypto":"error","node-security/no-cryptojs":"error","node-security/no-self-signed-certs":"error"};exports.configs={recommended:{plugins:{"node-security":exports.plugin},rules:recommendedRules},strict:{plugins:{"node-security":exports.plugin},rules:Object.fromEntries(Object.keys(exports.rules).map(ruleName=>[`node-security/${ruleName}`,"error"]))}};exports.default=exports.plugin;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.configs=exports.plugin=exports.rules=void 0;exports.rules={get"detect-child-process"(){return require("./rules/detect-child-process").detectChildProcess},get"detect-eval-with-expression"(){return require("./rules/detect-eval-with-expression").detectEvalWithExpression},get"detect-non-literal-fs-filename"(){return require("./rules/detect-non-literal-fs-filename").detectNonLiteralFsFilename},get"no-unsafe-dynamic-require"(){return require("./rules/no-unsafe-dynamic-require").noUnsafeDynamicRequire},get"no-buffer-overread"(){return require("./rules/no-buffer-overread").noBufferOverread},get"no-deprecated-buffer"(){return require("./rules/no-deprecated-buffer").noDeprecatedBuffer},get"no-unsafe-buffer-alloc"(){return require("./rules/no-unsafe-buffer-alloc").noUnsafeBufferAlloc},get"no-toctou-vulnerability"(){return require("./rules/no-toctou-vulnerability").noToctouVulnerability},get"no-zip-slip"(){return require("./rules/no-zip-slip").noZipSlip},get"no-arbitrary-file-access"(){return require("./rules/no-arbitrary-file-access").noArbitraryFileAccess},get"no-data-in-temp-storage"(){return require("./rules/no-data-in-temp-storage").noDataInTempStorage},get"no-ssrf"(){return require("./rules/no-ssrf").noSsrf},get"no-shell-injection"(){return require("./rules/no-shell-injection").noShellInjection},get"no-dynamic-command-string"(){return require("./rules/no-dynamic-command-string").noDynamicCommandString},get"no-dynamic-algorithm-selection"(){return require("./rules/no-dynamic-algorithm-selection").noDynamicAlgorithmSelection},get"detect-suspicious-dependencies"(){return require("./rules/detect-suspicious-dependencies").detectSuspiciousDependencies},get"lock-file"(){return require("./rules/lock-file").lockFile},get"no-dynamic-dependency-loading"(){return require("./rules/no-dynamic-dependency-loading").noDynamicDependencyLoading},get"require-dependency-integrity"(){return require("./rules/require-dependency-integrity").requireDependencyIntegrity},get"require-secure-credential-storage"(){return require("./rules/require-secure-credential-storage").requireSecureCredentialStorage},get"require-secure-deletion"(){return require("./rules/require-secure-deletion").requireSecureDeletion},get"require-storage-encryption"(){return require("./rules/require-storage-encryption").requireStorageEncryption},get"no-dynamic-require"(){return require("./rules/no-dynamic-require").noDynamicRequire},get"no-cryptojs"(){return require("./rules/no-cryptojs").noCryptojs},get"no-cryptojs-weak-random"(){return require("./rules/no-cryptojs-weak-random").noCryptojsWeakRandom},get"no-deprecated-cipher-method"(){return require("./rules/no-deprecated-cipher-method").noDeprecatedCipherMethod},get"no-ecb-mode"(){return require("./rules/no-ecb-mode").noEcbMode},get"no-insecure-key-derivation"(){return require("./rules/no-insecure-key-derivation").noInsecureKeyDerivation},get"no-insecure-rsa-padding"(){return require("./rules/no-insecure-rsa-padding").noInsecureRsaPadding},get"no-math-random-crypto"(){return require("./rules/no-math-random-crypto").noMathRandomCrypto},get"no-self-signed-certs"(){return require("./rules/no-self-signed-certs").noSelfSignedCerts},get"no-sha1-hash"(){return require("./rules/no-sha1-hash").noSha1Hash},get"no-static-iv"(){return require("./rules/no-static-iv").noStaticIv},get"no-timing-unsafe-compare"(){return require("./rules/no-timing-unsafe-compare").noTimingUnsafeCompare},get"no-weak-cipher-algorithm"(){return require("./rules/no-weak-cipher-algorithm").noWeakCipherAlgorithm},get"no-weak-hash-algorithm"(){return require("./rules/no-weak-hash-algorithm").noWeakHashAlgorithm},get"prefer-native-crypto"(){return require("./rules/prefer-native-crypto").preferNativeCrypto}};exports.plugin={meta:{name:"eslint-plugin-node-security",version:"4.9.1"},rules:exports.rules};const recommendedRules={"node-security/detect-child-process":"error","node-security/detect-eval-with-expression":"error","node-security/detect-non-literal-fs-filename":"warn","node-security/no-unsafe-dynamic-require":"error","node-security/no-buffer-overread":"warn","node-security/no-deprecated-buffer":"error","node-security/no-unsafe-buffer-alloc":"warn","node-security/no-toctou-vulnerability":"error","node-security/no-zip-slip":"error","node-security/no-arbitrary-file-access":"error","node-security/no-data-in-temp-storage":"error","node-security/no-ssrf":"warn","node-security/no-shell-injection":"error","node-security/no-dynamic-command-string":"error","node-security/no-dynamic-algorithm-selection":"error","node-security/no-timing-unsafe-compare":"warn","node-security/detect-suspicious-dependencies":"warn","node-security/lock-file":"warn","node-security/require-dependency-integrity":"error","node-security/no-weak-hash-algorithm":"error","node-security/no-weak-cipher-algorithm":"error","node-security/no-static-iv":"error","node-security/no-ecb-mode":"error","node-security/no-math-random-crypto":"error","node-security/no-cryptojs":"error","node-security/no-self-signed-certs":"error"};exports.configs={recommended:{plugins:{"node-security":exports.plugin},rules:recommendedRules},strict:{plugins:{"node-security":exports.plugin},rules:Object.fromEntries(Object.keys(exports.rules).map(ruleName=>[`node-security/${ruleName}`,"error"]))}};exports.default=exports.plugin;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.detectSuspiciousDependencies=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");exports.detectSuspiciousDependencies=(0,eslint_devkit_1.createRule)({name:"detect-suspicious-dependencies",meta:{type:"problem",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-node-security/docs/rules/detect-suspicious-dependencies.md",description:"Detect typosquatting in package names",cwe:"CWE-506",cvss:7.5},messages:{violationDetected:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.SECURITY,issueName:"Suspicious Dependency",cwe:"CWE-506",description:"Suspicious package name detected - possible typosquatting",severity:"HIGH",fix:"Verify package authenticity on npm registry",documentationLink:"https://cwe.mitre.org/data/definitions/506.html"})},schema:[]},defaultOptions:[],create(context){const popularPackages=["react","lodash","express","axios","webpack"];function levenshtein(a,b){const matrix=[];for(let i=0;i<=b.length;i++){matrix[i]=[i]}for(let j=0;j<=a.length;j++){matrix[0][j]=j}for(let i=1;i<=b.length;i++){for(let j=1;j<=a.length;j++){if(b.charAt(i-1)===a.charAt(j-1)){matrix[i][j]=matrix[i-1][j-1]}else{matrix[i][j]=Math.min(matrix[i-1][j-1]+1,matrix[i][j-1]+1,matrix[i-1][j]+1)}}}return matrix[b.length][a.length]}return{ImportDeclaration(node){const source=node.source.value;if(typeof source==="string"&&!source.startsWith(".")&&!source.startsWith("@")){for(const popular of popularPackages){const distance=levenshtein(source,popular);if(distance>0&&distance<=2){context.report({node,messageId:"violationDetected",data:{name:source,similar:popular}})}}}}}}});
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.detectSuspiciousDependencies=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");exports.detectSuspiciousDependencies=(0,eslint_devkit_1.createRule)({name:"detect-suspicious-dependencies",meta:{type:"problem",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-node-security/docs/rules/detect-suspicious-dependencies.md",description:"Detect typosquatting in package names",cwe:"CWE-506",cvss:7.5},messages:{violationDetected:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.SECURITY,issueName:"Suspicious Dependency",cwe:"CWE-506",description:"Suspicious package name detected - possible typosquatting",severity:"HIGH",fix:"Verify package authenticity on npm registry",documentationLink:"https://cwe.mitre.org/data/definitions/506.html"})},schema:[]},defaultOptions:[],create(context){const popularPackages=["react","lodash","express","axios","webpack"];const KNOWN_LEGITIMATE=new Set(["preact","recast","react-dom","reactor","redux","lodash-es","expressive","axios-retry","webpack-cli"]);function levenshtein(a,b){const matrix=[];for(let i=0;i<=b.length;i++){matrix[i]=[i]}for(let j=0;j<=a.length;j++){matrix[0][j]=j}for(let i=1;i<=b.length;i++){for(let j=1;j<=a.length;j++){if(b.charAt(i-1)===a.charAt(j-1)){matrix[i][j]=matrix[i-1][j-1]}else{matrix[i][j]=Math.min(matrix[i-1][j-1]+1,matrix[i][j-1]+1,matrix[i-1][j]+1);if(i>1&&j>1&&b.charAt(i-1)===a.charAt(j-2)&&b.charAt(i-2)===a.charAt(j-1)){matrix[i][j]=Math.min(matrix[i][j],matrix[i-2][j-2]+1)}}}}return matrix[b.length][a.length]}return{ImportDeclaration(node){const source=node.source.value;if(typeof source==="string"&&!source.startsWith(".")&&!source.startsWith("@")){for(const popular of popularPackages){const distance=levenshtein(source,popular);if(distance===1&&!KNOWN_LEGITIMATE.has(source)){context.report({node,messageId:"violationDetected",data:{name:source,similar:popular}})}}}}}}});
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.lockFile=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");exports.lockFile=(0,eslint_devkit_1.createRule)({name:"lock-file",meta:{type:"suggestion",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-node-security/docs/rules/lock-file.md",description:"Ensure package lock file exists for the configured package manager",cwe:"CWE-829",cvss:7.5},messages:{violationDetected:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.SECURITY,issueName:"Lock File Missing",cwe:"CWE-829",description:"Package lock file missing ({{ lockFile }}) for {{ packageManager }}. Commit the lock file to ensure supply chain integrity.",severity:"HIGH",fix:"Generate and commit the {{ lockFile }} file.",documentationLink:"https://cwe.mitre.org/data/definitions/829.html"})},schema:[{type:"object",properties:{packageManager:{type:"string",enum:["npm","yarn","pnpm"],description:"Package manager whose lock file is required"}},additionalProperties:false}]},defaultOptions:[{}],create(context){const fs=require("node:fs");const path=require("node:path");let checked=false;const options=context.options[0]||{};const userPackageManager=options.packageManager;const lockFiles={npm:"package-lock.json",yarn:"yarn.lock",pnpm:"pnpm-lock.yaml"};const targetLockFiles=userPackageManager?[lockFiles[userPackageManager]]:Object.values(lockFiles);const targetLockFile=userPackageManager?lockFiles[userPackageManager]:"package-lock.json | yarn.lock | pnpm-lock.yaml";const reportedManager=userPackageManager??"any";return{Program(node){if(checked)return;checked=true;let dir=path.dirname(context.filename);let found=false;for(let i=0;i<10;i++){for(const lf of targetLockFiles){if(fs.existsSync(path.join(dir,lf))){found=true;break}}if(found)break;const parentDir=path.dirname(dir);if(parentDir===dir)break;dir=parentDir}if(!found){context.report({node,messageId:"violationDetected",data:{packageManager:reportedManager,lockFile:targetLockFile}})}}}}});
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.lockFile=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");const reportedRoots=new Set;exports.lockFile=(0,eslint_devkit_1.createRule)({name:"lock-file",meta:{type:"suggestion",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-node-security/docs/rules/lock-file.md",description:"Ensure package lock file exists for the configured package manager",cwe:"CWE-829",cvss:7.5},messages:{violationDetected:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.SECURITY,issueName:"Lock File Missing",cwe:"CWE-829",description:"Package lock file missing ({{ lockFile }}) for {{ packageManager }}. Commit the lock file to ensure supply chain integrity.",severity:"HIGH",fix:"Generate and commit the {{ lockFile }} file.",documentationLink:"https://cwe.mitre.org/data/definitions/829.html"})},schema:[{type:"object",properties:{packageManager:{type:"string",enum:["npm","yarn","pnpm"],description:"Package manager whose lock file is required"}},additionalProperties:false}]},defaultOptions:[{}],create(context){const fs=require("node:fs");const path=require("node:path");const options=context.options[0]||{};const userPackageManager=options.packageManager;const lockFiles={npm:"package-lock.json",yarn:"yarn.lock",pnpm:"pnpm-lock.yaml"};const targetLockFiles=userPackageManager?[lockFiles[userPackageManager]]:Object.values(lockFiles);const targetLockFile=userPackageManager?lockFiles[userPackageManager]:"package-lock.json | yarn.lock | pnpm-lock.yaml";const reportedManager=userPackageManager??"any";return{Program(node){let dir=path.dirname(context.filename);let found=false;for(let i=0;i<10;i++){for(const lf of targetLockFiles){if(fs.existsSync(path.join(dir,lf))){found=true;break}}if(found)break;const parentDir=path.dirname(dir);if(parentDir===dir)break;dir=parentDir}if(!found){let root=path.dirname(context.filename);let manifest=false;for(let i=0;i<10;i++){if(fs.existsSync(path.join(root,"package.json"))){manifest=true;break}const parent=path.dirname(root);if(parent===root)break;root=parent}if(!manifest)return;if(reportedRoots.has(root))return;reportedRoots.add(root);context.report({node,messageId:"violationDetected",data:{packageManager:reportedManager,lockFile:targetLockFile}})}}}}});