@nodesecure/scanner
Version:
A package API to run a static analysis of your module's dependencies.
82 lines • 3.02 kB
JavaScript
// Import Node.js Dependencies
import path from "node:path";
// Import Third-party Dependencies
import * as i18n from "@nodesecure/i18n";
import * as RC from "@nodesecure/rc";
import { ContactExtractor } from "@nodesecure/contact";
// Import Internal Dependencies
import { getDirNameFromUrl } from "./dirname.js";
import { TopPackages } from "../class/TopPackages.class.js";
await i18n.extendFromSystemPath(path.join(getDirNameFromUrl(import.meta.url), "..", "i18n"));
// CONSTANTS
const kDetectedDep = i18n.taggedString `The dependency '${0}' has been detected in the dependency Tree.`;
const kDefaultIlluminatedContacts = [
{
name: "marak",
email: "marak.squires@gmail.com"
}
];
const kDependencyWarnMessage = {
"@scarf/scarf": await i18n.getToken("scanner.disable_scarf"),
iohook: await i18n.getToken("scanner.keylogging")
};
export async function getDependenciesWarnings(dependenciesMap, highlightContacts = [], isLocalScan = false) {
const vulnerableDependencyNames = Object.keys(kDependencyWarnMessage);
const topPackages = new TopPackages();
await topPackages.loadJSON();
const warnings = vulnerableDependencyNames
.flatMap((name) => {
if (!dependenciesMap.has(name)) {
return [];
}
return {
type: "dangerous-dependency",
message: `${kDetectedDep(name)} ${kDependencyWarnMessage[name]}`
};
});
const dependencies = Object.create(null);
for (const [packageName, dependency] of dependenciesMap) {
const { author, maintainers } = dependency.metadata;
const warning = await (isLocalScan ?
Promise.resolve(null) :
searchTypoSquattingByName(topPackages, packageName));
if (warning !== null) {
warnings.push(warning);
}
dependencies[packageName] = {
maintainers,
...(author === null ? {} : { author })
};
}
const memoizedConfig = RC.memoized();
const extractor = new ContactExtractor({
highlight: [
...highlightContacts,
...(memoizedConfig === null ?
[] : (memoizedConfig.scanner?.highlight?.contacts ?? [])),
...kDefaultIlluminatedContacts
]
});
const { illuminated } = await extractor.fromDependencies(dependencies);
return {
warnings,
illuminated
};
}
async function searchTypoSquattingByName(topPackages, packageName) {
const similarPackages = topPackages.getSimilarPackages(packageName);
if (similarPackages.length > 0 &&
similarPackages.length <= 3) {
const warningMessage = await i18n.getToken("scanner.typo_squatting", packageName, similarPackages.join(", "));
return {
type: "typo-squatting",
message: warningMessage,
metadata: {
name: packageName,
similar: similarPackages
}
};
}
return null;
}
//# sourceMappingURL=warnings.js.map