mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 12:10:49 +00:00
Some cleanup
This commit is contained in:
parent
2df8ce463c
commit
8a4f759a78
2 changed files with 67 additions and 28 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import { getMinimumPackageAgeHours, getNpmMinimumPackageAgeExclusions } from "../../../config/settings.js";
|
import { getMinimumPackageAgeHours } from "../../../config/settings.js";
|
||||||
import { ui } from "../../../environment/userInteraction.js";
|
import { ui } from "../../../environment/userInteraction.js";
|
||||||
import { getHeaderValueAsString } from "../../http-utils.js";
|
import { getHeaderValueAsString } from "../../http-utils.js";
|
||||||
|
|
||||||
|
|
@ -65,16 +65,6 @@ export function modifyNpmInfoResponse(body, headers) {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this package is excluded from minimum age filtering
|
|
||||||
const packageName = bodyJson.name;
|
|
||||||
const exclusions = getNpmMinimumPackageAgeExclusions();
|
|
||||||
if (packageName && exclusions.some((pattern) => matchesExclusionPattern(packageName, pattern))) {
|
|
||||||
ui.writeVerbose(
|
|
||||||
`Safe-chain: ${packageName} is excluded from minimum package age filtering (minimumPackageAgeExclusions setting).`
|
|
||||||
);
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cutOff = new Date(
|
const cutOff = new Date(
|
||||||
new Date().getTime() - getMinimumPackageAgeHours() * 3600 * 1000
|
new Date().getTime() - getMinimumPackageAgeHours() * 3600 * 1000
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -46,37 +46,86 @@ function buildNpmInterceptor(registry) {
|
||||||
reqContext.targetUrl,
|
reqContext.targetUrl,
|
||||||
registry
|
registry
|
||||||
);
|
);
|
||||||
|
const minimumAgeChecksEnabled = !skipMinimumPackageAge();
|
||||||
|
const packageIsExcludedFromMinimumAgeChecks =
|
||||||
|
packageName && isExcludedFromMinimumPackageAge(packageName);
|
||||||
|
|
||||||
if (await isMalwarePackage(packageName, version)) {
|
if (await isMalwarePackage(packageName, version)) {
|
||||||
reqContext.blockMalware(packageName, version);
|
reqContext.blockMalware(packageName, version);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!skipMinimumPackageAge() && isPackageInfoUrl(reqContext.targetUrl)) {
|
if (minimumAgeChecksEnabled && isPackageInfoUrl(reqContext.targetUrl)) {
|
||||||
reqContext.modifyRequestHeaders(modifyNpmInfoRequestHeaders);
|
reqContext.modifyRequestHeaders(modifyNpmInfoRequestHeaders);
|
||||||
reqContext.modifyBody(modifyNpmInfoResponse);
|
reqContext.modifyBody((body, headers) => {
|
||||||
|
const metadataPackageName = getPackageNameFromMetadataResponse(
|
||||||
|
body,
|
||||||
|
headers
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
metadataPackageName &&
|
||||||
|
isExcludedFromMinimumPackageAge(metadataPackageName)
|
||||||
|
) {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
return modifyNpmInfoResponse(body, headers);
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For tarball requests the metadata check above is skipped, so we check the
|
// For tarball requests the metadata check above is skipped, so we check the
|
||||||
// new packages list as a fallback (covers e.g. frozen-lockfile installs).
|
// new packages list as a fallback (covers e.g. frozen-lockfile installs).
|
||||||
if (!skipMinimumPackageAge() && packageName && version) {
|
if (
|
||||||
const exclusions = getNpmMinimumPackageAgeExclusions();
|
minimumAgeChecksEnabled &&
|
||||||
const isExcluded = exclusions.some((pattern) =>
|
packageName &&
|
||||||
matchesExclusionPattern(packageName, pattern)
|
version &&
|
||||||
);
|
!packageIsExcludedFromMinimumAgeChecks
|
||||||
|
) {
|
||||||
|
const newPackagesDatabase = await openNewPackagesDatabase();
|
||||||
|
|
||||||
if (!isExcluded) {
|
if (newPackagesDatabase.isNewlyReleasedPackage(packageName, version)) {
|
||||||
const newPackagesDatabase = await openNewPackagesDatabase();
|
reqContext.blockMinimumAgeRequest(
|
||||||
|
packageName,
|
||||||
if (newPackagesDatabase.isNewlyReleasedPackage(packageName, version)) {
|
version,
|
||||||
reqContext.blockMinimumAgeRequest(
|
`Forbidden - blocked by safe-chain direct download minimum package age (${packageName}@${version})`
|
||||||
packageName,
|
);
|
||||||
version,
|
|
||||||
`Forbidden - blocked by safe-chain direct download minimum package age (${packageName}@${version})`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} packageName
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
function isExcludedFromMinimumPackageAge(packageName) {
|
||||||
|
const exclusions = getNpmMinimumPackageAgeExclusions();
|
||||||
|
return exclusions.some((pattern) =>
|
||||||
|
matchesExclusionPattern(packageName, pattern)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Buffer} body
|
||||||
|
* @param {NodeJS.Dict<string | string[]> | undefined} headers
|
||||||
|
* @returns {string | undefined}
|
||||||
|
*/
|
||||||
|
function getPackageNameFromMetadataResponse(body, headers) {
|
||||||
|
try {
|
||||||
|
const contentType = headers?.["content-type"];
|
||||||
|
const normalizedContentType = Array.isArray(contentType)
|
||||||
|
? contentType.join(",")
|
||||||
|
: contentType;
|
||||||
|
|
||||||
|
if (!normalizedContentType?.toLowerCase().includes("application/json")) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bodyJson = JSON.parse(body.toString("utf8"));
|
||||||
|
return typeof bodyJson.name === "string" ? bodyJson.name : undefined;
|
||||||
|
} catch {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue