@kaynooo/pkg-tools 0.5.0 → 0.6.0
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 +3 -2
- package/dist/cli.js +39 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,9 +12,9 @@ pkg left-pad@1.3.0 @types/node --json
|
|
|
12
12
|
|
|
13
13
|
- Whether the name exists, the version the request resolves to (an exact version, a dist-tag or a range), the latest version, and the highest stable version at least two weeks old (`safe`), each with its publish date.
|
|
14
14
|
- Weekly downloads (public registry only), licence and repository.
|
|
15
|
-
- Warnings for a version under the minimum age (with the `safe` version to use instead), `preinstall`, `install` and `postinstall` scripts, a deprecated version, and a name that is a near miss of a popular package (one or two edits, other separators or case, or the same name under another scope).
|
|
15
|
+
- Warnings for a version under the minimum age (with the `safe` version to use instead; a fresh version clear of an advisory at `blockSeverity` or above that `safe` has is let through, with a warning naming the GHSAs it fixes), `preinstall`, `install` and `postinstall` scripts, a deprecated version, and a name that is a near miss of a popular package (one or two edits, other separators or case, or the same name under another scope).
|
|
16
16
|
|
|
17
|
-
`pkg` exits 1 when a package is blocked (missing, the request matches no version or is not a valid range, the resolved version is too fresh or has no publish date on npmjs.org, its licence is outside the allowlist, or an advisory reaches the threshold), 2 when it could not check (the registry unreachable, slower than 10 s or answering badly, a broken `.pkgrc.json`, `bunfig.toml` or `.npmrc`) or on a usage error; other warnings exit 0. `--json` prints one report, or an array for several names, `--min-age <days>` changes the 14 days.
|
|
17
|
+
`pkg` exits 1 when a package is blocked (missing, the request matches no version or is not a valid range, the resolved version is too fresh (unless it fixes an advisory of the safe version at the threshold) or has no publish date on npmjs.org, its licence is outside the allowlist, or an advisory reaches the threshold), 2 when it could not check (the registry unreachable, slower than 10 s or answering badly, a broken `.pkgrc.json`, `bunfig.toml` or `.npmrc`) or on a usage error; other warnings exit 0. `--json` prints one report, or an array for several names, `--min-age <days>` changes the 14 days.
|
|
18
18
|
|
|
19
19
|
## Config: licence allowlist and advisory threshold
|
|
20
20
|
|
|
@@ -38,6 +38,7 @@ pkg audit ~/Workspace/app --audit-level high --ignore GHSA-238p-pmpm-9mq7 --json
|
|
|
38
38
|
|
|
39
39
|
- `--audit-level <low|moderate|high|critical>` (`low`) keeps only the advisories at that severity or above, and `--ignore <GHSA or id>` (repeatable) skips an advisory; `blockSeverity` is for `pkg check` and does not apply here.
|
|
40
40
|
- `--json` prints the packages with a finding as `[{name, version, license, blocked, warnings, advisories}]`; `--min-age <days>` changes the 14 days.
|
|
41
|
+
- A pin under the minimum age fixing an advisory of the `safe` version at `blockSeverity` or above (not one `--ignore` skips) is let through as `pkg check` lets it, a warning naming the GHSAs.
|
|
41
42
|
- It exits 1 when a package is missing, too fresh or outside the allowlist, or an advisory remains after the level and the ignores; install scripts and near misses alone exit 0. When the advisories of a registry could not be read it warns which, never prints a clean result for them, and exits 2 unless something already blocks.
|
|
42
43
|
- An `npm:` alias (`"lodash": "npm:other@1.0.0"`) is audited as the package it names.
|
|
43
44
|
|
package/dist/cli.js
CHANGED
|
@@ -1143,6 +1143,14 @@ var init_secrets = __esm(() => {
|
|
|
1143
1143
|
SECRET_WORDS = new Set(["key", "pass", "pwd", "auth", "salt", "cookie", "session", "jwt", "ssn", "iban", "card", "cvv", "otp"]);
|
|
1144
1144
|
});
|
|
1145
1145
|
|
|
1146
|
+
// ../kit/src/sessions.ts
|
|
1147
|
+
var {Glob } = globalThis.Bun;
|
|
1148
|
+
var SESSION_FILES, ACCOUNT_DIRS;
|
|
1149
|
+
var init_sessions = __esm(() => {
|
|
1150
|
+
SESSION_FILES = new Glob("*.json");
|
|
1151
|
+
ACCOUNT_DIRS = new Glob("*/sessions");
|
|
1152
|
+
});
|
|
1153
|
+
|
|
1146
1154
|
// ../kit/src/index.ts
|
|
1147
1155
|
var init_src = __esm(() => {
|
|
1148
1156
|
init_args();
|
|
@@ -1156,6 +1164,7 @@ var init_src = __esm(() => {
|
|
|
1156
1164
|
init_logs();
|
|
1157
1165
|
init_process();
|
|
1158
1166
|
init_secrets();
|
|
1167
|
+
init_sessions();
|
|
1159
1168
|
init_style();
|
|
1160
1169
|
init_text();
|
|
1161
1170
|
init_tool();
|
|
@@ -2062,6 +2071,9 @@ function ageDays(published, now) {
|
|
|
2062
2071
|
const at = Date.parse(published ?? "");
|
|
2063
2072
|
return Number.isNaN(at) ? undefined : (now - at) / DAY;
|
|
2064
2073
|
}
|
|
2074
|
+
function daysAgo(age) {
|
|
2075
|
+
return age < 1 ? "less than a day" : `${Math.floor(age)} day${Math.floor(age) === 1 ? "" : "s"}`;
|
|
2076
|
+
}
|
|
2065
2077
|
function installScriptsOf(version) {
|
|
2066
2078
|
return Object.fromEntries(INSTALL_SCRIPTS.flatMap((name) => version?.scripts?.[name] === undefined ? [] : [[name, version.scripts[name]]]));
|
|
2067
2079
|
}
|
|
@@ -2072,7 +2084,7 @@ function safeRelease(packument, now, minAgeDays) {
|
|
|
2072
2084
|
}
|
|
2073
2085
|
function analyze(input) {
|
|
2074
2086
|
const { spec, packument, registry, now = Date.now(), minAgeDays = DEFAULT_MIN_AGE_DAYS } = input;
|
|
2075
|
-
const report = { name: spec.name, registry, exists: packument !== undefined, requested: spec.request, installScripts: {}, nearMisses: nearMisses(spec.name), advisories: input.advisories ?? [], warnings: [], blocked: false, downloads: input.downloads };
|
|
2087
|
+
const report = { name: spec.name, registry, exists: packument !== undefined, requested: spec.request, installScripts: {}, nearMisses: nearMisses(spec.name), advisories: input.advisories ?? [], fixes: [], warnings: [], blocked: false, downloads: input.downloads };
|
|
2076
2088
|
if (report.nearMisses.length > 0)
|
|
2077
2089
|
report.warnings.push(`name looks like ${report.nearMisses.join("; ")}, check it is the package meant`);
|
|
2078
2090
|
if (packument === undefined) {
|
|
@@ -2098,13 +2110,17 @@ function analyze(input) {
|
|
|
2098
2110
|
return report;
|
|
2099
2111
|
}
|
|
2100
2112
|
const age = ageDays(report.published, now);
|
|
2113
|
+
const kept = new Set(report.advisories.map((each) => each.id));
|
|
2114
|
+
report.fixes = report.safe?.version === version ? [] : (input.safeAdvisories ?? []).filter((each) => !kept.has(each.id));
|
|
2101
2115
|
if (age === undefined) {
|
|
2102
2116
|
const isBlocking = minAgeDays > 0 && registry === PUBLIC_HOST;
|
|
2103
2117
|
report.blocked ||= isBlocking;
|
|
2104
2118
|
report.warnings.push(`${registry} gives no publish date for ${version}, its age cannot be checked${isBlocking ? " and it is refused" : ""}`);
|
|
2119
|
+
} else if (age < minAgeDays && report.fixes.length > 0) {
|
|
2120
|
+
report.warnings.push(`${version} was published ${daysAgo(age)} ago, under ${minAgeDays} days, but it fixes ${report.fixes.map((each) => `${each.ghsa ?? each.id} (${each.severity})`).join(", ")} that ${report.safe?.version} has, so its age does not hold it back`);
|
|
2105
2121
|
} else if (age < minAgeDays) {
|
|
2106
2122
|
report.blocked = true;
|
|
2107
|
-
report.warnings.push(`${version} was published ${
|
|
2123
|
+
report.warnings.push(`${version} was published ${daysAgo(age)} ago, under ${minAgeDays} days${report.safe === undefined ? ", and no older stable version exists" : `, use ${spec.name}@${report.safe.version}`}`);
|
|
2108
2124
|
}
|
|
2109
2125
|
const scripts = Object.keys(report.installScripts);
|
|
2110
2126
|
if (scripts.length > 0)
|
|
@@ -2159,10 +2175,11 @@ async function checkPackage(text, context) {
|
|
|
2159
2175
|
const blockSeverity = context.settings?.blockSeverity ?? DEFAULT_BLOCK_SEVERITY;
|
|
2160
2176
|
if (report.version === undefined)
|
|
2161
2177
|
return report;
|
|
2162
|
-
const
|
|
2178
|
+
const safe = report.safe?.version;
|
|
2179
|
+
const { found, unavailable, isUnsupported } = await fetchAdvisories({ [spec.name]: safe === undefined || safe === report.version ? [report.version] : [report.version, safe] }, registry, context.fetcher);
|
|
2163
2180
|
if (unavailable !== undefined && isUnsupported !== true)
|
|
2164
2181
|
return unreachable(unavailable);
|
|
2165
|
-
const checked = analyze({ ...input, blockSeverity, advisories: advisoriesFor(found[spec.name], report.version) });
|
|
2182
|
+
const checked = analyze({ ...input, blockSeverity, advisories: advisoriesFor(found[spec.name], report.version), safeAdvisories: safe === undefined ? [] : filterAdvisories(advisoriesFor(found[spec.name], safe), blockSeverity) });
|
|
2166
2183
|
if (unavailable !== undefined)
|
|
2167
2184
|
checked.warnings.push(`${unavailable}, so its known advisories are not checked`);
|
|
2168
2185
|
return checked;
|
|
@@ -2274,11 +2291,18 @@ async function auditPackages(packages, context) {
|
|
|
2274
2291
|
packuments.set(key, fetchPackument(name, registry, context.fetcher));
|
|
2275
2292
|
return packuments.get(key);
|
|
2276
2293
|
};
|
|
2294
|
+
const looked = [];
|
|
2295
|
+
for (let start = 0;start < packages.length; start += BATCH) {
|
|
2296
|
+
looked.push(...await Promise.all(packages.slice(start, start + BATCH).map(async ({ name, version }) => {
|
|
2297
|
+
const registry = registryFor(name, context.configs);
|
|
2298
|
+
const input = { spec: { name, request: version }, packument: await lookup(name, registry), registry: new URL(registry.url).host, now: context.now, minAgeDays: context.minAgeDays, licenses: context.settings.licenses };
|
|
2299
|
+
return { name, version, registry, input, safe: analyze(input).safe?.version };
|
|
2300
|
+
})));
|
|
2301
|
+
}
|
|
2277
2302
|
const registries = new Map;
|
|
2278
|
-
for (const { name, version } of
|
|
2279
|
-
const registry = registryFor(name, context.configs);
|
|
2303
|
+
for (const { name, version, registry, safe } of looked) {
|
|
2280
2304
|
const group = registries.get(registry.url) ?? { registry, versions: {} };
|
|
2281
|
-
group.versions[name] = [...group.versions[name] ?? [], version];
|
|
2305
|
+
group.versions[name] = [...group.versions[name] ?? [], version, ...safe === undefined || safe === version ? [] : [safe]];
|
|
2282
2306
|
registries.set(registry.url, group);
|
|
2283
2307
|
}
|
|
2284
2308
|
const advisories = {};
|
|
@@ -2289,15 +2313,13 @@ async function auditPackages(packages, context) {
|
|
|
2289
2313
|
if (fetched.unavailable !== undefined)
|
|
2290
2314
|
unavailable.push(fetched.unavailable);
|
|
2291
2315
|
}
|
|
2292
|
-
const
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
})));
|
|
2300
|
-
}
|
|
2316
|
+
const blockSeverity = context.settings.blockSeverity ?? DEFAULT_BLOCK_SEVERITY;
|
|
2317
|
+
const audited = looked.map(({ name, version, input, safe }) => {
|
|
2318
|
+
const found = filterAdvisories(advisoriesFor(advisories[name], version), context.level, context.ignore);
|
|
2319
|
+
const safeAdvisories = safe === undefined ? [] : filterAdvisories(advisoriesFor(advisories[name], safe), blockSeverity, context.ignore);
|
|
2320
|
+
const report = analyze({ ...input, advisories: advisoriesFor(advisories[name], version), safeAdvisories });
|
|
2321
|
+
return { name, version, license: report.license, blocked: report.blocked || found.length > 0, warnings: report.warnings, advisories: found };
|
|
2322
|
+
});
|
|
2301
2323
|
return { audited, unavailable };
|
|
2302
2324
|
}
|
|
2303
2325
|
function renderAudit(findings, total) {
|
|
@@ -2727,7 +2749,7 @@ var init_consumers2 = __esm(() => {
|
|
|
2727
2749
|
init_src();
|
|
2728
2750
|
import process10 from "process";
|
|
2729
2751
|
// package.json
|
|
2730
|
-
var version = "0.
|
|
2752
|
+
var version = "0.6.0";
|
|
2731
2753
|
|
|
2732
2754
|
// src/cli.ts
|
|
2733
2755
|
process10.exitCode = await runCli({
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaynooo/pkg-tools",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.6.0",
|
|
5
5
|
"description": "pkg: check an npm package before it is added, for a guessed name, a version under two weeks old and install scripts.",
|
|
6
6
|
"author": "Kaynooo <contact@kaynooo.fr>",
|
|
7
7
|
"license": "MIT",
|