secure-scan 1.2.2
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/README.md +564 -0
- package/dist/ai/aiAnalyzer.d.ts +99 -0
- package/dist/ai/aiAnalyzer.d.ts.map +1 -0
- package/dist/ai/aiAnalyzer.js +669 -0
- package/dist/ai/aiAnalyzer.js.map +1 -0
- package/dist/ai/index.d.ts +5 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +21 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/analyzers/base/baseAnalyzer.d.ts +44 -0
- package/dist/analyzers/base/baseAnalyzer.d.ts.map +1 -0
- package/dist/analyzers/base/baseAnalyzer.js +53 -0
- package/dist/analyzers/base/baseAnalyzer.js.map +1 -0
- package/dist/analyzers/base/index.d.ts +5 -0
- package/dist/analyzers/base/index.d.ts.map +1 -0
- package/dist/analyzers/base/index.js +21 -0
- package/dist/analyzers/base/index.js.map +1 -0
- package/dist/analyzers/c-cpp/cppAnalyzer.d.ts +60 -0
- package/dist/analyzers/c-cpp/cppAnalyzer.d.ts.map +1 -0
- package/dist/analyzers/c-cpp/cppAnalyzer.js +218 -0
- package/dist/analyzers/c-cpp/cppAnalyzer.js.map +1 -0
- package/dist/analyzers/c-cpp/index.d.ts +5 -0
- package/dist/analyzers/c-cpp/index.d.ts.map +1 -0
- package/dist/analyzers/c-cpp/index.js +21 -0
- package/dist/analyzers/c-cpp/index.js.map +1 -0
- package/dist/analyzers/core/engine/index.d.ts +5 -0
- package/dist/analyzers/core/engine/index.d.ts.map +1 -0
- package/dist/analyzers/core/engine/index.js +21 -0
- package/dist/analyzers/core/engine/index.js.map +1 -0
- package/dist/analyzers/core/engine/ruleEngine.d.ts +46 -0
- package/dist/analyzers/core/engine/ruleEngine.d.ts.map +1 -0
- package/dist/analyzers/core/engine/ruleEngine.js +173 -0
- package/dist/analyzers/core/engine/ruleEngine.js.map +1 -0
- package/dist/analyzers/core/index.d.ts +8 -0
- package/dist/analyzers/core/index.d.ts.map +1 -0
- package/dist/analyzers/core/index.js +24 -0
- package/dist/analyzers/core/index.js.map +1 -0
- package/dist/analyzers/core/scanner/fileScanner.d.ts +31 -0
- package/dist/analyzers/core/scanner/fileScanner.d.ts.map +1 -0
- package/dist/analyzers/core/scanner/fileScanner.js +199 -0
- package/dist/analyzers/core/scanner/fileScanner.js.map +1 -0
- package/dist/analyzers/core/scanner/index.d.ts +5 -0
- package/dist/analyzers/core/scanner/index.d.ts.map +1 -0
- package/dist/analyzers/core/scanner/index.js +21 -0
- package/dist/analyzers/core/scanner/index.js.map +1 -0
- package/dist/analyzers/core/scoring/index.d.ts +5 -0
- package/dist/analyzers/core/scoring/index.d.ts.map +1 -0
- package/dist/analyzers/core/scoring/index.js +21 -0
- package/dist/analyzers/core/scoring/index.js.map +1 -0
- package/dist/analyzers/core/scoring/riskScoring.d.ts +49 -0
- package/dist/analyzers/core/scoring/riskScoring.d.ts.map +1 -0
- package/dist/analyzers/core/scoring/riskScoring.js +180 -0
- package/dist/analyzers/core/scoring/riskScoring.js.map +1 -0
- package/dist/analyzers/core/securityScanner.d.ts +47 -0
- package/dist/analyzers/core/securityScanner.d.ts.map +1 -0
- package/dist/analyzers/core/securityScanner.js +298 -0
- package/dist/analyzers/core/securityScanner.js.map +1 -0
- package/dist/analyzers/csharp/csharpAnalyzer.d.ts +64 -0
- package/dist/analyzers/csharp/csharpAnalyzer.d.ts.map +1 -0
- package/dist/analyzers/csharp/csharpAnalyzer.js +232 -0
- package/dist/analyzers/csharp/csharpAnalyzer.js.map +1 -0
- package/dist/analyzers/csharp/index.d.ts +5 -0
- package/dist/analyzers/csharp/index.d.ts.map +1 -0
- package/dist/analyzers/csharp/index.js +21 -0
- package/dist/analyzers/csharp/index.js.map +1 -0
- package/dist/analyzers/iac/iacAnalyzer.d.ts +36 -0
- package/dist/analyzers/iac/iacAnalyzer.d.ts.map +1 -0
- package/dist/analyzers/iac/iacAnalyzer.js +182 -0
- package/dist/analyzers/iac/iacAnalyzer.js.map +1 -0
- package/dist/analyzers/iac/index.d.ts +5 -0
- package/dist/analyzers/iac/index.d.ts.map +1 -0
- package/dist/analyzers/iac/index.js +21 -0
- package/dist/analyzers/iac/index.js.map +1 -0
- package/dist/analyzers/index.d.ts +30 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/index.js +80 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/analyzers/java/index.d.ts +5 -0
- package/dist/analyzers/java/index.d.ts.map +1 -0
- package/dist/analyzers/java/index.js +21 -0
- package/dist/analyzers/java/index.js.map +1 -0
- package/dist/analyzers/java/javaAnalyzer.d.ts +64 -0
- package/dist/analyzers/java/javaAnalyzer.d.ts.map +1 -0
- package/dist/analyzers/java/javaAnalyzer.js +224 -0
- package/dist/analyzers/java/javaAnalyzer.js.map +1 -0
- package/dist/analyzers/javascript/astUtils.d.ts +170 -0
- package/dist/analyzers/javascript/astUtils.d.ts.map +1 -0
- package/dist/analyzers/javascript/astUtils.js +700 -0
- package/dist/analyzers/javascript/astUtils.js.map +1 -0
- package/dist/analyzers/javascript/index.d.ts +18 -0
- package/dist/analyzers/javascript/index.d.ts.map +1 -0
- package/dist/analyzers/javascript/index.js +50 -0
- package/dist/analyzers/javascript/index.js.map +1 -0
- package/dist/analyzers/javascript/javascriptAnalyzer.d.ts +111 -0
- package/dist/analyzers/javascript/javascriptAnalyzer.d.ts.map +1 -0
- package/dist/analyzers/javascript/javascriptAnalyzer.js +860 -0
- package/dist/analyzers/javascript/javascriptAnalyzer.js.map +1 -0
- package/dist/analyzers/javascript/malwareDetector.d.ts +102 -0
- package/dist/analyzers/javascript/malwareDetector.d.ts.map +1 -0
- package/dist/analyzers/javascript/malwareDetector.js +616 -0
- package/dist/analyzers/javascript/malwareDetector.js.map +1 -0
- package/dist/analyzers/javascript/packageJsonAnalyzer.d.ts +87 -0
- package/dist/analyzers/javascript/packageJsonAnalyzer.d.ts.map +1 -0
- package/dist/analyzers/javascript/packageJsonAnalyzer.js +553 -0
- package/dist/analyzers/javascript/packageJsonAnalyzer.js.map +1 -0
- package/dist/analyzers/javascript/taintAnalyzer.d.ts +120 -0
- package/dist/analyzers/javascript/taintAnalyzer.d.ts.map +1 -0
- package/dist/analyzers/javascript/taintAnalyzer.js +526 -0
- package/dist/analyzers/javascript/taintAnalyzer.js.map +1 -0
- package/dist/analyzers/php/index.d.ts +5 -0
- package/dist/analyzers/php/index.d.ts.map +1 -0
- package/dist/analyzers/php/index.js +21 -0
- package/dist/analyzers/php/index.js.map +1 -0
- package/dist/analyzers/php/phpAnalyzer.d.ts +56 -0
- package/dist/analyzers/php/phpAnalyzer.d.ts.map +1 -0
- package/dist/analyzers/php/phpAnalyzer.js +202 -0
- package/dist/analyzers/php/phpAnalyzer.js.map +1 -0
- package/dist/analyzers/python/index.d.ts +5 -0
- package/dist/analyzers/python/index.d.ts.map +1 -0
- package/dist/analyzers/python/index.js +21 -0
- package/dist/analyzers/python/index.js.map +1 -0
- package/dist/analyzers/python/pythonAnalyzer.d.ts +64 -0
- package/dist/analyzers/python/pythonAnalyzer.d.ts.map +1 -0
- package/dist/analyzers/python/pythonAnalyzer.js +226 -0
- package/dist/analyzers/python/pythonAnalyzer.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +281 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/engine/index.d.ts +5 -0
- package/dist/core/engine/index.d.ts.map +1 -0
- package/dist/core/engine/index.js +21 -0
- package/dist/core/engine/index.js.map +1 -0
- package/dist/core/engine/ruleEngine.d.ts +46 -0
- package/dist/core/engine/ruleEngine.d.ts.map +1 -0
- package/dist/core/engine/ruleEngine.js +173 -0
- package/dist/core/engine/ruleEngine.js.map +1 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +24 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/scanner/fileScanner.d.ts +31 -0
- package/dist/core/scanner/fileScanner.d.ts.map +1 -0
- package/dist/core/scanner/fileScanner.js +199 -0
- package/dist/core/scanner/fileScanner.js.map +1 -0
- package/dist/core/scanner/index.d.ts +5 -0
- package/dist/core/scanner/index.d.ts.map +1 -0
- package/dist/core/scanner/index.js +21 -0
- package/dist/core/scanner/index.js.map +1 -0
- package/dist/core/scoring/index.d.ts +5 -0
- package/dist/core/scoring/index.d.ts.map +1 -0
- package/dist/core/scoring/index.js +21 -0
- package/dist/core/scoring/index.js.map +1 -0
- package/dist/core/scoring/riskScoring.d.ts +49 -0
- package/dist/core/scoring/riskScoring.d.ts.map +1 -0
- package/dist/core/scoring/riskScoring.js +180 -0
- package/dist/core/scoring/riskScoring.js.map +1 -0
- package/dist/core/securityScanner.d.ts +47 -0
- package/dist/core/securityScanner.d.ts.map +1 -0
- package/dist/core/securityScanner.js +298 -0
- package/dist/core/securityScanner.js.map +1 -0
- package/dist/dependencies/aiDependencyAnalyzer.d.ts +96 -0
- package/dist/dependencies/aiDependencyAnalyzer.d.ts.map +1 -0
- package/dist/dependencies/aiDependencyAnalyzer.js +435 -0
- package/dist/dependencies/aiDependencyAnalyzer.js.map +1 -0
- package/dist/dependencies/database/cveDatabase.d.ts +32 -0
- package/dist/dependencies/database/cveDatabase.d.ts.map +1 -0
- package/dist/dependencies/database/cveDatabase.js +393 -0
- package/dist/dependencies/database/cveDatabase.js.map +1 -0
- package/dist/dependencies/database/index.d.ts +6 -0
- package/dist/dependencies/database/index.d.ts.map +1 -0
- package/dist/dependencies/database/index.js +22 -0
- package/dist/dependencies/database/index.js.map +1 -0
- package/dist/dependencies/database/maliciousPackages.d.ts +43 -0
- package/dist/dependencies/database/maliciousPackages.d.ts.map +1 -0
- package/dist/dependencies/database/maliciousPackages.js +279 -0
- package/dist/dependencies/database/maliciousPackages.js.map +1 -0
- package/dist/dependencies/dependencyAnalyzer.d.ts +74 -0
- package/dist/dependencies/dependencyAnalyzer.d.ts.map +1 -0
- package/dist/dependencies/dependencyAnalyzer.js +349 -0
- package/dist/dependencies/dependencyAnalyzer.js.map +1 -0
- package/dist/dependencies/detectors/index.d.ts +7 -0
- package/dist/dependencies/detectors/index.d.ts.map +1 -0
- package/dist/dependencies/detectors/index.js +28 -0
- package/dist/dependencies/detectors/index.js.map +1 -0
- package/dist/dependencies/detectors/securityStandards.d.ts +15 -0
- package/dist/dependencies/detectors/securityStandards.d.ts.map +1 -0
- package/dist/dependencies/detectors/securityStandards.js +178 -0
- package/dist/dependencies/detectors/securityStandards.js.map +1 -0
- package/dist/dependencies/detectors/vulnerabilityDetector.d.ts +53 -0
- package/dist/dependencies/detectors/vulnerabilityDetector.d.ts.map +1 -0
- package/dist/dependencies/detectors/vulnerabilityDetector.js +289 -0
- package/dist/dependencies/detectors/vulnerabilityDetector.js.map +1 -0
- package/dist/dependencies/index.d.ts +14 -0
- package/dist/dependencies/index.d.ts.map +1 -0
- package/dist/dependencies/index.js +43 -0
- package/dist/dependencies/index.js.map +1 -0
- package/dist/dependencies/installed/index.d.ts +8 -0
- package/dist/dependencies/installed/index.d.ts.map +1 -0
- package/dist/dependencies/installed/index.js +24 -0
- package/dist/dependencies/installed/index.js.map +1 -0
- package/dist/dependencies/installed/installedScanner.d.ts +91 -0
- package/dist/dependencies/installed/installedScanner.d.ts.map +1 -0
- package/dist/dependencies/installed/installedScanner.js +766 -0
- package/dist/dependencies/installed/installedScanner.js.map +1 -0
- package/dist/dependencies/installed/malwarePatterns.d.ts +32 -0
- package/dist/dependencies/installed/malwarePatterns.d.ts.map +1 -0
- package/dist/dependencies/installed/malwarePatterns.js +480 -0
- package/dist/dependencies/installed/malwarePatterns.js.map +1 -0
- package/dist/dependencies/installed/types.d.ts +274 -0
- package/dist/dependencies/installed/types.d.ts.map +1 -0
- package/dist/dependencies/installed/types.js +7 -0
- package/dist/dependencies/installed/types.js.map +1 -0
- package/dist/dependencies/parsers/base/baseParser.d.ts +44 -0
- package/dist/dependencies/parsers/base/baseParser.d.ts.map +1 -0
- package/dist/dependencies/parsers/base/baseParser.js +80 -0
- package/dist/dependencies/parsers/base/baseParser.js.map +1 -0
- package/dist/dependencies/parsers/base/index.d.ts +6 -0
- package/dist/dependencies/parsers/base/index.d.ts.map +1 -0
- package/dist/dependencies/parsers/base/index.js +27 -0
- package/dist/dependencies/parsers/base/index.js.map +1 -0
- package/dist/dependencies/parsers/cpp/cppParser.d.ts +36 -0
- package/dist/dependencies/parsers/cpp/cppParser.d.ts.map +1 -0
- package/dist/dependencies/parsers/cpp/cppParser.js +196 -0
- package/dist/dependencies/parsers/cpp/cppParser.js.map +1 -0
- package/dist/dependencies/parsers/cpp/index.d.ts +6 -0
- package/dist/dependencies/parsers/cpp/index.d.ts.map +1 -0
- package/dist/dependencies/parsers/cpp/index.js +27 -0
- package/dist/dependencies/parsers/cpp/index.js.map +1 -0
- package/dist/dependencies/parsers/csharp/csharpParser.d.ts +32 -0
- package/dist/dependencies/parsers/csharp/csharpParser.d.ts.map +1 -0
- package/dist/dependencies/parsers/csharp/csharpParser.js +125 -0
- package/dist/dependencies/parsers/csharp/csharpParser.js.map +1 -0
- package/dist/dependencies/parsers/csharp/index.d.ts +6 -0
- package/dist/dependencies/parsers/csharp/index.d.ts.map +1 -0
- package/dist/dependencies/parsers/csharp/index.js +27 -0
- package/dist/dependencies/parsers/csharp/index.js.map +1 -0
- package/dist/dependencies/parsers/index.d.ts +24 -0
- package/dist/dependencies/parsers/index.d.ts.map +1 -0
- package/dist/dependencies/parsers/index.js +69 -0
- package/dist/dependencies/parsers/index.js.map +1 -0
- package/dist/dependencies/parsers/java/index.d.ts +6 -0
- package/dist/dependencies/parsers/java/index.d.ts.map +1 -0
- package/dist/dependencies/parsers/java/index.js +27 -0
- package/dist/dependencies/parsers/java/index.js.map +1 -0
- package/dist/dependencies/parsers/java/javaParser.d.ts +32 -0
- package/dist/dependencies/parsers/java/javaParser.d.ts.map +1 -0
- package/dist/dependencies/parsers/java/javaParser.js +168 -0
- package/dist/dependencies/parsers/java/javaParser.js.map +1 -0
- package/dist/dependencies/parsers/javascript/index.d.ts +6 -0
- package/dist/dependencies/parsers/javascript/index.d.ts.map +1 -0
- package/dist/dependencies/parsers/javascript/index.js +27 -0
- package/dist/dependencies/parsers/javascript/index.js.map +1 -0
- package/dist/dependencies/parsers/javascript/javascriptParser.d.ts +55 -0
- package/dist/dependencies/parsers/javascript/javascriptParser.d.ts.map +1 -0
- package/dist/dependencies/parsers/javascript/javascriptParser.js +266 -0
- package/dist/dependencies/parsers/javascript/javascriptParser.js.map +1 -0
- package/dist/dependencies/parsers/php/index.d.ts +6 -0
- package/dist/dependencies/parsers/php/index.d.ts.map +1 -0
- package/dist/dependencies/parsers/php/index.js +27 -0
- package/dist/dependencies/parsers/php/index.js.map +1 -0
- package/dist/dependencies/parsers/php/phpParser.d.ts +35 -0
- package/dist/dependencies/parsers/php/phpParser.d.ts.map +1 -0
- package/dist/dependencies/parsers/php/phpParser.js +162 -0
- package/dist/dependencies/parsers/php/phpParser.js.map +1 -0
- package/dist/dependencies/parsers/python/index.d.ts +6 -0
- package/dist/dependencies/parsers/python/index.d.ts.map +1 -0
- package/dist/dependencies/parsers/python/index.js +27 -0
- package/dist/dependencies/parsers/python/index.js.map +1 -0
- package/dist/dependencies/parsers/python/pythonParser.d.ts +60 -0
- package/dist/dependencies/parsers/python/pythonParser.d.ts.map +1 -0
- package/dist/dependencies/parsers/python/pythonParser.js +336 -0
- package/dist/dependencies/parsers/python/pythonParser.js.map +1 -0
- package/dist/dependencies/types.d.ts +280 -0
- package/dist/dependencies/types.d.ts.map +1 -0
- package/dist/dependencies/types.js +59 -0
- package/dist/dependencies/types.js.map +1 -0
- package/dist/i18n/index.d.ts +2 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +18 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/translations.d.ts +55 -0
- package/dist/i18n/translations.d.ts.map +1 -0
- package/dist/i18n/translations.js +119 -0
- package/dist/i18n/translations.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/reports/dependencyReportGenerator.d.ts +20 -0
- package/dist/reports/dependencyReportGenerator.d.ts.map +1 -0
- package/dist/reports/dependencyReportGenerator.js +690 -0
- package/dist/reports/dependencyReportGenerator.js.map +1 -0
- package/dist/reports/htmlReportGenerator.d.ts +43 -0
- package/dist/reports/htmlReportGenerator.d.ts.map +1 -0
- package/dist/reports/htmlReportGenerator.js +793 -0
- package/dist/reports/htmlReportGenerator.js.map +1 -0
- package/dist/reports/index.d.ts +7 -0
- package/dist/reports/index.d.ts.map +1 -0
- package/dist/reports/index.js +23 -0
- package/dist/reports/index.js.map +1 -0
- package/dist/reports/installedDepsReportGenerator.d.ts +14 -0
- package/dist/reports/installedDepsReportGenerator.d.ts.map +1 -0
- package/dist/reports/installedDepsReportGenerator.js +872 -0
- package/dist/reports/installedDepsReportGenerator.js.map +1 -0
- package/dist/rules/index.d.ts +31 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +95 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/malware/categories/backdoors.d.ts +12 -0
- package/dist/rules/malware/categories/backdoors.d.ts.map +1 -0
- package/dist/rules/malware/categories/backdoors.js +163 -0
- package/dist/rules/malware/categories/backdoors.js.map +1 -0
- package/dist/rules/malware/categories/cryptominers.d.ts +13 -0
- package/dist/rules/malware/categories/cryptominers.d.ts.map +1 -0
- package/dist/rules/malware/categories/cryptominers.js +415 -0
- package/dist/rules/malware/categories/cryptominers.js.map +1 -0
- package/dist/rules/malware/categories/exfiltration.d.ts +20 -0
- package/dist/rules/malware/categories/exfiltration.d.ts.map +1 -0
- package/dist/rules/malware/categories/exfiltration.js +658 -0
- package/dist/rules/malware/categories/exfiltration.js.map +1 -0
- package/dist/rules/malware/categories/keyloggers.d.ts +19 -0
- package/dist/rules/malware/categories/keyloggers.d.ts.map +1 -0
- package/dist/rules/malware/categories/keyloggers.js +763 -0
- package/dist/rules/malware/categories/keyloggers.js.map +1 -0
- package/dist/rules/malware/categories/loaders.d.ts +20 -0
- package/dist/rules/malware/categories/loaders.d.ts.map +1 -0
- package/dist/rules/malware/categories/loaders.js +702 -0
- package/dist/rules/malware/categories/loaders.js.map +1 -0
- package/dist/rules/malware/categories/network.d.ts +19 -0
- package/dist/rules/malware/categories/network.d.ts.map +1 -0
- package/dist/rules/malware/categories/network.js +622 -0
- package/dist/rules/malware/categories/network.js.map +1 -0
- package/dist/rules/malware/categories/obfuscation.d.ts +22 -0
- package/dist/rules/malware/categories/obfuscation.d.ts.map +1 -0
- package/dist/rules/malware/categories/obfuscation.js +766 -0
- package/dist/rules/malware/categories/obfuscation.js.map +1 -0
- package/dist/rules/malware/constants/index.d.ts +281 -0
- package/dist/rules/malware/constants/index.d.ts.map +1 -0
- package/dist/rules/malware/constants/index.js +327 -0
- package/dist/rules/malware/constants/index.js.map +1 -0
- package/dist/rules/malware/engine/index.d.ts +178 -0
- package/dist/rules/malware/engine/index.d.ts.map +1 -0
- package/dist/rules/malware/engine/index.js +552 -0
- package/dist/rules/malware/engine/index.js.map +1 -0
- package/dist/rules/malware/index.d.ts +205 -0
- package/dist/rules/malware/index.d.ts.map +1 -0
- package/dist/rules/malware/index.js +837 -0
- package/dist/rules/malware/index.js.map +1 -0
- package/dist/rules/malware/scoring/index.d.ts +84 -0
- package/dist/rules/malware/scoring/index.d.ts.map +1 -0
- package/dist/rules/malware/scoring/index.js +441 -0
- package/dist/rules/malware/scoring/index.js.map +1 -0
- package/dist/rules/malware/types/index.d.ts +616 -0
- package/dist/rules/malware/types/index.d.ts.map +1 -0
- package/dist/rules/malware/types/index.js +155 -0
- package/dist/rules/malware/types/index.js.map +1 -0
- package/dist/rules/malware/utils/index.d.ts +117 -0
- package/dist/rules/malware/utils/index.d.ts.map +1 -0
- package/dist/rules/malware/utils/index.js +514 -0
- package/dist/rules/malware/utils/index.js.map +1 -0
- package/dist/rules/standards.d.ts +26 -0
- package/dist/rules/standards.d.ts.map +1 -0
- package/dist/rules/standards.js +352 -0
- package/dist/rules/standards.js.map +1 -0
- package/dist/rules/vulnerabilities/constants/index.d.ts +835 -0
- package/dist/rules/vulnerabilities/constants/index.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/constants/index.js +544 -0
- package/dist/rules/vulnerabilities/constants/index.js.map +1 -0
- package/dist/rules/vulnerabilities/engine/index.d.ts +145 -0
- package/dist/rules/vulnerabilities/engine/index.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/engine/index.js +581 -0
- package/dist/rules/vulnerabilities/engine/index.js.map +1 -0
- package/dist/rules/vulnerabilities/index.d.ts +148 -0
- package/dist/rules/vulnerabilities/index.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/index.js +252 -0
- package/dist/rules/vulnerabilities/index.js.map +1 -0
- package/dist/rules/vulnerabilities/rules/authentication.d.ts +8 -0
- package/dist/rules/vulnerabilities/rules/authentication.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/rules/authentication.js +419 -0
- package/dist/rules/vulnerabilities/rules/authentication.js.map +1 -0
- package/dist/rules/vulnerabilities/rules/commandInjection.d.ts +8 -0
- package/dist/rules/vulnerabilities/rules/commandInjection.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/rules/commandInjection.js +300 -0
- package/dist/rules/vulnerabilities/rules/commandInjection.js.map +1 -0
- package/dist/rules/vulnerabilities/rules/csrf.d.ts +8 -0
- package/dist/rules/vulnerabilities/rules/csrf.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/rules/csrf.js +261 -0
- package/dist/rules/vulnerabilities/rules/csrf.js.map +1 -0
- package/dist/rules/vulnerabilities/rules/deserialization.d.ts +8 -0
- package/dist/rules/vulnerabilities/rules/deserialization.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/rules/deserialization.js +336 -0
- package/dist/rules/vulnerabilities/rules/deserialization.js.map +1 -0
- package/dist/rules/vulnerabilities/rules/fileUpload.d.ts +8 -0
- package/dist/rules/vulnerabilities/rules/fileUpload.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/rules/fileUpload.js +325 -0
- package/dist/rules/vulnerabilities/rules/fileUpload.js.map +1 -0
- package/dist/rules/vulnerabilities/rules/hardcodedSecrets.d.ts +8 -0
- package/dist/rules/vulnerabilities/rules/hardcodedSecrets.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/rules/hardcodedSecrets.js +446 -0
- package/dist/rules/vulnerabilities/rules/hardcodedSecrets.js.map +1 -0
- package/dist/rules/vulnerabilities/rules/index.d.ts +17 -0
- package/dist/rules/vulnerabilities/rules/index.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/rules/index.js +47 -0
- package/dist/rules/vulnerabilities/rules/index.js.map +1 -0
- package/dist/rules/vulnerabilities/rules/pathTraversal.d.ts +8 -0
- package/dist/rules/vulnerabilities/rules/pathTraversal.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/rules/pathTraversal.js +351 -0
- package/dist/rules/vulnerabilities/rules/pathTraversal.js.map +1 -0
- package/dist/rules/vulnerabilities/rules/prototypePollution.d.ts +8 -0
- package/dist/rules/vulnerabilities/rules/prototypePollution.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/rules/prototypePollution.js +272 -0
- package/dist/rules/vulnerabilities/rules/prototypePollution.js.map +1 -0
- package/dist/rules/vulnerabilities/rules/securityMisconfiguration.d.ts +8 -0
- package/dist/rules/vulnerabilities/rules/securityMisconfiguration.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/rules/securityMisconfiguration.js +438 -0
- package/dist/rules/vulnerabilities/rules/securityMisconfiguration.js.map +1 -0
- package/dist/rules/vulnerabilities/rules/sqlInjection.d.ts +12 -0
- package/dist/rules/vulnerabilities/rules/sqlInjection.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/rules/sqlInjection.js +636 -0
- package/dist/rules/vulnerabilities/rules/sqlInjection.js.map +1 -0
- package/dist/rules/vulnerabilities/rules/ssrf.d.ts +8 -0
- package/dist/rules/vulnerabilities/rules/ssrf.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/rules/ssrf.js +401 -0
- package/dist/rules/vulnerabilities/rules/ssrf.js.map +1 -0
- package/dist/rules/vulnerabilities/rules/xss.d.ts +11 -0
- package/dist/rules/vulnerabilities/rules/xss.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/rules/xss.js +724 -0
- package/dist/rules/vulnerabilities/rules/xss.js.map +1 -0
- package/dist/rules/vulnerabilities/scoring/index.d.ts +80 -0
- package/dist/rules/vulnerabilities/scoring/index.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/scoring/index.js +414 -0
- package/dist/rules/vulnerabilities/scoring/index.js.map +1 -0
- package/dist/rules/vulnerabilities/types/index.d.ts +830 -0
- package/dist/rules/vulnerabilities/types/index.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/types/index.js +164 -0
- package/dist/rules/vulnerabilities/types/index.js.map +1 -0
- package/dist/rules/vulnerabilities/utils/index.d.ts +206 -0
- package/dist/rules/vulnerabilities/utils/index.d.ts.map +1 -0
- package/dist/rules/vulnerabilities/utils/index.js +615 -0
- package/dist/rules/vulnerabilities/utils/index.js.map +1 -0
- package/dist/types/index.d.ts +359 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +61 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.d.ts +82 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +326 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +40 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +139 -0
- package/dist/utils/logger.js.map +1 -0
- package/docs/ARCHITECTURE.md +320 -0
- package/docs/V1.2.1-IA_Performances.md +116 -0
- package/docs/images/WIN_Defender.png +0 -0
- package/package.json +68 -0
- package/secure-scan.config.json +134 -0
- package/secure-scan.sln +29 -0
- package/src/ai/aiAnalyzer.ts +714 -0
- package/src/ai/index.ts +5 -0
- package/src/analyzers/base/baseAnalyzer.ts +66 -0
- package/src/analyzers/base/index.ts +5 -0
- package/src/analyzers/c-cpp/cppAnalyzer.ts +308 -0
- package/src/analyzers/c-cpp/index.ts +5 -0
- package/src/analyzers/core/engine/index.ts +5 -0
- package/src/analyzers/core/engine/ruleEngine.ts +221 -0
- package/src/analyzers/core/index.ts +8 -0
- package/src/analyzers/core/scanner/fileScanner.ts +204 -0
- package/src/analyzers/core/scanner/index.ts +5 -0
- package/src/analyzers/core/scoring/index.ts +5 -0
- package/src/analyzers/core/scoring/riskScoring.ts +198 -0
- package/src/analyzers/core/securityScanner.ts +321 -0
- package/src/analyzers/csharp/csharpAnalyzer.ts +328 -0
- package/src/analyzers/csharp/index.ts +5 -0
- package/src/analyzers/iac/iacAnalyzer.ts +318 -0
- package/src/analyzers/iac/index.ts +5 -0
- package/src/analyzers/index.ts +67 -0
- package/src/analyzers/java/index.ts +5 -0
- package/src/analyzers/java/javaAnalyzer.ts +320 -0
- package/src/analyzers/javascript/PROMPT_JS_ANALYZER.md +267 -0
- package/src/analyzers/javascript/astUtils.ts +789 -0
- package/src/analyzers/javascript/index.ts +50 -0
- package/src/analyzers/javascript/javascriptAnalyzer.ts +984 -0
- package/src/analyzers/javascript/malwareDetector.ts +697 -0
- package/src/analyzers/javascript/packageJsonAnalyzer.ts +626 -0
- package/src/analyzers/javascript/taintAnalyzer.ts +630 -0
- package/src/analyzers/php/index.ts +5 -0
- package/src/analyzers/php/phpAnalyzer.ts +280 -0
- package/src/analyzers/python/index.ts +5 -0
- package/src/analyzers/python/pythonAnalyzer.ts +319 -0
- package/src/cli/index.ts +276 -0
- package/src/dependencies/aiDependencyAnalyzer.ts +496 -0
- package/src/dependencies/database/cveDatabase.ts +426 -0
- package/src/dependencies/database/index.ts +6 -0
- package/src/dependencies/database/maliciousPackages.ts +286 -0
- package/src/dependencies/dependencyAnalyzer.ts +394 -0
- package/src/dependencies/detectors/index.ts +7 -0
- package/src/dependencies/detectors/securityStandards.ts +200 -0
- package/src/dependencies/detectors/vulnerabilityDetector.ts +343 -0
- package/src/dependencies/index.ts +27 -0
- package/src/dependencies/installed/index.ts +8 -0
- package/src/dependencies/installed/installedScanner.ts +821 -0
- package/src/dependencies/installed/malwarePatterns.ts +492 -0
- package/src/dependencies/installed/types.ts +287 -0
- package/src/dependencies/parsers/base/baseParser.ts +108 -0
- package/src/dependencies/parsers/base/index.ts +6 -0
- package/src/dependencies/parsers/cpp/cppParser.ts +245 -0
- package/src/dependencies/parsers/cpp/index.ts +6 -0
- package/src/dependencies/parsers/csharp/csharpParser.ts +151 -0
- package/src/dependencies/parsers/csharp/index.ts +6 -0
- package/src/dependencies/parsers/index.ts +56 -0
- package/src/dependencies/parsers/java/index.ts +6 -0
- package/src/dependencies/parsers/java/javaParser.ts +203 -0
- package/src/dependencies/parsers/javascript/index.ts +6 -0
- package/src/dependencies/parsers/javascript/javascriptParser.ts +362 -0
- package/src/dependencies/parsers/php/index.ts +6 -0
- package/src/dependencies/parsers/php/phpParser.ts +208 -0
- package/src/dependencies/parsers/python/index.ts +6 -0
- package/src/dependencies/parsers/python/pythonParser.ts +437 -0
- package/src/dependencies/types.ts +330 -0
- package/src/i18n/index.ts +1 -0
- package/src/i18n/translations.ts +194 -0
- package/src/index.ts +16 -0
- package/src/reports/dependencyReportGenerator.ts +717 -0
- package/src/reports/htmlReportGenerator.ts +781 -0
- package/src/reports/index.ts +7 -0
- package/src/reports/installedDepsReportGenerator.ts +899 -0
- package/src/rules/index.ts +58 -0
- package/src/rules/malware/INFO.md +287 -0
- package/src/rules/malware/categories/backdoors.ts +174 -0
- package/src/rules/malware/categories/cryptominers.ts +434 -0
- package/src/rules/malware/categories/exfiltration.ts +677 -0
- package/src/rules/malware/categories/keyloggers.ts +780 -0
- package/src/rules/malware/categories/loaders.ts +721 -0
- package/src/rules/malware/categories/network.ts +639 -0
- package/src/rules/malware/categories/obfuscation.ts +788 -0
- package/src/rules/malware/constants/index.ts +358 -0
- package/src/rules/malware/engine/index.ts +758 -0
- package/src/rules/malware/index.ts +928 -0
- package/src/rules/malware/scoring/index.ts +549 -0
- package/src/rules/malware/types/index.ts +752 -0
- package/src/rules/malware/utils/index.ts +643 -0
- package/src/rules/standards.ts +372 -0
- package/src/rules/vulnerabilities/PROMPT_VULNERABILITIES.md +226 -0
- package/src/rules/vulnerabilities/constants/index.ts +625 -0
- package/src/rules/vulnerabilities/engine/index.ts +831 -0
- package/src/rules/vulnerabilities/index.ts +312 -0
- package/src/rules/vulnerabilities/rules/authentication.ts +426 -0
- package/src/rules/vulnerabilities/rules/commandInjection.ts +307 -0
- package/src/rules/vulnerabilities/rules/csrf.ts +268 -0
- package/src/rules/vulnerabilities/rules/deserialization.ts +343 -0
- package/src/rules/vulnerabilities/rules/fileUpload.ts +332 -0
- package/src/rules/vulnerabilities/rules/hardcodedSecrets.ts +453 -0
- package/src/rules/vulnerabilities/rules/index.ts +17 -0
- package/src/rules/vulnerabilities/rules/pathTraversal.ts +358 -0
- package/src/rules/vulnerabilities/rules/prototypePollution.ts +279 -0
- package/src/rules/vulnerabilities/rules/securityMisconfiguration.ts +445 -0
- package/src/rules/vulnerabilities/rules/sqlInjection.ts +669 -0
- package/src/rules/vulnerabilities/rules/ssrf.ts +408 -0
- package/src/rules/vulnerabilities/rules/xss.ts +753 -0
- package/src/rules/vulnerabilities/scoring/index.ts +543 -0
- package/src/rules/vulnerabilities/types/index.ts +1004 -0
- package/src/rules/vulnerabilities/utils/index.ts +709 -0
- package/src/types/index.ts +391 -0
- package/src/utils/index.ts +306 -0
- package/src/utils/logger.ts +150 -0
- package/test-installed-scanner.ts +136 -0
- package/tsconfig.json +30 -0
|
@@ -0,0 +1,821 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Installed Dependencies Scanner
|
|
3
|
+
* Scans installed packages (node_modules, vendor, venv) for malware
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as fs from 'fs';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import * as crypto from 'crypto';
|
|
9
|
+
import {
|
|
10
|
+
InstalledPackage,
|
|
11
|
+
InstalledMalwareFinding,
|
|
12
|
+
InstalledDependenciesScanResult,
|
|
13
|
+
InstalledScanConfig,
|
|
14
|
+
InstalledScanStats,
|
|
15
|
+
ScannedFolder,
|
|
16
|
+
IntegrityIssue,
|
|
17
|
+
SuspiciousScriptFinding,
|
|
18
|
+
PostInstallScript,
|
|
19
|
+
InstalledPackageMetadata,
|
|
20
|
+
IntegrityStatus
|
|
21
|
+
} from './types';
|
|
22
|
+
import { MALWARE_PATTERNS, SUSPICIOUS_SCRIPT_PATTERNS, getPatternsForFile } from './malwarePatterns';
|
|
23
|
+
import { MalwareIndicator, PackageEcosystem } from '../types';
|
|
24
|
+
import { Severity } from '../../types';
|
|
25
|
+
import { logger } from '../../utils/logger';
|
|
26
|
+
import { generateId } from '../../utils';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Default configuration for installed dependencies scanner
|
|
30
|
+
*/
|
|
31
|
+
const DEFAULT_CONFIG: Partial<InstalledScanConfig> = {
|
|
32
|
+
maxFileSizeBytes: 5 * 1024 * 1024, // 5MB
|
|
33
|
+
fileExtensions: ['.js', '.ts', '.mjs', '.cjs', '.py', '.php', '.rb', '.sh', '.ps1', '.cmd', '.bat'],
|
|
34
|
+
verifyIntegrity: true,
|
|
35
|
+
scanPostInstallScripts: true,
|
|
36
|
+
maxDepth: 10,
|
|
37
|
+
verbose: false,
|
|
38
|
+
parallelScans: 4
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Folder configurations for different ecosystems
|
|
43
|
+
*/
|
|
44
|
+
const DEPENDENCY_FOLDERS = {
|
|
45
|
+
npm: ['node_modules'],
|
|
46
|
+
pip: ['venv', '.venv', 'env', '.env', 'site-packages', 'lib/python*/site-packages'],
|
|
47
|
+
composer: ['vendor'],
|
|
48
|
+
maven: ['.m2/repository'],
|
|
49
|
+
gradle: ['.gradle/caches/modules-2/files-2.1'],
|
|
50
|
+
nuget: ['packages', '.nuget/packages']
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Installed Dependencies Scanner Class
|
|
55
|
+
*/
|
|
56
|
+
export class InstalledDependenciesScanner {
|
|
57
|
+
private config: InstalledScanConfig;
|
|
58
|
+
private scannedFiles: Set<string> = new Set();
|
|
59
|
+
private stats: InstalledScanStats;
|
|
60
|
+
|
|
61
|
+
constructor(config: InstalledScanConfig) {
|
|
62
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
63
|
+
this.stats = this.initializeStats();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Run the installed dependencies scan
|
|
68
|
+
*/
|
|
69
|
+
async scan(): Promise<InstalledDependenciesScanResult> {
|
|
70
|
+
const startTime = Date.now();
|
|
71
|
+
logger.info('🔍 Starting installed dependencies scan...');
|
|
72
|
+
|
|
73
|
+
const scannedFolders: ScannedFolder[] = [];
|
|
74
|
+
const installedPackages: InstalledPackage[] = [];
|
|
75
|
+
const malwareFindings: InstalledMalwareFinding[] = [];
|
|
76
|
+
const integrityIssues: IntegrityIssue[] = [];
|
|
77
|
+
const suspiciousScripts: SuspiciousScriptFinding[] = [];
|
|
78
|
+
|
|
79
|
+
// Find and scan dependency folders
|
|
80
|
+
const foldersToScan = this.config.foldersToScan || this.findDependencyFolders();
|
|
81
|
+
|
|
82
|
+
for (const folderPath of foldersToScan) {
|
|
83
|
+
if (!fs.existsSync(folderPath)) continue;
|
|
84
|
+
|
|
85
|
+
logger.info(`📂 Scanning: ${folderPath}`);
|
|
86
|
+
|
|
87
|
+
const folderInfo = await this.scanDependencyFolder(folderPath);
|
|
88
|
+
scannedFolders.push(folderInfo.scannedFolder);
|
|
89
|
+
installedPackages.push(...folderInfo.packages);
|
|
90
|
+
malwareFindings.push(...folderInfo.malwareFindings);
|
|
91
|
+
suspiciousScripts.push(...folderInfo.suspiciousScripts);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Verify integrity if enabled
|
|
95
|
+
if (this.config.verifyIntegrity) {
|
|
96
|
+
const integrity = await this.verifyPackageIntegrity(installedPackages);
|
|
97
|
+
integrityIssues.push(...integrity);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Update statistics
|
|
101
|
+
const endTime = Date.now();
|
|
102
|
+
this.stats.duration = endTime - startTime;
|
|
103
|
+
this.stats.totalFoldersScanned = scannedFolders.length;
|
|
104
|
+
this.stats.totalPackagesFound = installedPackages.length;
|
|
105
|
+
this.stats.malwareFindingsCount = malwareFindings.length;
|
|
106
|
+
this.stats.integrityIssuesCount = integrityIssues.length;
|
|
107
|
+
this.stats.suspiciousScriptsCount = suspiciousScripts.length;
|
|
108
|
+
|
|
109
|
+
// Count findings by severity
|
|
110
|
+
for (const finding of malwareFindings) {
|
|
111
|
+
this.stats.findingsBySeverity[finding.severity] =
|
|
112
|
+
(this.stats.findingsBySeverity[finding.severity] || 0) + 1;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
logger.info(`✅ Scan complete: ${malwareFindings.length} malware findings, ${integrityIssues.length} integrity issues`);
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
scannedFolders,
|
|
119
|
+
installedPackages,
|
|
120
|
+
malwareFindings,
|
|
121
|
+
integrityIssues,
|
|
122
|
+
suspiciousScripts,
|
|
123
|
+
stats: this.stats,
|
|
124
|
+
timestamp: new Date()
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Find dependency folders in the project
|
|
130
|
+
*/
|
|
131
|
+
private findDependencyFolders(): string[] {
|
|
132
|
+
const folders: string[] = [];
|
|
133
|
+
const projectPath = this.config.projectPath;
|
|
134
|
+
|
|
135
|
+
// Check for node_modules
|
|
136
|
+
const nodeModules = path.join(projectPath, 'node_modules');
|
|
137
|
+
if (fs.existsSync(nodeModules)) {
|
|
138
|
+
folders.push(nodeModules);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Check for vendor (PHP)
|
|
142
|
+
const vendor = path.join(projectPath, 'vendor');
|
|
143
|
+
if (fs.existsSync(vendor)) {
|
|
144
|
+
folders.push(vendor);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Check for Python virtual environments
|
|
148
|
+
for (const venvName of ['venv', '.venv', 'env', '.env']) {
|
|
149
|
+
const venv = path.join(projectPath, venvName);
|
|
150
|
+
if (fs.existsSync(venv)) {
|
|
151
|
+
// Look for site-packages
|
|
152
|
+
const sitePackages = this.findSitePackages(venv);
|
|
153
|
+
if (sitePackages) {
|
|
154
|
+
folders.push(sitePackages);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return folders;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Find site-packages in a Python virtual environment
|
|
164
|
+
*/
|
|
165
|
+
private findSitePackages(venvPath: string): string | null {
|
|
166
|
+
// Windows: venv/Lib/site-packages
|
|
167
|
+
const windowsPath = path.join(venvPath, 'Lib', 'site-packages');
|
|
168
|
+
if (fs.existsSync(windowsPath)) {
|
|
169
|
+
return windowsPath;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Unix: venv/lib/pythonX.X/site-packages
|
|
173
|
+
const libPath = path.join(venvPath, 'lib');
|
|
174
|
+
if (fs.existsSync(libPath)) {
|
|
175
|
+
try {
|
|
176
|
+
const entries = fs.readdirSync(libPath);
|
|
177
|
+
for (const entry of entries) {
|
|
178
|
+
if (entry.startsWith('python')) {
|
|
179
|
+
const sitePackages = path.join(libPath, entry, 'site-packages');
|
|
180
|
+
if (fs.existsSync(sitePackages)) {
|
|
181
|
+
return sitePackages;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
} catch {
|
|
186
|
+
// Ignore errors
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Scan a dependency folder
|
|
195
|
+
*/
|
|
196
|
+
private async scanDependencyFolder(folderPath: string): Promise<{
|
|
197
|
+
scannedFolder: ScannedFolder;
|
|
198
|
+
packages: InstalledPackage[];
|
|
199
|
+
malwareFindings: InstalledMalwareFinding[];
|
|
200
|
+
suspiciousScripts: SuspiciousScriptFinding[];
|
|
201
|
+
}> {
|
|
202
|
+
const packages: InstalledPackage[] = [];
|
|
203
|
+
const malwareFindings: InstalledMalwareFinding[] = [];
|
|
204
|
+
const suspiciousScripts: SuspiciousScriptFinding[] = [];
|
|
205
|
+
|
|
206
|
+
const folderType = this.getFolderType(folderPath);
|
|
207
|
+
const ecosystem = this.getEcosystemFromFolder(folderPath);
|
|
208
|
+
|
|
209
|
+
let totalSize = 0;
|
|
210
|
+
let filesScanned = 0;
|
|
211
|
+
|
|
212
|
+
// Get all packages in the folder
|
|
213
|
+
const packageDirs = await this.getPackageDirectories(folderPath, ecosystem);
|
|
214
|
+
|
|
215
|
+
for (const packageDir of packageDirs) {
|
|
216
|
+
const pkg = await this.parseInstalledPackage(packageDir, ecosystem);
|
|
217
|
+
if (pkg) {
|
|
218
|
+
packages.push(pkg);
|
|
219
|
+
totalSize += pkg.sizeBytes;
|
|
220
|
+
|
|
221
|
+
// Scan package files for malware
|
|
222
|
+
const findings = await this.scanPackageForMalware(pkg, packageDir);
|
|
223
|
+
malwareFindings.push(...findings.malwareFindings);
|
|
224
|
+
filesScanned += findings.filesScanned;
|
|
225
|
+
|
|
226
|
+
// Check post-install scripts
|
|
227
|
+
if (this.config.scanPostInstallScripts && pkg.hasPostInstallScripts) {
|
|
228
|
+
const scriptFindings = this.analyzePostInstallScripts(pkg);
|
|
229
|
+
suspiciousScripts.push(...scriptFindings);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Update ecosystem stats
|
|
233
|
+
this.stats.packagesByEcosystem[ecosystem] =
|
|
234
|
+
(this.stats.packagesByEcosystem[ecosystem] || 0) + 1;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
this.stats.totalFilesScanned += filesScanned;
|
|
239
|
+
this.stats.totalBytesScanned += totalSize;
|
|
240
|
+
|
|
241
|
+
return {
|
|
242
|
+
scannedFolder: {
|
|
243
|
+
path: folderPath,
|
|
244
|
+
type: folderType,
|
|
245
|
+
ecosystem,
|
|
246
|
+
packageCount: packages.length,
|
|
247
|
+
totalSizeBytes: totalSize,
|
|
248
|
+
filesScanned
|
|
249
|
+
},
|
|
250
|
+
packages,
|
|
251
|
+
malwareFindings,
|
|
252
|
+
suspiciousScripts
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Get folder type from path
|
|
258
|
+
*/
|
|
259
|
+
private getFolderType(folderPath: string): ScannedFolder['type'] {
|
|
260
|
+
const folderName = path.basename(folderPath);
|
|
261
|
+
|
|
262
|
+
if (folderName === 'node_modules') return 'node_modules';
|
|
263
|
+
if (folderName === 'vendor') return 'vendor';
|
|
264
|
+
if (folderName === 'site-packages') return 'site-packages';
|
|
265
|
+
if (['venv', '.venv', 'env', '.env'].includes(folderName)) return 'venv';
|
|
266
|
+
if (folderName === 'packages') return 'packages';
|
|
267
|
+
|
|
268
|
+
return 'other';
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Get ecosystem from folder path
|
|
273
|
+
*/
|
|
274
|
+
private getEcosystemFromFolder(folderPath: string): PackageEcosystem {
|
|
275
|
+
if (folderPath.includes('node_modules')) return 'npm';
|
|
276
|
+
if (folderPath.includes('vendor')) return 'composer';
|
|
277
|
+
if (folderPath.includes('site-packages') || folderPath.includes('venv')) return 'pip';
|
|
278
|
+
if (folderPath.includes('.nuget') || folderPath.includes('packages')) return 'nuget';
|
|
279
|
+
|
|
280
|
+
return 'npm'; // Default
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Get package directories in a dependency folder
|
|
285
|
+
*/
|
|
286
|
+
private async getPackageDirectories(folderPath: string, ecosystem: PackageEcosystem): Promise<string[]> {
|
|
287
|
+
const packageDirs: string[] = [];
|
|
288
|
+
|
|
289
|
+
try {
|
|
290
|
+
const entries = fs.readdirSync(folderPath, { withFileTypes: true });
|
|
291
|
+
|
|
292
|
+
for (const entry of entries) {
|
|
293
|
+
if (!entry.isDirectory()) continue;
|
|
294
|
+
|
|
295
|
+
const fullPath = path.join(folderPath, entry.name);
|
|
296
|
+
|
|
297
|
+
// Handle scoped packages for npm (@scope/package)
|
|
298
|
+
if (ecosystem === 'npm' && entry.name.startsWith('@')) {
|
|
299
|
+
const scopedEntries = fs.readdirSync(fullPath, { withFileTypes: true });
|
|
300
|
+
for (const scopedEntry of scopedEntries) {
|
|
301
|
+
if (scopedEntry.isDirectory()) {
|
|
302
|
+
packageDirs.push(path.join(fullPath, scopedEntry.name));
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
} else if (!entry.name.startsWith('.')) {
|
|
306
|
+
packageDirs.push(fullPath);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
} catch (error) {
|
|
310
|
+
logger.debug(`Error reading directory ${folderPath}: ${error}`);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return packageDirs;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Parse an installed package directory
|
|
318
|
+
*/
|
|
319
|
+
private async parseInstalledPackage(packageDir: string, ecosystem: PackageEcosystem): Promise<InstalledPackage | null> {
|
|
320
|
+
try {
|
|
321
|
+
let name = path.basename(packageDir);
|
|
322
|
+
let version = 'unknown';
|
|
323
|
+
let metadata: InstalledPackageMetadata = {};
|
|
324
|
+
let hasPostInstallScripts = false;
|
|
325
|
+
let postInstallScripts: PostInstallScript[] = [];
|
|
326
|
+
|
|
327
|
+
// Handle scoped packages
|
|
328
|
+
const parentDir = path.basename(path.dirname(packageDir));
|
|
329
|
+
if (parentDir.startsWith('@')) {
|
|
330
|
+
name = `${parentDir}/${name}`;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Parse package.json for npm
|
|
334
|
+
if (ecosystem === 'npm') {
|
|
335
|
+
const packageJsonPath = path.join(packageDir, 'package.json');
|
|
336
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
337
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
338
|
+
name = packageJson.name || name;
|
|
339
|
+
version = packageJson.version || version;
|
|
340
|
+
metadata = {
|
|
341
|
+
author: typeof packageJson.author === 'string' ? packageJson.author : packageJson.author?.name,
|
|
342
|
+
license: packageJson.license,
|
|
343
|
+
homepage: packageJson.homepage,
|
|
344
|
+
repository: typeof packageJson.repository === 'string' ? packageJson.repository : packageJson.repository?.url,
|
|
345
|
+
description: packageJson.description,
|
|
346
|
+
main: packageJson.main,
|
|
347
|
+
binaries: packageJson.bin ? Object.keys(packageJson.bin) : undefined
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
// Check for post-install scripts
|
|
351
|
+
const scripts = packageJson.scripts || {};
|
|
352
|
+
for (const scriptType of ['preinstall', 'install', 'postinstall', 'preuninstall', 'postuninstall'] as const) {
|
|
353
|
+
if (scripts[scriptType]) {
|
|
354
|
+
hasPostInstallScripts = true;
|
|
355
|
+
const scriptInfo = this.analyzeScript(scriptType, scripts[scriptType], packageDir);
|
|
356
|
+
postInstallScripts.push(scriptInfo);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Parse for pip/Python
|
|
363
|
+
if (ecosystem === 'pip') {
|
|
364
|
+
// Try to find PKG-INFO or METADATA
|
|
365
|
+
const metadataPath = path.join(packageDir, 'PKG-INFO');
|
|
366
|
+
const distInfoDir = this.findDistInfoDir(packageDir);
|
|
367
|
+
|
|
368
|
+
if (distInfoDir) {
|
|
369
|
+
const metaPath = path.join(distInfoDir, 'METADATA');
|
|
370
|
+
if (fs.existsSync(metaPath)) {
|
|
371
|
+
const content = fs.readFileSync(metaPath, 'utf-8');
|
|
372
|
+
const parsed = this.parsePythonMetadata(content);
|
|
373
|
+
name = parsed.name || name;
|
|
374
|
+
version = parsed.version || version;
|
|
375
|
+
metadata = {
|
|
376
|
+
author: parsed.author,
|
|
377
|
+
license: parsed.license,
|
|
378
|
+
homepage: parsed.homepage,
|
|
379
|
+
description: parsed.summary
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Calculate size and file count
|
|
386
|
+
const sizeInfo = this.calculateDirectorySize(packageDir);
|
|
387
|
+
|
|
388
|
+
return {
|
|
389
|
+
name,
|
|
390
|
+
version,
|
|
391
|
+
ecosystem,
|
|
392
|
+
installPath: packageDir,
|
|
393
|
+
sizeBytes: sizeInfo.size,
|
|
394
|
+
fileCount: sizeInfo.fileCount,
|
|
395
|
+
hasPostInstallScripts,
|
|
396
|
+
postInstallScripts: postInstallScripts.length > 0 ? postInstallScripts : undefined,
|
|
397
|
+
metadata
|
|
398
|
+
};
|
|
399
|
+
} catch (error) {
|
|
400
|
+
logger.debug(`Error parsing package at ${packageDir}: ${error}`);
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Find .dist-info directory for Python packages
|
|
407
|
+
*/
|
|
408
|
+
private findDistInfoDir(packageDir: string): string | null {
|
|
409
|
+
const parentDir = path.dirname(packageDir);
|
|
410
|
+
const packageName = path.basename(packageDir);
|
|
411
|
+
|
|
412
|
+
try {
|
|
413
|
+
const entries = fs.readdirSync(parentDir);
|
|
414
|
+
for (const entry of entries) {
|
|
415
|
+
if (entry.startsWith(packageName.replace(/-/g, '_')) && entry.endsWith('.dist-info')) {
|
|
416
|
+
return path.join(parentDir, entry);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
} catch {
|
|
420
|
+
// Ignore
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Parse Python package metadata
|
|
428
|
+
*/
|
|
429
|
+
private parsePythonMetadata(content: string): Record<string, string> {
|
|
430
|
+
const result: Record<string, string> = {};
|
|
431
|
+
const lines = content.split('\n');
|
|
432
|
+
|
|
433
|
+
for (const line of lines) {
|
|
434
|
+
const match = line.match(/^([A-Za-z-]+):\s*(.+)$/);
|
|
435
|
+
if (match) {
|
|
436
|
+
const key = match[1].toLowerCase().replace(/-/g, '_');
|
|
437
|
+
result[key] = match[2].trim();
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
return {
|
|
442
|
+
name: result.name,
|
|
443
|
+
version: result.version,
|
|
444
|
+
author: result.author,
|
|
445
|
+
license: result.license,
|
|
446
|
+
homepage: result.home_page,
|
|
447
|
+
summary: result.summary
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Analyze a post-install script
|
|
453
|
+
*/
|
|
454
|
+
private analyzeScript(type: PostInstallScript['type'], command: string, packageDir: string): PostInstallScript {
|
|
455
|
+
const riskIndicators: string[] = [];
|
|
456
|
+
let riskLevel: Severity = Severity.INFO;
|
|
457
|
+
let scriptContent: string | undefined;
|
|
458
|
+
let scriptPath: string | undefined;
|
|
459
|
+
|
|
460
|
+
// Check for file reference
|
|
461
|
+
const fileMatch = command.match(/node\s+([^\s]+)/);
|
|
462
|
+
if (fileMatch) {
|
|
463
|
+
const possiblePath = path.join(packageDir, fileMatch[1]);
|
|
464
|
+
if (fs.existsSync(possiblePath)) {
|
|
465
|
+
scriptPath = possiblePath;
|
|
466
|
+
try {
|
|
467
|
+
scriptContent = fs.readFileSync(possiblePath, 'utf-8');
|
|
468
|
+
} catch {
|
|
469
|
+
// Ignore read errors
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Analyze command and content for suspicious patterns
|
|
475
|
+
const contentToAnalyze = scriptContent || command;
|
|
476
|
+
|
|
477
|
+
for (const pattern of SUSPICIOUS_SCRIPT_PATTERNS) {
|
|
478
|
+
if (pattern.test(contentToAnalyze)) {
|
|
479
|
+
riskIndicators.push(pattern.source);
|
|
480
|
+
if (riskLevel === Severity.INFO) riskLevel = Severity.LOW;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Check for high-risk patterns
|
|
485
|
+
if (/curl.*\|.*sh|wget.*\|.*bash|rm\s+-rf/.test(contentToAnalyze)) {
|
|
486
|
+
riskLevel = Severity.CRITICAL;
|
|
487
|
+
} else if (/eval|exec|subprocess|child_process/.test(contentToAnalyze)) {
|
|
488
|
+
riskLevel = Severity.HIGH;
|
|
489
|
+
} else if (/http|fetch|request/.test(contentToAnalyze)) {
|
|
490
|
+
riskLevel = Severity.MEDIUM;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
return {
|
|
494
|
+
type,
|
|
495
|
+
command,
|
|
496
|
+
scriptPath,
|
|
497
|
+
content: scriptContent,
|
|
498
|
+
riskLevel,
|
|
499
|
+
riskIndicators
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Analyze post-install scripts for a package
|
|
505
|
+
*/
|
|
506
|
+
private analyzePostInstallScripts(pkg: InstalledPackage): SuspiciousScriptFinding[] {
|
|
507
|
+
const findings: SuspiciousScriptFinding[] = [];
|
|
508
|
+
|
|
509
|
+
if (!pkg.postInstallScripts) return findings;
|
|
510
|
+
|
|
511
|
+
for (const script of pkg.postInstallScripts) {
|
|
512
|
+
if (script.riskLevel !== 'info' && script.riskIndicators.length > 0) {
|
|
513
|
+
findings.push({
|
|
514
|
+
packageName: pkg.name,
|
|
515
|
+
script,
|
|
516
|
+
severity: script.riskLevel,
|
|
517
|
+
description: `Suspicious ${script.type} script detected in package ${pkg.name}`,
|
|
518
|
+
riskIndicators: script.riskIndicators
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
return findings;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Calculate directory size
|
|
528
|
+
*/
|
|
529
|
+
private calculateDirectorySize(dirPath: string): { size: number; fileCount: number } {
|
|
530
|
+
let size = 0;
|
|
531
|
+
let fileCount = 0;
|
|
532
|
+
|
|
533
|
+
const calculate = (dir: string, depth: number = 0) => {
|
|
534
|
+
if (depth > 5) return; // Limit recursion depth
|
|
535
|
+
|
|
536
|
+
try {
|
|
537
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
538
|
+
for (const entry of entries) {
|
|
539
|
+
const fullPath = path.join(dir, entry.name);
|
|
540
|
+
if (entry.isDirectory()) {
|
|
541
|
+
calculate(fullPath, depth + 1);
|
|
542
|
+
} else if (entry.isFile()) {
|
|
543
|
+
const stats = fs.statSync(fullPath);
|
|
544
|
+
size += stats.size;
|
|
545
|
+
fileCount++;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
} catch {
|
|
549
|
+
// Ignore permission errors
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
|
|
553
|
+
calculate(dirPath);
|
|
554
|
+
return { size, fileCount };
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Scan a package for malware
|
|
559
|
+
*/
|
|
560
|
+
private async scanPackageForMalware(pkg: InstalledPackage, packageDir: string): Promise<{
|
|
561
|
+
malwareFindings: InstalledMalwareFinding[];
|
|
562
|
+
filesScanned: number;
|
|
563
|
+
}> {
|
|
564
|
+
const malwareFindings: InstalledMalwareFinding[] = [];
|
|
565
|
+
let filesScanned = 0;
|
|
566
|
+
|
|
567
|
+
const scanFile = (filePath: string) => {
|
|
568
|
+
if (this.scannedFiles.has(filePath)) return;
|
|
569
|
+
this.scannedFiles.add(filePath);
|
|
570
|
+
|
|
571
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
572
|
+
if (!this.config.fileExtensions?.includes(ext)) return;
|
|
573
|
+
|
|
574
|
+
try {
|
|
575
|
+
const stats = fs.statSync(filePath);
|
|
576
|
+
if (stats.size > (this.config.maxFileSizeBytes ?? 5 * 1024 * 1024)) return;
|
|
577
|
+
|
|
578
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
579
|
+
filesScanned++;
|
|
580
|
+
|
|
581
|
+
// Get patterns applicable to this file type
|
|
582
|
+
const patterns = getPatternsForFile(filePath);
|
|
583
|
+
|
|
584
|
+
for (const pattern of patterns) {
|
|
585
|
+
for (const regex of pattern.patterns) {
|
|
586
|
+
// Reset regex state
|
|
587
|
+
regex.lastIndex = 0;
|
|
588
|
+
const match = regex.exec(content);
|
|
589
|
+
|
|
590
|
+
if (match) {
|
|
591
|
+
// Find line number
|
|
592
|
+
const beforeMatch = content.substring(0, match.index);
|
|
593
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
594
|
+
|
|
595
|
+
// Extract code snippet
|
|
596
|
+
const lines = content.split('\n');
|
|
597
|
+
const startLine = Math.max(0, lineNumber - 2);
|
|
598
|
+
const endLine = Math.min(lines.length, lineNumber + 2);
|
|
599
|
+
const codeSnippet = lines.slice(startLine, endLine).join('\n');
|
|
600
|
+
|
|
601
|
+
malwareFindings.push({
|
|
602
|
+
id: generateId(),
|
|
603
|
+
package: pkg,
|
|
604
|
+
filePath,
|
|
605
|
+
lineNumber,
|
|
606
|
+
indicators: [pattern.indicator],
|
|
607
|
+
severity: pattern.severity,
|
|
608
|
+
title: pattern.name,
|
|
609
|
+
description: pattern.description,
|
|
610
|
+
matchedPattern: pattern.id,
|
|
611
|
+
codeSnippet,
|
|
612
|
+
standards: pattern.standards,
|
|
613
|
+
recommendation: this.getRecommendation(pattern.indicator),
|
|
614
|
+
confidence: pattern.confidence,
|
|
615
|
+
timestamp: new Date()
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
// Only report first match per pattern per file
|
|
619
|
+
break;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
} catch (error) {
|
|
624
|
+
// Ignore file read errors (binary files, etc.)
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
const scanDirectory = (dir: string, depth: number = 0) => {
|
|
629
|
+
if (depth > (this.config.maxDepth ?? 10)) return;
|
|
630
|
+
|
|
631
|
+
try {
|
|
632
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
633
|
+
for (const entry of entries) {
|
|
634
|
+
const fullPath = path.join(dir, entry.name);
|
|
635
|
+
if (entry.isDirectory()) {
|
|
636
|
+
// Skip nested node_modules
|
|
637
|
+
if (entry.name === 'node_modules' && depth > 0) continue;
|
|
638
|
+
scanDirectory(fullPath, depth + 1);
|
|
639
|
+
} else if (entry.isFile()) {
|
|
640
|
+
scanFile(fullPath);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
} catch {
|
|
644
|
+
// Ignore permission errors
|
|
645
|
+
}
|
|
646
|
+
};
|
|
647
|
+
|
|
648
|
+
scanDirectory(packageDir);
|
|
649
|
+
return { malwareFindings, filesScanned };
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* Get recommendation for malware indicator
|
|
654
|
+
*/
|
|
655
|
+
private getRecommendation(indicator: MalwareIndicator): string {
|
|
656
|
+
const recommendations: Record<MalwareIndicator, string> = {
|
|
657
|
+
[MalwareIndicator.BACKDOOR]: 'Remove this package immediately. It contains backdoor code that allows remote access.',
|
|
658
|
+
[MalwareIndicator.CRYPTOMINER]: 'Remove this package. It contains cryptocurrency mining code that steals computational resources.',
|
|
659
|
+
[MalwareIndicator.STEALER]: 'Remove this package immediately. It attempts to steal credentials or sensitive data.',
|
|
660
|
+
[MalwareIndicator.LOADER]: 'Remove this package. It downloads and executes code from external sources.',
|
|
661
|
+
[MalwareIndicator.OBFUSCATED]: 'Review this package carefully. Heavily obfuscated code may hide malicious functionality.',
|
|
662
|
+
[MalwareIndicator.DATA_EXFILTRATION]: 'Remove this package. It attempts to send sensitive data to external servers.',
|
|
663
|
+
[MalwareIndicator.KNOWN_MALWARE]: 'Remove this package immediately. It has been identified as known malware.'
|
|
664
|
+
};
|
|
665
|
+
|
|
666
|
+
return recommendations[indicator] || 'Review this package and consider removing it.';
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Verify package integrity
|
|
671
|
+
*/
|
|
672
|
+
private async verifyPackageIntegrity(packages: InstalledPackage[]): Promise<IntegrityIssue[]> {
|
|
673
|
+
const issues: IntegrityIssue[] = [];
|
|
674
|
+
|
|
675
|
+
// Try to load lock file
|
|
676
|
+
const lockFileData = await this.loadLockFile();
|
|
677
|
+
if (!lockFileData) {
|
|
678
|
+
logger.debug('No lock file found for integrity verification');
|
|
679
|
+
return issues;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
for (const pkg of packages) {
|
|
683
|
+
const expectedVersion = lockFileData.packages[pkg.name];
|
|
684
|
+
|
|
685
|
+
if (!expectedVersion) {
|
|
686
|
+
// Package not in lock file
|
|
687
|
+
issues.push({
|
|
688
|
+
packageName: pkg.name,
|
|
689
|
+
issueType: 'unexpected_package',
|
|
690
|
+
severity: Severity.MEDIUM,
|
|
691
|
+
description: `Package ${pkg.name} is installed but not in lock file`,
|
|
692
|
+
actual: pkg.version
|
|
693
|
+
});
|
|
694
|
+
} else if (expectedVersion !== pkg.version) {
|
|
695
|
+
// Version mismatch
|
|
696
|
+
issues.push({
|
|
697
|
+
packageName: pkg.name,
|
|
698
|
+
issueType: 'version_mismatch',
|
|
699
|
+
severity: Severity.HIGH,
|
|
700
|
+
description: `Package ${pkg.name} version mismatch - possible tampering`,
|
|
701
|
+
expected: expectedVersion,
|
|
702
|
+
actual: pkg.version
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
// Update package integrity status
|
|
707
|
+
pkg.integrityStatus = {
|
|
708
|
+
status: expectedVersion === pkg.version ? 'verified' :
|
|
709
|
+
expectedVersion ? 'mismatch' : 'unknown',
|
|
710
|
+
expectedVersion,
|
|
711
|
+
installedVersion: pkg.version
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// Check for missing packages
|
|
716
|
+
for (const [pkgName, version] of Object.entries(lockFileData.packages)) {
|
|
717
|
+
const installed = packages.find(p => p.name === pkgName);
|
|
718
|
+
if (!installed) {
|
|
719
|
+
issues.push({
|
|
720
|
+
packageName: pkgName,
|
|
721
|
+
issueType: 'missing_package',
|
|
722
|
+
severity: Severity.LOW,
|
|
723
|
+
description: `Package ${pkgName} is in lock file but not installed`,
|
|
724
|
+
expected: version as string
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
return issues;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* Load lock file data
|
|
734
|
+
*/
|
|
735
|
+
private async loadLockFile(): Promise<{ packages: Record<string, string> } | null> {
|
|
736
|
+
const projectPath = this.config.projectPath;
|
|
737
|
+
const packages: Record<string, string> = {};
|
|
738
|
+
|
|
739
|
+
// Try package-lock.json
|
|
740
|
+
const packageLockPath = path.join(projectPath, 'package-lock.json');
|
|
741
|
+
if (fs.existsSync(packageLockPath)) {
|
|
742
|
+
try {
|
|
743
|
+
const lockFile = JSON.parse(fs.readFileSync(packageLockPath, 'utf-8'));
|
|
744
|
+
|
|
745
|
+
// Handle npm v3 format
|
|
746
|
+
if (lockFile.packages) {
|
|
747
|
+
for (const [key, value] of Object.entries(lockFile.packages)) {
|
|
748
|
+
if (key && key !== '') {
|
|
749
|
+
const name = key.replace(/^node_modules\//, '');
|
|
750
|
+
packages[name] = (value as any).version;
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// Handle npm v1/v2 format
|
|
756
|
+
if (lockFile.dependencies) {
|
|
757
|
+
for (const [name, value] of Object.entries(lockFile.dependencies)) {
|
|
758
|
+
packages[name] = (value as any).version;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
return { packages };
|
|
763
|
+
} catch {
|
|
764
|
+
logger.debug('Error parsing package-lock.json');
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// Try yarn.lock (simplified parsing)
|
|
769
|
+
const yarnLockPath = path.join(projectPath, 'yarn.lock');
|
|
770
|
+
if (fs.existsSync(yarnLockPath)) {
|
|
771
|
+
try {
|
|
772
|
+
const content = fs.readFileSync(yarnLockPath, 'utf-8');
|
|
773
|
+
const lines = content.split('\n');
|
|
774
|
+
let currentPackage = '';
|
|
775
|
+
|
|
776
|
+
for (const line of lines) {
|
|
777
|
+
const pkgMatch = line.match(/^"?(@?[^@\s]+)@/);
|
|
778
|
+
if (pkgMatch) {
|
|
779
|
+
currentPackage = pkgMatch[1];
|
|
780
|
+
}
|
|
781
|
+
const versionMatch = line.match(/^\s+version:?\s+"?([^"\s]+)"?/);
|
|
782
|
+
if (versionMatch && currentPackage) {
|
|
783
|
+
packages[currentPackage] = versionMatch[1];
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
return { packages };
|
|
788
|
+
} catch {
|
|
789
|
+
logger.debug('Error parsing yarn.lock');
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
return null;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
/**
|
|
797
|
+
* Initialize statistics
|
|
798
|
+
*/
|
|
799
|
+
private initializeStats(): InstalledScanStats {
|
|
800
|
+
return {
|
|
801
|
+
totalFoldersScanned: 0,
|
|
802
|
+
totalPackagesFound: 0,
|
|
803
|
+
totalFilesScanned: 0,
|
|
804
|
+
totalBytesScanned: 0,
|
|
805
|
+
malwareFindingsCount: 0,
|
|
806
|
+
integrityIssuesCount: 0,
|
|
807
|
+
suspiciousScriptsCount: 0,
|
|
808
|
+
packagesByEcosystem: {} as Record<PackageEcosystem, number>,
|
|
809
|
+
findingsBySeverity: {} as Record<Severity, number>,
|
|
810
|
+
duration: 0
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* Quick scan function
|
|
817
|
+
*/
|
|
818
|
+
export async function scanInstalledDependencies(projectPath: string): Promise<InstalledDependenciesScanResult> {
|
|
819
|
+
const scanner = new InstalledDependenciesScanner({ projectPath });
|
|
820
|
+
return scanner.scan();
|
|
821
|
+
}
|