generated from nhcarrigan/template
feat: add npm audit script, crowdin helpers now write data to disk
Node.js CI / Lint and Test (push) Failing after 34s
Node.js CI / Lint and Test (push) Failing after 34s
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* @copyright NHCarrigan
|
||||
* @license Naomi's Public License
|
||||
* @author Naomi Carrigan
|
||||
*/
|
||||
|
||||
import { writeFile, appendFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { Octokit } from "@octokit/rest";
|
||||
import { serialiseJsonOrError } from "../utils/serialiseJsonOrError.js";
|
||||
|
||||
if (process.env.GITHUB_TOKEN === undefined) {
|
||||
throw new Error("Missing Github Token - did you run this with `op`?");
|
||||
}
|
||||
|
||||
const resultPath = join(
|
||||
import.meta.dirname,
|
||||
"..",
|
||||
"..",
|
||||
"data",
|
||||
"npm-vulnerabilities.txt",
|
||||
);
|
||||
|
||||
const orgsToCheck = [
|
||||
"deepgram",
|
||||
"deepgram-devs",
|
||||
"deepgram-starters",
|
||||
];
|
||||
|
||||
const vulnerablePackages: Array<{ name: string; version: string }> = [
|
||||
{ name: "ansi-regex", version: "6.2.1" },
|
||||
{ name: "ansi-styles", version: "6.2.2" },
|
||||
{ name: "backslash", version: "0.2.1" },
|
||||
{ name: "chalk-template", version: "1.1.1" },
|
||||
{ name: "chalk", version: "5.6.1" },
|
||||
{ name: "color-convert", version: "3.1.1" },
|
||||
{ name: "color-name", version: "2.0.1" },
|
||||
{ name: "color-string", version: "2.1.1" },
|
||||
{ name: "color", version: "5.0.1" },
|
||||
{ name: "debug", version: "4.4.2" },
|
||||
{ name: "has-ansi", version: "6.0.1" },
|
||||
{ name: "is-arrayish", version: "0.3.3" },
|
||||
{ name: "simple-swizzle", version: "0.2.3" },
|
||||
{ name: "slice-ansi", version: "7.1.1" },
|
||||
{ name: "strip-ansi", version: "7.1.1" },
|
||||
{ name: "supports-color", version: "10.2.1" },
|
||||
{ name: "supports-hyperlinks", version: "4.1.1" },
|
||||
{ name: "wrap-ansi", version: "9.0.1" },
|
||||
];
|
||||
|
||||
const gh = new Octokit({
|
||||
auth: process.env.GITHUB_TOKEN,
|
||||
});
|
||||
|
||||
const repositories: Array<{ name: string; owner: string }>
|
||||
= [];
|
||||
|
||||
await writeFile(resultPath, "", "utf-8");
|
||||
|
||||
for (const org of orgsToCheck) {
|
||||
let page = 1;
|
||||
console.log(`Fetching ${org} repositories page ${page.toString()}`);
|
||||
let repos = await gh.repos.listForOrg(
|
||||
{
|
||||
org: org,
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- SDK signature.
|
||||
per_page: 100,
|
||||
},
|
||||
);
|
||||
repositories.push(...repos.data.map((repo) => {
|
||||
return { name: repo.name, owner: org };
|
||||
}));
|
||||
while (repos.data.length >= 100) {
|
||||
page = page + 1;
|
||||
console.log(`Fetching ${org} repositories page ${page.toString()}`);
|
||||
repos = await gh.repos.listForOrg({
|
||||
org: org,
|
||||
page: page,
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- SDK signature.
|
||||
per_page: 100,
|
||||
});
|
||||
repositories.push(...repos.data.map((repo) => {
|
||||
return { name: repo.name, owner: org };
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Found ${repositories.length.toString()} repositories in ${orgsToCheck.length.toString()} orgs.`);
|
||||
|
||||
for (const repo of repositories) {
|
||||
const fileRequest = await gh.repos.getContent({
|
||||
owner: repo.owner,
|
||||
path: "package.json",
|
||||
repo: repo.name,
|
||||
}).catch(() => {
|
||||
return null;
|
||||
});
|
||||
if (!fileRequest) {
|
||||
console.log(`Package.json not found in ${repo.owner}/${repo.name}`);
|
||||
continue;
|
||||
}
|
||||
const file = fileRequest.data;
|
||||
if (!("type" in file) || file.type !== "file") {
|
||||
console.log(`Package.json found but is not file.`);
|
||||
continue;
|
||||
}
|
||||
const { content } = file;
|
||||
const parsed = Buffer.from(content, "base64").toString();
|
||||
const serialised: {
|
||||
dependencies?: Record<string, string>;
|
||||
devDependencies?: Record<string, string>;
|
||||
} | null = serialiseJsonOrError(parsed);
|
||||
if (!serialised) {
|
||||
console.log(`Failed to serialise ${parsed}`);
|
||||
continue;
|
||||
}
|
||||
const deps: Record<string, string> = {};
|
||||
if (serialised.dependencies) {
|
||||
Object.assign(deps, serialised.dependencies);
|
||||
}
|
||||
if (serialised.devDependencies) {
|
||||
Object.assign(deps, serialised.devDependencies);
|
||||
}
|
||||
|
||||
console.log(`Auditing packages in ${repo.owner}/${repo.name}...`);
|
||||
|
||||
for (const dep of vulnerablePackages) {
|
||||
if (!(dep.name in deps)) {
|
||||
continue;
|
||||
}
|
||||
if (dep.version !== deps[dep.name]) {
|
||||
console.log(
|
||||
`Found ${dep.name}: ${dep.version} but it was not the vulnerable ${String(deps[dep.name])} version.`,
|
||||
);
|
||||
await appendFile(
|
||||
resultPath,
|
||||
`${repo.owner}/${repo.name}: Found ${dep.name} but ${String(deps[dep.name])} is not the vulnerable ${dep.version} version.\n`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
console.log(
|
||||
`FOUND VULNERABLE ${dep.name}: ${dep.version} IN ${repo.owner}/${repo.name}!!!!`,
|
||||
);
|
||||
await appendFile(
|
||||
resultPath,
|
||||
`!! FOUND VULNERALBE ${dep.name}: ${dep.version} IN ${repo.owner}/${repo.name} !!\n`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("All done!");
|
||||
Reference in New Issue
Block a user