@westbayberry/dg 1.1.5 → 1.2.1
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/dist/index.mjs +983 -618
- package/dist/postinstall.mjs +38 -13
- package/dist/python-hook/dg_pip_hook.py +15 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -910,15 +910,15 @@ var require_route = __commonJS({
|
|
|
910
910
|
};
|
|
911
911
|
}
|
|
912
912
|
function wrapConversion(toModel, graph) {
|
|
913
|
-
const
|
|
913
|
+
const path = [graph[toModel].parent, toModel];
|
|
914
914
|
let fn = conversions[graph[toModel].parent][toModel];
|
|
915
915
|
let cur = graph[toModel].parent;
|
|
916
916
|
while (graph[cur].parent) {
|
|
917
|
-
|
|
917
|
+
path.unshift(graph[cur].parent);
|
|
918
918
|
fn = link2(conversions[graph[cur].parent][cur], fn);
|
|
919
919
|
cur = graph[cur].parent;
|
|
920
920
|
}
|
|
921
|
-
fn.conversion =
|
|
921
|
+
fn.conversion = path;
|
|
922
922
|
return fn;
|
|
923
923
|
}
|
|
924
924
|
module.exports = function(fromModel) {
|
|
@@ -1590,8 +1590,8 @@ var require_source = __commonJS({
|
|
|
1590
1590
|
// src/telemetry.ts
|
|
1591
1591
|
import { platform, arch } from "node:os";
|
|
1592
1592
|
function telemetryEnabled() {
|
|
1593
|
-
if (process.env.DG_TELEMETRY === "0") return false;
|
|
1594
1593
|
if (process.env.DO_NOT_TRACK === "1") return false;
|
|
1594
|
+
if (process.env.DG_TELEMETRY === "0") return false;
|
|
1595
1595
|
return true;
|
|
1596
1596
|
}
|
|
1597
1597
|
function classifyError(err) {
|
|
@@ -1894,6 +1894,7 @@ __export(auth_exports, {
|
|
|
1894
1894
|
pollAuthSession: () => pollAuthSession,
|
|
1895
1895
|
preflightAuthCheck: () => preflightAuthCheck,
|
|
1896
1896
|
readTermsAcceptedAt: () => readTermsAcceptedAt,
|
|
1897
|
+
recordScanCapReached: () => recordScanCapReached,
|
|
1897
1898
|
recordScanNoticeShown: () => recordScanNoticeShown,
|
|
1898
1899
|
saveCredentials: () => saveCredentials,
|
|
1899
1900
|
saveCredentialsFromToken: () => saveCredentialsFromToken,
|
|
@@ -2004,17 +2005,17 @@ function ensureConfigDir() {
|
|
|
2004
2005
|
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
2005
2006
|
}
|
|
2006
2007
|
}
|
|
2007
|
-
function ensureConfigPerms(
|
|
2008
|
+
function ensureConfigPerms(path) {
|
|
2008
2009
|
let st;
|
|
2009
2010
|
try {
|
|
2010
|
-
st = lstatSync(
|
|
2011
|
+
st = lstatSync(path);
|
|
2011
2012
|
} catch {
|
|
2012
2013
|
return;
|
|
2013
2014
|
}
|
|
2014
2015
|
if (!st || typeof st.isSymbolicLink !== "function") return;
|
|
2015
2016
|
if (st.isSymbolicLink()) {
|
|
2016
2017
|
process.stderr.write(
|
|
2017
|
-
`Warning: ${
|
|
2018
|
+
`Warning: ${path} is a symlink; refusing to chmod (would affect the symlink target). Replace with a regular file to enforce 0o600.
|
|
2018
2019
|
`
|
|
2019
2020
|
);
|
|
2020
2021
|
return;
|
|
@@ -2023,12 +2024,12 @@ function ensureConfigPerms(path2) {
|
|
|
2023
2024
|
const mode = (st.mode ?? 384) & 511;
|
|
2024
2025
|
if (mode === 384) return;
|
|
2025
2026
|
process.stderr.write(
|
|
2026
|
-
`Warning: ${
|
|
2027
|
+
`Warning: ${path} has perms 0o${mode.toString(8)} (expected 0o600); re-tightening.
|
|
2027
2028
|
`
|
|
2028
2029
|
);
|
|
2029
2030
|
let fd;
|
|
2030
2031
|
try {
|
|
2031
|
-
fd = openSync(
|
|
2032
|
+
fd = openSync(path, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW);
|
|
2032
2033
|
fchmodSync(fd, 384);
|
|
2033
2034
|
} catch {
|
|
2034
2035
|
} finally {
|
|
@@ -2185,11 +2186,11 @@ async function fetchCliPolicy(opts) {
|
|
|
2185
2186
|
return null;
|
|
2186
2187
|
}
|
|
2187
2188
|
}
|
|
2188
|
-
async function postCliEvent(
|
|
2189
|
+
async function postCliEvent(path, body, apiUrl, apiKey, timeoutMs = 3e3) {
|
|
2189
2190
|
try {
|
|
2190
2191
|
const ctrl = new AbortController();
|
|
2191
2192
|
const timer = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
2192
|
-
await globalThis.fetch(`${apiUrl}${
|
|
2193
|
+
await globalThis.fetch(`${apiUrl}${path}`, {
|
|
2193
2194
|
method: "POST",
|
|
2194
2195
|
headers: {
|
|
2195
2196
|
"Content-Type": "application/json",
|
|
@@ -2263,9 +2264,9 @@ function authStatusCachePath() {
|
|
|
2263
2264
|
}
|
|
2264
2265
|
function readCachedAuthStatus() {
|
|
2265
2266
|
try {
|
|
2266
|
-
const
|
|
2267
|
-
if (!existsSync(
|
|
2268
|
-
const raw = readFileSync(
|
|
2267
|
+
const path = authStatusCachePath();
|
|
2268
|
+
if (!existsSync(path)) return null;
|
|
2269
|
+
const raw = readFileSync(path, "utf-8");
|
|
2269
2270
|
const cached = JSON.parse(raw);
|
|
2270
2271
|
if (typeof cached.fetchedAt !== "number") return null;
|
|
2271
2272
|
if (Date.now() - cached.fetchedAt > AUTH_STATUS_TTL_MS) return null;
|
|
@@ -2276,25 +2277,35 @@ function readCachedAuthStatus() {
|
|
|
2276
2277
|
}
|
|
2277
2278
|
function writeCachedAuthStatus(status) {
|
|
2278
2279
|
try {
|
|
2279
|
-
const
|
|
2280
|
-
const dir = dirname(
|
|
2280
|
+
const path = authStatusCachePath();
|
|
2281
|
+
const dir = dirname(path);
|
|
2281
2282
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true, mode: 448 });
|
|
2282
|
-
writeFileSync(
|
|
2283
|
+
writeFileSync(path, JSON.stringify(status), { mode: 384 });
|
|
2283
2284
|
} catch {
|
|
2284
2285
|
}
|
|
2285
2286
|
}
|
|
2287
|
+
function recordScanCapReached(scansUsed, maxScans, reason) {
|
|
2288
|
+
writeCachedAuthStatus({
|
|
2289
|
+
authenticated: !!getStoredApiKey(),
|
|
2290
|
+
freeTierCapReached: true,
|
|
2291
|
+
scansUsed,
|
|
2292
|
+
scansLimit: maxScans,
|
|
2293
|
+
capReason: reason,
|
|
2294
|
+
fetchedAt: Date.now()
|
|
2295
|
+
});
|
|
2296
|
+
}
|
|
2286
2297
|
async function preflightAuthCheck(apiUrl) {
|
|
2287
2298
|
if (process.env.DG_SIMULATE_FREE_CAP_REACHED === "1") {
|
|
2288
2299
|
throw new PreflightFreeCapReachedError(5, 5);
|
|
2289
2300
|
}
|
|
2301
|
+
const apiKey = getStoredApiKey();
|
|
2290
2302
|
const cached = readCachedAuthStatus();
|
|
2291
|
-
if (cached) {
|
|
2303
|
+
if (cached && cached.authenticated === !!apiKey) {
|
|
2292
2304
|
if (cached.freeTierCapReached) {
|
|
2293
2305
|
throw new PreflightFreeCapReachedError(cached.scansUsed, cached.scansLimit ?? cached.scansUsed, cached.capReason ?? "monthly_limit");
|
|
2294
2306
|
}
|
|
2295
2307
|
return cached;
|
|
2296
2308
|
}
|
|
2297
|
-
const apiKey = getStoredApiKey();
|
|
2298
2309
|
const headers = {};
|
|
2299
2310
|
if (apiKey) {
|
|
2300
2311
|
headers["Authorization"] = `Bearer ${apiKey}`;
|
|
@@ -2324,17 +2335,17 @@ async function preflightAuthCheck(apiUrl) {
|
|
|
2324
2335
|
} catch {
|
|
2325
2336
|
}
|
|
2326
2337
|
if (body.freeTierCapReached) {
|
|
2327
|
-
const
|
|
2338
|
+
const capReason2 = body.capReason === "prefix_cap" ? "prefix_cap" : "monthly_limit";
|
|
2328
2339
|
const status2 = {
|
|
2329
2340
|
authenticated: !!apiKey,
|
|
2330
2341
|
freeTierCapReached: true,
|
|
2331
2342
|
scansUsed: body.scansUsed ?? 0,
|
|
2332
2343
|
scansLimit: body.maxScans ?? 0,
|
|
2333
|
-
capReason,
|
|
2344
|
+
capReason: capReason2,
|
|
2334
2345
|
fetchedAt: Date.now()
|
|
2335
2346
|
};
|
|
2336
2347
|
writeCachedAuthStatus(status2);
|
|
2337
|
-
throw new PreflightFreeCapReachedError(status2.scansUsed, status2.scansLimit ?? 0,
|
|
2348
|
+
throw new PreflightFreeCapReachedError(status2.scansUsed, status2.scansLimit ?? 0, capReason2);
|
|
2338
2349
|
}
|
|
2339
2350
|
}
|
|
2340
2351
|
if (!resp.ok) {
|
|
@@ -2352,25 +2363,27 @@ async function preflightAuthCheck(apiUrl) {
|
|
|
2352
2363
|
data = await resp.json();
|
|
2353
2364
|
} catch {
|
|
2354
2365
|
}
|
|
2366
|
+
const capReason = data.capReason === "prefix_cap" ? "prefix_cap" : "monthly_limit";
|
|
2355
2367
|
const status = {
|
|
2356
2368
|
authenticated: !!apiKey,
|
|
2357
2369
|
freeTierCapReached: !!data.freeTierCapReached,
|
|
2358
2370
|
scansUsed: data.scansUsed ?? 0,
|
|
2359
2371
|
scansLimit: data.scansLimit ?? null,
|
|
2372
|
+
capReason,
|
|
2360
2373
|
tier: data.tier,
|
|
2361
2374
|
name: data.name,
|
|
2362
2375
|
fetchedAt: Date.now()
|
|
2363
2376
|
};
|
|
2364
2377
|
writeCachedAuthStatus(status);
|
|
2365
2378
|
if (status.freeTierCapReached) {
|
|
2366
|
-
throw new PreflightFreeCapReachedError(status.scansUsed, status.scansLimit ?? 0);
|
|
2379
|
+
throw new PreflightFreeCapReachedError(status.scansUsed, status.scansLimit ?? 0, capReason);
|
|
2367
2380
|
}
|
|
2368
2381
|
return status;
|
|
2369
2382
|
}
|
|
2370
2383
|
function clearAuthStatusCache() {
|
|
2371
2384
|
try {
|
|
2372
|
-
const
|
|
2373
|
-
if (existsSync(
|
|
2385
|
+
const path = authStatusCachePath();
|
|
2386
|
+
if (existsSync(path)) unlinkSync(path);
|
|
2374
2387
|
} catch {
|
|
2375
2388
|
}
|
|
2376
2389
|
}
|
|
@@ -2816,7 +2829,7 @@ var init_config = __esm({
|
|
|
2816
2829
|
DG_DEBUG=1 Enable debug output
|
|
2817
2830
|
DG_QUIET=1 Same as passing --quiet
|
|
2818
2831
|
DG_WORKSPACE Workspace subdirectory to scan
|
|
2819
|
-
DG_TELEMETRY=
|
|
2832
|
+
DG_TELEMETRY=0 Opt out of anonymous crash reports (on by default; DO_NOT_TRACK=1 also opts out)
|
|
2820
2833
|
DG_FORCE_POSTINSTALL=1 Force postinstall to run even outside a TTY
|
|
2821
2834
|
(useful for re-running setup manually)
|
|
2822
2835
|
DG_NO_RC_EDIT=1 Postinstall installs shims but does not edit
|
|
@@ -2865,23 +2878,23 @@ function cacheFile() {
|
|
|
2865
2878
|
return dgCachePath("update-check.json");
|
|
2866
2879
|
}
|
|
2867
2880
|
function readCache() {
|
|
2868
|
-
const
|
|
2881
|
+
const path = cacheFile();
|
|
2869
2882
|
let stat = null;
|
|
2870
2883
|
try {
|
|
2871
|
-
stat = lstatSync2(
|
|
2884
|
+
stat = lstatSync2(path, { throwIfNoEntry: false }) ?? null;
|
|
2872
2885
|
} catch {
|
|
2873
2886
|
return null;
|
|
2874
2887
|
}
|
|
2875
2888
|
if (!stat) return null;
|
|
2876
2889
|
if (!stat.isFile() || stat.size > MAX_CACHE_BYTES) {
|
|
2877
2890
|
try {
|
|
2878
|
-
unlinkSync2(
|
|
2891
|
+
unlinkSync2(path);
|
|
2879
2892
|
} catch {
|
|
2880
2893
|
}
|
|
2881
2894
|
return null;
|
|
2882
2895
|
}
|
|
2883
2896
|
try {
|
|
2884
|
-
const raw = readFileSync3(
|
|
2897
|
+
const raw = readFileSync3(path, "utf-8");
|
|
2885
2898
|
const data = JSON.parse(raw);
|
|
2886
2899
|
if (typeof data.latest === "string" && typeof data.checkedAt === "number") {
|
|
2887
2900
|
return data;
|
|
@@ -2892,14 +2905,14 @@ function readCache() {
|
|
|
2892
2905
|
}
|
|
2893
2906
|
function writeCache(entry) {
|
|
2894
2907
|
try {
|
|
2895
|
-
const
|
|
2896
|
-
const parent = dirname3(
|
|
2908
|
+
const path = cacheFile();
|
|
2909
|
+
const parent = dirname3(path);
|
|
2897
2910
|
if (!existsSync3(parent)) mkdirSync2(parent, { recursive: true, mode: 448 });
|
|
2898
2911
|
const serialized = JSON.stringify(entry);
|
|
2899
2912
|
if (serialized.length > MAX_CACHE_BYTES) return;
|
|
2900
|
-
writeFileSync2(
|
|
2913
|
+
writeFileSync2(path, serialized, { encoding: "utf-8", mode: 384 });
|
|
2901
2914
|
try {
|
|
2902
|
-
chmodSync2(
|
|
2915
|
+
chmodSync2(path, 384);
|
|
2903
2916
|
} catch {
|
|
2904
2917
|
}
|
|
2905
2918
|
} catch {
|
|
@@ -3050,17 +3063,17 @@ function ensureUnderHome(target) {
|
|
|
3050
3063
|
throw new UnsafePathError(`refusing to operate on path outside $HOME: ${target}`, target);
|
|
3051
3064
|
}
|
|
3052
3065
|
}
|
|
3053
|
-
function lstatNoSymlink(
|
|
3066
|
+
function lstatNoSymlink(path) {
|
|
3054
3067
|
let st;
|
|
3055
3068
|
try {
|
|
3056
|
-
st = lstatSync3(
|
|
3069
|
+
st = lstatSync3(path);
|
|
3057
3070
|
} catch (e) {
|
|
3058
3071
|
const code = e.code;
|
|
3059
3072
|
if (code === "ENOENT") return;
|
|
3060
3073
|
throw e;
|
|
3061
3074
|
}
|
|
3062
3075
|
if (st.isSymbolicLink()) {
|
|
3063
|
-
throw new UnsafePathError(`refusing: ${
|
|
3076
|
+
throw new UnsafePathError(`refusing: ${path} is a symlink`, path);
|
|
3064
3077
|
}
|
|
3065
3078
|
}
|
|
3066
3079
|
function safeMkdirRecursive(target, mode = 493) {
|
|
@@ -3090,9 +3103,9 @@ function atomicWriteFile(target, content, mode = 420) {
|
|
|
3090
3103
|
writeFileSync3(tmp, content, { mode });
|
|
3091
3104
|
renameSync(tmp, target);
|
|
3092
3105
|
}
|
|
3093
|
-
function isExecutable(
|
|
3106
|
+
function isExecutable(path) {
|
|
3094
3107
|
try {
|
|
3095
|
-
const st = statSync(
|
|
3108
|
+
const st = statSync(path);
|
|
3096
3109
|
return st.isFile() && (st.mode & 73) !== 0;
|
|
3097
3110
|
} catch {
|
|
3098
3111
|
return false;
|
|
@@ -3117,9 +3130,9 @@ var init_safe_fs = __esm({
|
|
|
3117
3130
|
"src/shims/safe-fs.ts"() {
|
|
3118
3131
|
"use strict";
|
|
3119
3132
|
UnsafePathError = class extends Error {
|
|
3120
|
-
constructor(message,
|
|
3133
|
+
constructor(message, path) {
|
|
3121
3134
|
super(message);
|
|
3122
|
-
this.path =
|
|
3135
|
+
this.path = path;
|
|
3123
3136
|
this.name = "UnsafePathError";
|
|
3124
3137
|
}
|
|
3125
3138
|
};
|
|
@@ -3151,16 +3164,29 @@ var init_templates = __esm({
|
|
|
3151
3164
|
"mamba"
|
|
3152
3165
|
];
|
|
3153
3166
|
UNIX_SHIM_BODY = `#!/bin/sh
|
|
3167
|
+
nonce=$(cat "$HOME/.dg/state/shim-nonce" 2>/dev/null)
|
|
3154
3168
|
if [ -n "\${DG_SHIM_ACTIVE:-}" ]; then
|
|
3155
3169
|
cleaned_path=$(printf '%s' "$PATH" | awk -v RS=':' -v ORS=':' '$0 != ENVIRON["HOME"]"/.dg/shims"' | sed 's/:$//')
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3170
|
+
# Only honor DG_SHIM_ACTIVE as the recursion guard when it equals the
|
|
3171
|
+
# on-disk nonce \u2014 that is the value our own wrapper sets before running the
|
|
3172
|
+
# real installer. A non-matching value was set outside dg (stale or a
|
|
3173
|
+
# bypass attempt) and must NOT skip scanning.
|
|
3174
|
+
if [ -n "$nonce" ] && [ "$DG_SHIM_ACTIVE" = "$nonce" ]; then
|
|
3175
|
+
real_bin=$(PATH="$cleaned_path" command -v __ECOSYSTEM__)
|
|
3176
|
+
if [ -n "$real_bin" ]; then
|
|
3177
|
+
exec "$real_bin" "$@"
|
|
3178
|
+
fi
|
|
3179
|
+
echo "dg: real __ECOSYSTEM__ not found on PATH" >&2
|
|
3180
|
+
exit 127
|
|
3181
|
+
fi
|
|
3182
|
+
if [ -z "$nonce" ]; then
|
|
3183
|
+
echo "dg: shim nonce missing (reinstall dg) \u2014 cannot verify; passing through __ECOSYSTEM__ UNSCANNED." >&2
|
|
3184
|
+
real_bin=$(PATH="$cleaned_path" command -v __ECOSYSTEM__)
|
|
3185
|
+
if [ -n "$real_bin" ]; then exec "$real_bin" "$@"; fi
|
|
3186
|
+
exit 127
|
|
3159
3187
|
fi
|
|
3160
|
-
echo "dg:
|
|
3161
|
-
exit 127
|
|
3188
|
+
echo "dg: ignoring externally-set DG_SHIM_ACTIVE (nonce mismatch); scanning __ECOSYSTEM__." >&2
|
|
3162
3189
|
fi
|
|
3163
|
-
nonce=$(cat "$HOME/.dg/state/shim-nonce" 2>/dev/null)
|
|
3164
3190
|
dg_entry=$(cat "$HOME/.dg/state/dg-entry" 2>/dev/null)
|
|
3165
3191
|
if [ -n "$dg_entry" ] && [ -x "$dg_entry" ]; then
|
|
3166
3192
|
DG_SHIM_ACTIVE="$nonce" DG_SHIM_PARENT_PATH="$PATH" exec "$dg_entry" __wrap __ECOSYSTEM__ "$@"
|
|
@@ -3180,6 +3206,8 @@ exit 127
|
|
|
3180
3206
|
`;
|
|
3181
3207
|
WINDOWS_SHIM_BODY = `@echo off
|
|
3182
3208
|
setlocal enabledelayedexpansion
|
|
3209
|
+
set "DG_SHIM_NONCE="
|
|
3210
|
+
if exist "%USERPROFILE%\\.dg\\state\\shim-nonce" set /p DG_SHIM_NONCE=<"%USERPROFILE%\\.dg\\state\\shim-nonce"
|
|
3183
3211
|
if not "%DG_SHIM_ACTIVE%"=="" (
|
|
3184
3212
|
set "_dg_realpath="
|
|
3185
3213
|
for /f "tokens=*" %%i in ('where __ECOSYSTEM__ 2^>nul') do (
|
|
@@ -3187,15 +3215,25 @@ if not "%DG_SHIM_ACTIVE%"=="" (
|
|
|
3187
3215
|
if not defined _dg_realpath set "_dg_realpath=%%i"
|
|
3188
3216
|
)
|
|
3189
3217
|
)
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3218
|
+
rem Only honor DG_SHIM_ACTIVE as the recursion guard when it equals the nonce.
|
|
3219
|
+
if "%DG_SHIM_ACTIVE%"=="!DG_SHIM_NONCE!" (
|
|
3220
|
+
if defined _dg_realpath (
|
|
3221
|
+
"!_dg_realpath!" %*
|
|
3222
|
+
exit /b !errorlevel!
|
|
3223
|
+
)
|
|
3224
|
+
echo dg: real __ECOSYSTEM__ not found on PATH 1>&2
|
|
3225
|
+
exit /b 127
|
|
3193
3226
|
)
|
|
3194
|
-
|
|
3195
|
-
|
|
3227
|
+
if "!DG_SHIM_NONCE!"=="" (
|
|
3228
|
+
echo dg: shim nonce missing ^(reinstall dg^) -- passing through __ECOSYSTEM__ UNSCANNED. 1>&2
|
|
3229
|
+
if defined _dg_realpath (
|
|
3230
|
+
"!_dg_realpath!" %*
|
|
3231
|
+
exit /b !errorlevel!
|
|
3232
|
+
)
|
|
3233
|
+
exit /b 127
|
|
3234
|
+
)
|
|
3235
|
+
echo dg: ignoring externally-set DG_SHIM_ACTIVE ^(nonce mismatch^); scanning __ECOSYSTEM__. 1>&2
|
|
3196
3236
|
)
|
|
3197
|
-
set "DG_SHIM_NONCE="
|
|
3198
|
-
if exist "%USERPROFILE%\\.dg\\state\\shim-nonce" set /p DG_SHIM_NONCE=<"%USERPROFILE%\\.dg\\state\\shim-nonce"
|
|
3199
3237
|
set "DG_ENTRY="
|
|
3200
3238
|
if exist "%USERPROFILE%\\.dg\\state\\dg-entry" set /p DG_ENTRY=<"%USERPROFILE%\\.dg\\state\\dg-entry"
|
|
3201
3239
|
set "DG_SHIM_ACTIVE=!DG_SHIM_NONCE!"
|
|
@@ -3237,9 +3275,9 @@ exit /b 127
|
|
|
3237
3275
|
import { homedir as homedir3 } from "node:os";
|
|
3238
3276
|
import { join as join3 } from "node:path";
|
|
3239
3277
|
import { existsSync as existsSync5, readFileSync as readFileSync4, lstatSync as lstatSync4, appendFileSync, writeFileSync as writeFileSync4 } from "node:fs";
|
|
3240
|
-
function expandHome(
|
|
3241
|
-
if (
|
|
3242
|
-
return
|
|
3278
|
+
function expandHome(path) {
|
|
3279
|
+
if (path.startsWith("~/")) return join3(homedir3(), path.slice(2));
|
|
3280
|
+
return path;
|
|
3243
3281
|
}
|
|
3244
3282
|
function detectShellKind(envShell) {
|
|
3245
3283
|
const s = (envShell ?? "").toLowerCase();
|
|
@@ -3463,6 +3501,7 @@ var init_resolve = __esm({
|
|
|
3463
3501
|
var install_exports = {};
|
|
3464
3502
|
__export(install_exports, {
|
|
3465
3503
|
bypassLogPath: () => bypassLogPath,
|
|
3504
|
+
childInstallEnv: () => childInstallEnv,
|
|
3466
3505
|
currentDgEntry: () => currentDgEntry,
|
|
3467
3506
|
dgShimDir: () => dgShimDir,
|
|
3468
3507
|
ensureDgEntryRecorded: () => ensureDgEntryRecorded,
|
|
@@ -3509,15 +3548,15 @@ function ensureDgEntryRecorded(targetHome = homedir5()) {
|
|
|
3509
3548
|
try {
|
|
3510
3549
|
const entry = currentDgEntry();
|
|
3511
3550
|
if (!entry) return;
|
|
3512
|
-
const
|
|
3551
|
+
const path = dgEntryStatePath(targetHome);
|
|
3513
3552
|
let existing = null;
|
|
3514
3553
|
try {
|
|
3515
|
-
existing = readFileSync6(
|
|
3554
|
+
existing = readFileSync6(path, "utf-8").trim();
|
|
3516
3555
|
} catch {
|
|
3517
3556
|
}
|
|
3518
3557
|
if (existing === entry) return;
|
|
3519
|
-
safeMkdirRecursive(dirname5(
|
|
3520
|
-
safeWriteFile(
|
|
3558
|
+
safeMkdirRecursive(dirname5(path), 493);
|
|
3559
|
+
safeWriteFile(path, entry + "\n", 420);
|
|
3521
3560
|
} catch {
|
|
3522
3561
|
}
|
|
3523
3562
|
}
|
|
@@ -3529,11 +3568,21 @@ function readNonce() {
|
|
|
3529
3568
|
return null;
|
|
3530
3569
|
}
|
|
3531
3570
|
}
|
|
3532
|
-
function
|
|
3571
|
+
function childInstallEnv() {
|
|
3572
|
+
const env3 = {};
|
|
3573
|
+
for (const [k, v] of Object.entries(process.env)) {
|
|
3574
|
+
if (k.startsWith("DG_")) continue;
|
|
3575
|
+
env3[k] = v;
|
|
3576
|
+
}
|
|
3577
|
+
const nonce = readNonce();
|
|
3578
|
+
if (nonce) env3.DG_SHIM_ACTIVE = nonce;
|
|
3579
|
+
return env3;
|
|
3580
|
+
}
|
|
3581
|
+
function chownIfNeeded(path, uid, gid) {
|
|
3533
3582
|
if (uid === void 0 || gid === void 0) return;
|
|
3534
3583
|
if (process.platform === "win32") return;
|
|
3535
3584
|
try {
|
|
3536
|
-
chownSync(
|
|
3585
|
+
chownSync(path, uid, gid);
|
|
3537
3586
|
} catch {
|
|
3538
3587
|
}
|
|
3539
3588
|
}
|
|
@@ -28803,10 +28852,10 @@ var require_react_reconciler_development = __commonJS({
|
|
|
28803
28852
|
var setErrorHandler = null;
|
|
28804
28853
|
var setSuspenseHandler = null;
|
|
28805
28854
|
{
|
|
28806
|
-
var copyWithDeleteImpl = function(obj,
|
|
28807
|
-
var key =
|
|
28855
|
+
var copyWithDeleteImpl = function(obj, path, index2) {
|
|
28856
|
+
var key = path[index2];
|
|
28808
28857
|
var updated = isArray(obj) ? obj.slice() : assign({}, obj);
|
|
28809
|
-
if (index2 + 1 ===
|
|
28858
|
+
if (index2 + 1 === path.length) {
|
|
28810
28859
|
if (isArray(updated)) {
|
|
28811
28860
|
updated.splice(key, 1);
|
|
28812
28861
|
} else {
|
|
@@ -28814,11 +28863,11 @@ var require_react_reconciler_development = __commonJS({
|
|
|
28814
28863
|
}
|
|
28815
28864
|
return updated;
|
|
28816
28865
|
}
|
|
28817
|
-
updated[key] = copyWithDeleteImpl(obj[key],
|
|
28866
|
+
updated[key] = copyWithDeleteImpl(obj[key], path, index2 + 1);
|
|
28818
28867
|
return updated;
|
|
28819
28868
|
};
|
|
28820
|
-
var copyWithDelete = function(obj,
|
|
28821
|
-
return copyWithDeleteImpl(obj,
|
|
28869
|
+
var copyWithDelete = function(obj, path) {
|
|
28870
|
+
return copyWithDeleteImpl(obj, path, 0);
|
|
28822
28871
|
};
|
|
28823
28872
|
var copyWithRenameImpl = function(obj, oldPath, newPath, index2) {
|
|
28824
28873
|
var oldKey = oldPath[index2];
|
|
@@ -28856,17 +28905,17 @@ var require_react_reconciler_development = __commonJS({
|
|
|
28856
28905
|
}
|
|
28857
28906
|
return copyWithRenameImpl(obj, oldPath, newPath, 0);
|
|
28858
28907
|
};
|
|
28859
|
-
var copyWithSetImpl = function(obj,
|
|
28860
|
-
if (index2 >=
|
|
28908
|
+
var copyWithSetImpl = function(obj, path, index2, value) {
|
|
28909
|
+
if (index2 >= path.length) {
|
|
28861
28910
|
return value;
|
|
28862
28911
|
}
|
|
28863
|
-
var key =
|
|
28912
|
+
var key = path[index2];
|
|
28864
28913
|
var updated = isArray(obj) ? obj.slice() : assign({}, obj);
|
|
28865
|
-
updated[key] = copyWithSetImpl(obj[key],
|
|
28914
|
+
updated[key] = copyWithSetImpl(obj[key], path, index2 + 1, value);
|
|
28866
28915
|
return updated;
|
|
28867
28916
|
};
|
|
28868
|
-
var copyWithSet = function(obj,
|
|
28869
|
-
return copyWithSetImpl(obj,
|
|
28917
|
+
var copyWithSet = function(obj, path, value) {
|
|
28918
|
+
return copyWithSetImpl(obj, path, 0, value);
|
|
28870
28919
|
};
|
|
28871
28920
|
var findHook = function(fiber, id) {
|
|
28872
28921
|
var currentHook2 = fiber.memoizedState;
|
|
@@ -28876,10 +28925,10 @@ var require_react_reconciler_development = __commonJS({
|
|
|
28876
28925
|
}
|
|
28877
28926
|
return currentHook2;
|
|
28878
28927
|
};
|
|
28879
|
-
overrideHookState = function(fiber, id,
|
|
28928
|
+
overrideHookState = function(fiber, id, path, value) {
|
|
28880
28929
|
var hook = findHook(fiber, id);
|
|
28881
28930
|
if (hook !== null) {
|
|
28882
|
-
var newState = copyWithSet(hook.memoizedState,
|
|
28931
|
+
var newState = copyWithSet(hook.memoizedState, path, value);
|
|
28883
28932
|
hook.memoizedState = newState;
|
|
28884
28933
|
hook.baseState = newState;
|
|
28885
28934
|
fiber.memoizedProps = assign({}, fiber.memoizedProps);
|
|
@@ -28889,10 +28938,10 @@ var require_react_reconciler_development = __commonJS({
|
|
|
28889
28938
|
}
|
|
28890
28939
|
}
|
|
28891
28940
|
};
|
|
28892
|
-
overrideHookStateDeletePath = function(fiber, id,
|
|
28941
|
+
overrideHookStateDeletePath = function(fiber, id, path) {
|
|
28893
28942
|
var hook = findHook(fiber, id);
|
|
28894
28943
|
if (hook !== null) {
|
|
28895
|
-
var newState = copyWithDelete(hook.memoizedState,
|
|
28944
|
+
var newState = copyWithDelete(hook.memoizedState, path);
|
|
28896
28945
|
hook.memoizedState = newState;
|
|
28897
28946
|
hook.baseState = newState;
|
|
28898
28947
|
fiber.memoizedProps = assign({}, fiber.memoizedProps);
|
|
@@ -28915,8 +28964,8 @@ var require_react_reconciler_development = __commonJS({
|
|
|
28915
28964
|
}
|
|
28916
28965
|
}
|
|
28917
28966
|
};
|
|
28918
|
-
overrideProps = function(fiber,
|
|
28919
|
-
fiber.pendingProps = copyWithSet(fiber.memoizedProps,
|
|
28967
|
+
overrideProps = function(fiber, path, value) {
|
|
28968
|
+
fiber.pendingProps = copyWithSet(fiber.memoizedProps, path, value);
|
|
28920
28969
|
if (fiber.alternate) {
|
|
28921
28970
|
fiber.alternate.pendingProps = fiber.pendingProps;
|
|
28922
28971
|
}
|
|
@@ -28925,8 +28974,8 @@ var require_react_reconciler_development = __commonJS({
|
|
|
28925
28974
|
scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp);
|
|
28926
28975
|
}
|
|
28927
28976
|
};
|
|
28928
|
-
overridePropsDeletePath = function(fiber,
|
|
28929
|
-
fiber.pendingProps = copyWithDelete(fiber.memoizedProps,
|
|
28977
|
+
overridePropsDeletePath = function(fiber, path) {
|
|
28978
|
+
fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path);
|
|
28930
28979
|
if (fiber.alternate) {
|
|
28931
28980
|
fiber.alternate.pendingProps = fiber.pendingProps;
|
|
28932
28981
|
}
|
|
@@ -36994,8 +37043,8 @@ var init_ErrorOverview = __esm({
|
|
|
36994
37043
|
init_dist3();
|
|
36995
37044
|
init_Box();
|
|
36996
37045
|
init_Text();
|
|
36997
|
-
cleanupPath = (
|
|
36998
|
-
return
|
|
37046
|
+
cleanupPath = (path) => {
|
|
37047
|
+
return path?.replace(`file://${cwd()}/`, "");
|
|
36999
37048
|
};
|
|
37000
37049
|
stackUtils = new import_stack_utils.default({
|
|
37001
37050
|
cwd: cwd(),
|
|
@@ -41664,18 +41713,19 @@ async function readNdjsonAnalyzeResponse(response, onPackageProgress) {
|
|
|
41664
41713
|
}
|
|
41665
41714
|
buf += decoder.decode();
|
|
41666
41715
|
if (buf.trim()) processLine(buf);
|
|
41667
|
-
|
|
41716
|
+
const payload = finalPayload;
|
|
41717
|
+
if (!payload) {
|
|
41668
41718
|
throw new APIError(
|
|
41669
41719
|
"Streaming response ended without a result event",
|
|
41670
41720
|
0,
|
|
41671
41721
|
""
|
|
41672
41722
|
);
|
|
41673
41723
|
}
|
|
41674
|
-
if (typeof
|
|
41724
|
+
if (typeof payload.score !== "number" || !Array.isArray(payload.packages)) {
|
|
41675
41725
|
throw new APIError("Invalid streamed result payload", 0, "");
|
|
41676
41726
|
}
|
|
41677
|
-
checkVersionFloor(
|
|
41678
|
-
return sanitizeResponse(
|
|
41727
|
+
checkVersionFloor(payload);
|
|
41728
|
+
return sanitizeResponse(payload);
|
|
41679
41729
|
}
|
|
41680
41730
|
async function callPyPIAnalyzeAPI(packages, config, onProgress) {
|
|
41681
41731
|
const batchSize = config.apiKey ? BATCH_SIZE : ANON_BATCH_SIZE;
|
|
@@ -41992,9 +42042,9 @@ function parseLockfile(content) {
|
|
|
41992
42042
|
const lockfileVersion = json.lockfileVersion ?? 1;
|
|
41993
42043
|
const packages = /* @__PURE__ */ new Map();
|
|
41994
42044
|
if (lockfileVersion >= 2 && json.packages) {
|
|
41995
|
-
for (const [
|
|
41996
|
-
if (
|
|
41997
|
-
const pathName = extractPackageName(
|
|
42045
|
+
for (const [path, entry] of Object.entries(json.packages)) {
|
|
42046
|
+
if (path === "") continue;
|
|
42047
|
+
const pathName = extractPackageName(path);
|
|
41998
42048
|
if (!pathName) continue;
|
|
41999
42049
|
const e = entry;
|
|
42000
42050
|
const entryName = typeof e.name === "string" && e.name.length > 0 ? e.name : void 0;
|
|
@@ -42266,12 +42316,12 @@ var init_parse_package_json = __esm({
|
|
|
42266
42316
|
// src/lockfile/index.ts
|
|
42267
42317
|
import { readFileSync as readFileSync8, existsSync as existsSync11, statSync as statSync3 } from "node:fs";
|
|
42268
42318
|
import { join as join6 } from "node:path";
|
|
42269
|
-
function readFileSafe(
|
|
42270
|
-
const size = statSync3(
|
|
42319
|
+
function readFileSafe(path) {
|
|
42320
|
+
const size = statSync3(path).size;
|
|
42271
42321
|
if (size > MAX_LOCKFILE_BYTES) {
|
|
42272
|
-
throw new Error(`Lockfile too large (${(size / 1024 / 1024).toFixed(0)} MB, max 50 MB): ${
|
|
42322
|
+
throw new Error(`Lockfile too large (${(size / 1024 / 1024).toFixed(0)} MB, max 50 MB): ${path}`);
|
|
42273
42323
|
}
|
|
42274
|
-
return readFileSync8(
|
|
42324
|
+
return readFileSync8(path, "utf-8");
|
|
42275
42325
|
}
|
|
42276
42326
|
function discoverChanges(cwd2, config) {
|
|
42277
42327
|
if (config.workspace) {
|
|
@@ -42537,6 +42587,12 @@ var init_lockfile = __esm({
|
|
|
42537
42587
|
});
|
|
42538
42588
|
|
|
42539
42589
|
// src/commands/wrapper-shared.ts
|
|
42590
|
+
function injectIgnoreScripts(args, opts) {
|
|
42591
|
+
if (!opts.isNpmFamily) return args;
|
|
42592
|
+
if (!(opts.strict || opts.dgNoScripts)) return args;
|
|
42593
|
+
if (args.includes("--ignore-scripts")) return args;
|
|
42594
|
+
return [...args, "--ignore-scripts"];
|
|
42595
|
+
}
|
|
42540
42596
|
function stripDgFlags(args) {
|
|
42541
42597
|
let dgForce = false;
|
|
42542
42598
|
let dgForceReason;
|
|
@@ -42619,9 +42675,7 @@ function realNpmBinary() {
|
|
|
42619
42675
|
return real;
|
|
42620
42676
|
}
|
|
42621
42677
|
function shimSentinelEnv() {
|
|
42622
|
-
|
|
42623
|
-
if (!nonce) return process.env;
|
|
42624
|
-
return { ...process.env, DG_SHIM_ACTIVE: nonce };
|
|
42678
|
+
return childInstallEnv();
|
|
42625
42679
|
}
|
|
42626
42680
|
function parseNpmArgs(args) {
|
|
42627
42681
|
const { filtered, dgForce, dgForceReason, dgNoScripts } = stripDgFlags(args);
|
|
@@ -42889,9 +42943,9 @@ function readLockfilePins(cwd2) {
|
|
|
42889
42943
|
...Object.keys(root.optionalDependencies ?? {}),
|
|
42890
42944
|
...Object.keys(root.peerDependencies ?? {})
|
|
42891
42945
|
]);
|
|
42892
|
-
for (const [
|
|
42893
|
-
if (
|
|
42894
|
-
const m =
|
|
42946
|
+
for (const [path, entry] of Object.entries(lock.packages ?? {})) {
|
|
42947
|
+
if (path === "") continue;
|
|
42948
|
+
const m = path.match(/^node_modules\/((?:@[^/]+\/)?[^/]+)$/);
|
|
42895
42949
|
if (!m) continue;
|
|
42896
42950
|
const name = m[1];
|
|
42897
42951
|
if (!directDeps.has(name)) continue;
|
|
@@ -43067,6 +43121,22 @@ function parsePipSpec(spec) {
|
|
|
43067
43121
|
versionSpec: match[2] ?? null
|
|
43068
43122
|
};
|
|
43069
43123
|
}
|
|
43124
|
+
function pinPipArgs(rawArgs, userSpecs, resolved) {
|
|
43125
|
+
const specNames = new Set(userSpecs.map((s) => parsePipSpec(s).name.toLowerCase()));
|
|
43126
|
+
const pinByName = /* @__PURE__ */ new Map();
|
|
43127
|
+
for (const p of resolved) {
|
|
43128
|
+
const key = p.name.toLowerCase();
|
|
43129
|
+
if (specNames.has(key) && !pinByName.has(key)) {
|
|
43130
|
+
pinByName.set(key, `${p.name}==${p.version}`);
|
|
43131
|
+
}
|
|
43132
|
+
}
|
|
43133
|
+
const specSet = new Set(userSpecs);
|
|
43134
|
+
return rawArgs.map((a) => {
|
|
43135
|
+
if (!specSet.has(a)) return a;
|
|
43136
|
+
const { name } = parsePipSpec(a);
|
|
43137
|
+
return pinByName.get(name.toLowerCase()) ?? a;
|
|
43138
|
+
});
|
|
43139
|
+
}
|
|
43070
43140
|
async function resolvePipVersion(spec) {
|
|
43071
43141
|
const { name, versionSpec } = parsePipSpec(spec);
|
|
43072
43142
|
if (versionSpec?.startsWith("==")) {
|
|
@@ -43128,9 +43198,7 @@ async function resolvePackages2(specs) {
|
|
|
43128
43198
|
return { resolved, failed };
|
|
43129
43199
|
}
|
|
43130
43200
|
function shimSentinelEnv2() {
|
|
43131
|
-
|
|
43132
|
-
if (!nonce) return process.env;
|
|
43133
|
-
return { ...process.env, DG_SHIM_ACTIVE: nonce };
|
|
43201
|
+
return childInstallEnv();
|
|
43134
43202
|
}
|
|
43135
43203
|
async function detectPipBinary() {
|
|
43136
43204
|
const py3 = walkPathExcludingShimDir("python3");
|
|
@@ -43333,6 +43401,153 @@ var init_pip_wrapper = __esm({
|
|
|
43333
43401
|
}
|
|
43334
43402
|
});
|
|
43335
43403
|
|
|
43404
|
+
// src/wrapper/route.ts
|
|
43405
|
+
function routeVerdict(input) {
|
|
43406
|
+
const { verdict, mode, strict, dgForce } = input;
|
|
43407
|
+
const refuseHard = mode === "block" || strict;
|
|
43408
|
+
const refuseWarn = strict;
|
|
43409
|
+
const D = (outcome, refuseExitCode, extra) => ({
|
|
43410
|
+
verdict,
|
|
43411
|
+
outcome,
|
|
43412
|
+
refuseExitCode,
|
|
43413
|
+
bypassed: false,
|
|
43414
|
+
...extra
|
|
43415
|
+
});
|
|
43416
|
+
if (verdict === "free_cap") return D("refuse", 1);
|
|
43417
|
+
if (verdict === "pass") return D("install", 0);
|
|
43418
|
+
if (dgForce && (verdict === "warn" || verdict === "block")) {
|
|
43419
|
+
return D("install", 0, { audit: "override", bypassed: true });
|
|
43420
|
+
}
|
|
43421
|
+
switch (verdict) {
|
|
43422
|
+
case "warn":
|
|
43423
|
+
if (mode === "off") return D("install", 0);
|
|
43424
|
+
if (refuseWarn) return D("refuse", 1);
|
|
43425
|
+
return D("prompt", 1);
|
|
43426
|
+
// warn/block mode → prompt; decline → 1
|
|
43427
|
+
case "block":
|
|
43428
|
+
if (mode === "off") return D("install", 0);
|
|
43429
|
+
return D("refuse", 2, { audit: "block" });
|
|
43430
|
+
case "analysis_incomplete":
|
|
43431
|
+
if (dgForce) return D("install", 0, { bypassed: true });
|
|
43432
|
+
if (refuseHard) return D("refuse", 4);
|
|
43433
|
+
return D("install", 0);
|
|
43434
|
+
// off/warn → install with a "could not verify" notice
|
|
43435
|
+
case "scan_failed":
|
|
43436
|
+
case "tree_failed":
|
|
43437
|
+
if (dgForce) return D("install", 0, { bypassed: true });
|
|
43438
|
+
if (refuseHard) return D("refuse", 2);
|
|
43439
|
+
return D("install", 0);
|
|
43440
|
+
// best-effort under off/warn
|
|
43441
|
+
case "resolve_failed":
|
|
43442
|
+
if (dgForce) return D("passthrough", 0, { bypassed: true });
|
|
43443
|
+
if (refuseHard) return D("refuse", 2);
|
|
43444
|
+
return D("passthrough", 0);
|
|
43445
|
+
// nothing resolved to scan → hand off to the installer
|
|
43446
|
+
default: {
|
|
43447
|
+
const _never = verdict;
|
|
43448
|
+
void _never;
|
|
43449
|
+
return D(refuseHard ? "refuse" : "install", refuseHard ? 4 : 0);
|
|
43450
|
+
}
|
|
43451
|
+
}
|
|
43452
|
+
}
|
|
43453
|
+
var init_route = __esm({
|
|
43454
|
+
"src/wrapper/route.ts"() {
|
|
43455
|
+
"use strict";
|
|
43456
|
+
}
|
|
43457
|
+
});
|
|
43458
|
+
|
|
43459
|
+
// src/wrapper/run.ts
|
|
43460
|
+
function verdictFromResult(result, gates = {}) {
|
|
43461
|
+
if (gates.scanFailed) return "scan_failed";
|
|
43462
|
+
if (gates.treeFailed) return "tree_failed";
|
|
43463
|
+
if (gates.resolveFailed) return "resolve_failed";
|
|
43464
|
+
const action = result?.action;
|
|
43465
|
+
if (action === "pass" || action === "warn" || action === "block") return action;
|
|
43466
|
+
return "analysis_incomplete";
|
|
43467
|
+
}
|
|
43468
|
+
function scanVerdictOf(decision) {
|
|
43469
|
+
if (decision.bypassed && (decision.verdict === "warn" || decision.verdict === "block")) {
|
|
43470
|
+
return "override";
|
|
43471
|
+
}
|
|
43472
|
+
switch (decision.verdict) {
|
|
43473
|
+
case "pass":
|
|
43474
|
+
return "pass";
|
|
43475
|
+
case "warn":
|
|
43476
|
+
return "warn";
|
|
43477
|
+
case "block":
|
|
43478
|
+
return "block";
|
|
43479
|
+
case "analysis_incomplete":
|
|
43480
|
+
return "analysis_incomplete";
|
|
43481
|
+
case "scan_failed":
|
|
43482
|
+
case "tree_failed":
|
|
43483
|
+
case "resolve_failed":
|
|
43484
|
+
return "scan_failed";
|
|
43485
|
+
default:
|
|
43486
|
+
return "skipped";
|
|
43487
|
+
}
|
|
43488
|
+
}
|
|
43489
|
+
async function executeDecision(decision, ctx, presenter) {
|
|
43490
|
+
await presenter.announce(decision, ctx);
|
|
43491
|
+
if (decision.audit) {
|
|
43492
|
+
await presenter.audit(decision.audit, ctx);
|
|
43493
|
+
}
|
|
43494
|
+
const scanVerdict = scanVerdictOf(decision);
|
|
43495
|
+
const base = (installRan, installExitCode) => ({
|
|
43496
|
+
scanVerdict,
|
|
43497
|
+
installRan,
|
|
43498
|
+
installExitCode,
|
|
43499
|
+
error: ctx.error,
|
|
43500
|
+
suppressedByAllowlist: ctx.suppressedCount > 0 ? ctx.suppressedCount : void 0
|
|
43501
|
+
});
|
|
43502
|
+
switch (decision.outcome) {
|
|
43503
|
+
case "refuse":
|
|
43504
|
+
presenter.emit(base(false, null));
|
|
43505
|
+
return decision.refuseExitCode;
|
|
43506
|
+
case "install": {
|
|
43507
|
+
const code = await presenter.runInstall(ctx.installArgs);
|
|
43508
|
+
presenter.emit(base(true, code));
|
|
43509
|
+
return code;
|
|
43510
|
+
}
|
|
43511
|
+
case "passthrough": {
|
|
43512
|
+
const code = await presenter.runInstall(ctx.passthroughArgs);
|
|
43513
|
+
presenter.emit(base(true, code));
|
|
43514
|
+
return code;
|
|
43515
|
+
}
|
|
43516
|
+
case "prompt": {
|
|
43517
|
+
const proceed = await presenter.confirmProceed(ctx);
|
|
43518
|
+
if (!proceed) {
|
|
43519
|
+
presenter.emit(base(false, null));
|
|
43520
|
+
return decision.refuseExitCode;
|
|
43521
|
+
}
|
|
43522
|
+
if (presenter.onPromptAccepted) await presenter.onPromptAccepted(ctx);
|
|
43523
|
+
const code = await presenter.runInstall(ctx.installArgs);
|
|
43524
|
+
presenter.emit(base(true, code));
|
|
43525
|
+
return code;
|
|
43526
|
+
}
|
|
43527
|
+
default: {
|
|
43528
|
+
const _never = decision.outcome;
|
|
43529
|
+
void _never;
|
|
43530
|
+
return 1;
|
|
43531
|
+
}
|
|
43532
|
+
}
|
|
43533
|
+
}
|
|
43534
|
+
var init_run = __esm({
|
|
43535
|
+
"src/wrapper/run.ts"() {
|
|
43536
|
+
"use strict";
|
|
43537
|
+
}
|
|
43538
|
+
});
|
|
43539
|
+
|
|
43540
|
+
// src/wrapper/json.ts
|
|
43541
|
+
function emitWrapperJson(config, result) {
|
|
43542
|
+
if (!config.json) return;
|
|
43543
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
43544
|
+
}
|
|
43545
|
+
var init_json = __esm({
|
|
43546
|
+
"src/wrapper/json.ts"() {
|
|
43547
|
+
"use strict";
|
|
43548
|
+
}
|
|
43549
|
+
});
|
|
43550
|
+
|
|
43336
43551
|
// src/security/artifact_integrity.ts
|
|
43337
43552
|
function normalize(h, algo) {
|
|
43338
43553
|
if (!h) return void 0;
|
|
@@ -43427,16 +43642,16 @@ function collectNpmLockSha512Hashes(packageLock) {
|
|
|
43427
43642
|
const root = packageLock;
|
|
43428
43643
|
const packages = root["packages"];
|
|
43429
43644
|
if (packages && typeof packages === "object") {
|
|
43430
|
-
for (const [
|
|
43431
|
-
if (
|
|
43645
|
+
for (const [path, raw] of Object.entries(packages)) {
|
|
43646
|
+
if (path === "") continue;
|
|
43432
43647
|
if (!raw || typeof raw !== "object") continue;
|
|
43433
43648
|
const entry = raw;
|
|
43434
43649
|
const version = typeof entry.version === "string" ? entry.version : void 0;
|
|
43435
43650
|
const integrity = typeof entry.integrity === "string" ? entry.integrity : void 0;
|
|
43436
43651
|
if (!version || !integrity) continue;
|
|
43437
|
-
const idx =
|
|
43652
|
+
const idx = path.lastIndexOf("node_modules/");
|
|
43438
43653
|
if (idx < 0) continue;
|
|
43439
|
-
const name =
|
|
43654
|
+
const name = path.slice(idx + "node_modules/".length);
|
|
43440
43655
|
if (!name) continue;
|
|
43441
43656
|
const hex = npmIntegrityToSha512Hex(integrity);
|
|
43442
43657
|
if (hex) out.set(`${name}@${version}`, hex);
|
|
@@ -43678,7 +43893,7 @@ var init_FileSavePrompt = __esm({
|
|
|
43678
43893
|
return;
|
|
43679
43894
|
}
|
|
43680
43895
|
if ((key.backspace || key.delete) && !state.filterText) {
|
|
43681
|
-
const parentDir =
|
|
43896
|
+
const parentDir = dirname8(state.directory);
|
|
43682
43897
|
if (parentDir !== state.directory) {
|
|
43683
43898
|
dispatch({ type: "SET_DIRECTORY", directory: parentDir, entries: listDirectory(parentDir) });
|
|
43684
43899
|
}
|
|
@@ -43691,7 +43906,7 @@ var init_FileSavePrompt = __esm({
|
|
|
43691
43906
|
if (key.return) {
|
|
43692
43907
|
const entry = filteredEntries[state.browserCursor];
|
|
43693
43908
|
if (!entry || !entry.isDirectory) return;
|
|
43694
|
-
const newDir = entry.name === ".." ?
|
|
43909
|
+
const newDir = entry.name === ".." ? dirname8(state.directory) : join8(state.directory, entry.name);
|
|
43695
43910
|
dispatch({ type: "SET_DIRECTORY", directory: newDir, entries: listDirectory(newDir) });
|
|
43696
43911
|
return;
|
|
43697
43912
|
}
|
|
@@ -43967,9 +44182,9 @@ async function scanDir(dir, depth, _root) {
|
|
|
43967
44182
|
}
|
|
43968
44183
|
return { subdirs, lockfileHits };
|
|
43969
44184
|
}
|
|
43970
|
-
async function isSafeRegularFile(
|
|
44185
|
+
async function isSafeRegularFile(path) {
|
|
43971
44186
|
try {
|
|
43972
|
-
const st = await lstat(
|
|
44187
|
+
const st = await lstat(path);
|
|
43973
44188
|
return st.isFile() && !st.isSymbolicLink();
|
|
43974
44189
|
} catch {
|
|
43975
44190
|
return false;
|
|
@@ -44104,9 +44319,9 @@ function discoverProjectsConsolidated(projectPaths, config) {
|
|
|
44104
44319
|
const seenPy = /* @__PURE__ */ new Set();
|
|
44105
44320
|
const unparseable = [];
|
|
44106
44321
|
let rawCount = 0;
|
|
44107
|
-
for (const
|
|
44322
|
+
for (const path of projectPaths) {
|
|
44108
44323
|
try {
|
|
44109
|
-
const d = discoverChanges(
|
|
44324
|
+
const d = discoverChanges(path, config);
|
|
44110
44325
|
for (const pkg of d.packages) {
|
|
44111
44326
|
rawCount++;
|
|
44112
44327
|
const key = `${pkg.name}@${pkg.version}`;
|
|
@@ -44122,7 +44337,7 @@ function discoverProjectsConsolidated(projectPaths, config) {
|
|
|
44122
44337
|
pythonPackages.push(pkg);
|
|
44123
44338
|
}
|
|
44124
44339
|
} catch {
|
|
44125
|
-
unparseable.push(
|
|
44340
|
+
unparseable.push(path);
|
|
44126
44341
|
}
|
|
44127
44342
|
}
|
|
44128
44343
|
return {
|
|
@@ -44371,21 +44586,21 @@ function validateAllowlist(raw) {
|
|
|
44371
44586
|
return { ok: true, allowlist: { schemaVersion: 1, rules, packages } };
|
|
44372
44587
|
}
|
|
44373
44588
|
function loadAllowlist(cwd2) {
|
|
44374
|
-
const
|
|
44375
|
-
if (!
|
|
44589
|
+
const path = findAllowlistFile(cwd2);
|
|
44590
|
+
if (!path) return null;
|
|
44376
44591
|
let raw;
|
|
44377
44592
|
try {
|
|
44378
|
-
raw = JSON.parse(readFileSync10(
|
|
44593
|
+
raw = JSON.parse(readFileSync10(path, "utf-8"));
|
|
44379
44594
|
} catch (e) {
|
|
44380
44595
|
process.stderr.write(
|
|
44381
|
-
`dg: .dg-allowlist.json at ${
|
|
44596
|
+
`dg: .dg-allowlist.json at ${path} is not valid JSON (${e.message}). Ignoring.
|
|
44382
44597
|
`
|
|
44383
44598
|
);
|
|
44384
44599
|
return null;
|
|
44385
44600
|
}
|
|
44386
44601
|
const validation = validateAllowlist(raw);
|
|
44387
44602
|
if (!validation.ok) {
|
|
44388
|
-
process.stderr.write(`dg: .dg-allowlist.json at ${
|
|
44603
|
+
process.stderr.write(`dg: .dg-allowlist.json at ${path} failed validation:
|
|
44389
44604
|
`);
|
|
44390
44605
|
for (const err of validation.errors) {
|
|
44391
44606
|
process.stderr.write(` ${err.path}: ${err.message}
|
|
@@ -44395,7 +44610,7 @@ function loadAllowlist(cwd2) {
|
|
|
44395
44610
|
`);
|
|
44396
44611
|
return null;
|
|
44397
44612
|
}
|
|
44398
|
-
return { ...validation.allowlist, sourcePath:
|
|
44613
|
+
return { ...validation.allowlist, sourcePath: path };
|
|
44399
44614
|
}
|
|
44400
44615
|
function findingRuleId(f) {
|
|
44401
44616
|
return (f.category ?? f.title ?? "").toString();
|
|
@@ -44540,6 +44755,7 @@ function buildSarif(response, opts = {}) {
|
|
|
44540
44755
|
});
|
|
44541
44756
|
}
|
|
44542
44757
|
const findings = pkg.findings ?? [];
|
|
44758
|
+
let pkgResultCount = 0;
|
|
44543
44759
|
for (const f of findings) {
|
|
44544
44760
|
const id = findingId(f);
|
|
44545
44761
|
const level = severityToLevel(f.severity);
|
|
@@ -44563,6 +44779,32 @@ function buildSarif(response, opts = {}) {
|
|
|
44563
44779
|
}],
|
|
44564
44780
|
partialFingerprints: { dg_finding: findingFingerprint(pkg, f) }
|
|
44565
44781
|
});
|
|
44782
|
+
pkgResultCount++;
|
|
44783
|
+
}
|
|
44784
|
+
if (pkgResultCount === 0 && (pkg.action === "block" || pkg.action === "warn")) {
|
|
44785
|
+
const ruleId = pkg.action === "block" ? "dg.block" : "dg.warn";
|
|
44786
|
+
const level = pkg.action === "block" ? "error" : "warning";
|
|
44787
|
+
if (!ruleMap.has(ruleId)) {
|
|
44788
|
+
ruleMap.set(ruleId, {
|
|
44789
|
+
id: ruleId,
|
|
44790
|
+
name: ruleId,
|
|
44791
|
+
shortDescription: {
|
|
44792
|
+
text: pkg.action === "block" ? "Package blocked by Dependency Guardian" : "Package flagged (warn) by Dependency Guardian"
|
|
44793
|
+
},
|
|
44794
|
+
defaultConfiguration: { level }
|
|
44795
|
+
});
|
|
44796
|
+
}
|
|
44797
|
+
results.push({
|
|
44798
|
+
ruleId,
|
|
44799
|
+
level,
|
|
44800
|
+
message: { text: `${pkg.name} ${pkg.version}: ${pkg.action} verdict from Dependency Guardian (no individual findings surfaced at this tier).` },
|
|
44801
|
+
locations: [{
|
|
44802
|
+
physicalLocation: {
|
|
44803
|
+
artifactLocation: { uri: opts.lockfileUri ?? `dg:${pkg.name}@${pkg.version}` }
|
|
44804
|
+
}
|
|
44805
|
+
}],
|
|
44806
|
+
partialFingerprints: { dg_finding: `${pkg.name}@${pkg.version}#${ruleId}`.slice(0, 240) }
|
|
44807
|
+
});
|
|
44566
44808
|
}
|
|
44567
44809
|
}
|
|
44568
44810
|
return {
|
|
@@ -44699,7 +44941,7 @@ function shouldFireAudit(policy, decisionAction) {
|
|
|
44699
44941
|
return false;
|
|
44700
44942
|
}
|
|
44701
44943
|
function flagPackages(packages) {
|
|
44702
|
-
return packages.filter((p) => p.
|
|
44944
|
+
return packages.filter((p) => (p.action ?? "pass") !== "pass");
|
|
44703
44945
|
}
|
|
44704
44946
|
async function dispatchPublishCheckAudit(opts) {
|
|
44705
44947
|
try {
|
|
@@ -44726,8 +44968,8 @@ function bypassLogPath2() {
|
|
|
44726
44968
|
}
|
|
44727
44969
|
function recordBypassLocally(record) {
|
|
44728
44970
|
try {
|
|
44729
|
-
const
|
|
44730
|
-
const dir = dirname10(
|
|
44971
|
+
const path = bypassLogPath2();
|
|
44972
|
+
const dir = dirname10(path);
|
|
44731
44973
|
if (!existsSync16(dir)) mkdirSync6(dir, { recursive: true, mode: 448 });
|
|
44732
44974
|
const full = {
|
|
44733
44975
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -44738,7 +44980,7 @@ function recordBypassLocally(record) {
|
|
|
44738
44980
|
reason: record.reason,
|
|
44739
44981
|
packages: record.packages
|
|
44740
44982
|
};
|
|
44741
|
-
appendFileSync3(
|
|
44983
|
+
appendFileSync3(path, JSON.stringify(full) + "\n", { mode: 384 });
|
|
44742
44984
|
} catch {
|
|
44743
44985
|
}
|
|
44744
44986
|
}
|
|
@@ -44797,10 +45039,6 @@ function note(config, text) {
|
|
|
44797
45039
|
if (config.quiet) return;
|
|
44798
45040
|
process.stderr.write(text);
|
|
44799
45041
|
}
|
|
44800
|
-
function emitWrapperJson(config, result) {
|
|
44801
|
-
if (!config.json) return;
|
|
44802
|
-
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
44803
|
-
}
|
|
44804
45042
|
function wrapperPackagesFromResult(result, topLevelNames) {
|
|
44805
45043
|
return result.packages.map((p) => ({
|
|
44806
45044
|
name: p.name,
|
|
@@ -44811,13 +45049,13 @@ function wrapperPackagesFromResult(result, topLevelNames) {
|
|
|
44811
45049
|
}));
|
|
44812
45050
|
}
|
|
44813
45051
|
function loadPackageLockJson(cwd2 = process.cwd()) {
|
|
44814
|
-
const
|
|
44815
|
-
if (!existsSync17(
|
|
45052
|
+
const path = resolvePath(cwd2, "package-lock.json");
|
|
45053
|
+
if (!existsSync17(path)) return null;
|
|
44816
45054
|
try {
|
|
44817
|
-
const st = lstatSync5(
|
|
45055
|
+
const st = lstatSync5(path);
|
|
44818
45056
|
if (!st.isFile()) return null;
|
|
44819
45057
|
if (st.size > MAX_PACKAGE_LOCK_BYTES) return null;
|
|
44820
|
-
return JSON.parse(readFileSync11(
|
|
45058
|
+
return JSON.parse(readFileSync11(path, "utf8"));
|
|
44821
45059
|
} catch {
|
|
44822
45060
|
return null;
|
|
44823
45061
|
}
|
|
@@ -44897,7 +45135,7 @@ function maybePrintFirstScanNotice(config) {
|
|
|
44897
45135
|
if (getScanNoticeShownAt2() !== null) return;
|
|
44898
45136
|
process.stderr.write(
|
|
44899
45137
|
import_chalk5.default.dim(
|
|
44900
|
-
" Dependency Guardian sends package names + versions to api.westbayberry.com.\n Anonymous crash reports are on
|
|
45138
|
+
" Dependency Guardian sends package names + versions to api.westbayberry.com.\n Anonymous crash reports are on to help us fix early bugs (no source, paths, or package names);\n opt out with DG_TELEMETRY=0 or DO_NOT_TRACK=1.\n Terms: https://westbayberry.com/terms \xB7 Privacy: https://westbayberry.com/privacy\n"
|
|
44901
45139
|
)
|
|
44902
45140
|
);
|
|
44903
45141
|
recordScanNoticeShown2();
|
|
@@ -45228,14 +45466,7 @@ async function runStatic(config) {
|
|
|
45228
45466
|
}
|
|
45229
45467
|
if (discovery.pythonPackages.length > 0) {
|
|
45230
45468
|
const pyResult = await callPyPIAnalyzeAPI(discovery.pythonPackages, config);
|
|
45231
|
-
result
|
|
45232
|
-
result.score = Math.max(result.score, pyResult.score);
|
|
45233
|
-
if (pyResult.action === "block" || pyResult.action === "warn" && result.action === "pass") {
|
|
45234
|
-
result.action = pyResult.action;
|
|
45235
|
-
}
|
|
45236
|
-
if (pyResult.freeScansRemaining !== void 0) {
|
|
45237
|
-
result.freeScansRemaining = pyResult.freeScansRemaining;
|
|
45238
|
-
}
|
|
45469
|
+
result = mergeResponses([result, pyResult]);
|
|
45239
45470
|
}
|
|
45240
45471
|
clearSpinner();
|
|
45241
45472
|
dbg(
|
|
@@ -45292,11 +45523,7 @@ async function runStatic(config) {
|
|
|
45292
45523
|
printTrialBanner(result, config);
|
|
45293
45524
|
process.exit(scanExitCode(result.action, config.mode));
|
|
45294
45525
|
}
|
|
45295
|
-
function mergeProjectConfig(config, _argv) {
|
|
45296
|
-
return config;
|
|
45297
|
-
}
|
|
45298
45526
|
async function runStaticNpm(npmArgs, config) {
|
|
45299
|
-
config = mergeProjectConfig(config, process.argv.slice(2));
|
|
45300
45527
|
const parsed = parseNpmArgs(npmArgs);
|
|
45301
45528
|
if (!parsed.shouldScan) {
|
|
45302
45529
|
const code = await runNpm(parsed.rawArgs);
|
|
@@ -45399,11 +45626,11 @@ function buildInstallArgs(parsed, topLevelSpecs, tree, config) {
|
|
|
45399
45626
|
if (tree.length > 0 && topLevelSpecs.length > 0) {
|
|
45400
45627
|
args = pinTopLevelArgs(args, topLevelSpecs, tree);
|
|
45401
45628
|
}
|
|
45402
|
-
|
|
45403
|
-
|
|
45404
|
-
|
|
45405
|
-
|
|
45406
|
-
|
|
45629
|
+
return injectIgnoreScripts(args, {
|
|
45630
|
+
isNpmFamily: true,
|
|
45631
|
+
strict: config.strict,
|
|
45632
|
+
dgNoScripts: parsed.dgNoScripts
|
|
45633
|
+
});
|
|
45407
45634
|
}
|
|
45408
45635
|
async function scanAndInstallStatic(resolved, parsed, config) {
|
|
45409
45636
|
const topLevelSpecs = resolved.map((p) => `${p.name}@${p.version}`);
|
|
@@ -45432,6 +45659,14 @@ async function scanAndInstallStatic(resolved, parsed, config) {
|
|
|
45432
45659
|
process.stderr.write(
|
|
45433
45660
|
import_chalk5.default.dim(" Only top-level packages would be scanned; transitive deps would slip through. Use --dg-force to bypass.\n\n")
|
|
45434
45661
|
);
|
|
45662
|
+
emitWrapperJson(config, {
|
|
45663
|
+
ecosystem: "npm",
|
|
45664
|
+
packages: [],
|
|
45665
|
+
scanVerdict: "scan_failed",
|
|
45666
|
+
installRan: false,
|
|
45667
|
+
installExitCode: null,
|
|
45668
|
+
error: { code: "tree_resolution_failed", message: treeError }
|
|
45669
|
+
});
|
|
45435
45670
|
process.exit(2);
|
|
45436
45671
|
}
|
|
45437
45672
|
process.stderr.write(
|
|
@@ -45540,120 +45775,110 @@ async function scanAndInstallStatic(resolved, parsed, config) {
|
|
|
45540
45775
|
);
|
|
45541
45776
|
}
|
|
45542
45777
|
}
|
|
45543
|
-
|
|
45544
|
-
|
|
45545
|
-
|
|
45546
|
-
|
|
45547
|
-
|
|
45778
|
+
const npmInstallArgs = buildInstallArgs(parsed, topLevelSpecs, tree.packages, config);
|
|
45779
|
+
const npmTopLevelNames = new Set(resolved.map((p) => p.name));
|
|
45780
|
+
const npmDecision = routeVerdict({
|
|
45781
|
+
verdict: verdictFromResult(result),
|
|
45782
|
+
mode: config.mode,
|
|
45783
|
+
strict: config.strict,
|
|
45784
|
+
dgForce: parsed.dgForce
|
|
45785
|
+
});
|
|
45786
|
+
const npmPresenter = {
|
|
45787
|
+
async announce(d) {
|
|
45788
|
+
if (d.verdict === "pass") {
|
|
45789
|
+
const topLevel2 = resolved.map((p) => `${p.name} ${p.version}`);
|
|
45790
|
+
const passLine = topLevel2.length === 1 ? ` ${import_chalk5.default.green("\u2713")} ${import_chalk5.default.bold("DG verified:")} ${topLevel2[0]} is safe` : ` ${import_chalk5.default.green("\u2713")} ${import_chalk5.default.bold("DG verified:")} ${topLevel2.length} packages safe`;
|
|
45791
|
+
const installLine = topLevel2.length === 1 ? ` ${import_chalk5.default.green("\u2713")} Installing ${topLevel2[0]}` : ` ${import_chalk5.default.green("\u2713")} Installing ${topLevel2.join(", ")}`;
|
|
45792
|
+
process.stderr.write(`${passLine}
|
|
45548
45793
|
${installLine}
|
|
45549
45794
|
`);
|
|
45550
|
-
|
|
45551
|
-
|
|
45552
|
-
|
|
45795
|
+
if (parsed.dgNoScripts || config.strict) {
|
|
45796
|
+
const why = config.strict ? "--strict" : "--dg-no-scripts";
|
|
45797
|
+
process.stderr.write(import_chalk5.default.dim(` ${why}: lifecycle scripts will be suppressed during install.
|
|
45553
45798
|
`));
|
|
45554
|
-
|
|
45555
|
-
|
|
45556
|
-
|
|
45557
|
-
|
|
45558
|
-
|
|
45559
|
-
|
|
45560
|
-
|
|
45561
|
-
|
|
45562
|
-
|
|
45563
|
-
|
|
45564
|
-
|
|
45565
|
-
|
|
45566
|
-
|
|
45567
|
-
|
|
45568
|
-
|
|
45569
|
-
|
|
45570
|
-
|
|
45571
|
-
|
|
45572
|
-
|
|
45573
|
-
|
|
45574
|
-
|
|
45575
|
-
|
|
45576
|
-
|
|
45577
|
-
|
|
45578
|
-
|
|
45579
|
-
|
|
45580
|
-
|
|
45581
|
-
|
|
45582
|
-
|
|
45583
|
-
|
|
45584
|
-
|
|
45585
|
-
|
|
45586
|
-
|
|
45587
|
-
|
|
45588
|
-
|
|
45589
|
-
|
|
45590
|
-
|
|
45591
|
-
|
|
45592
|
-
|
|
45593
|
-
|
|
45594
|
-
|
|
45595
|
-
|
|
45596
|
-
|
|
45597
|
-
|
|
45598
|
-
|
|
45599
|
-
|
|
45600
|
-
|
|
45601
|
-
|
|
45602
|
-
|
|
45603
|
-
|
|
45604
|
-
const { dispatchInstallAudit:
|
|
45605
|
-
await
|
|
45799
|
+
}
|
|
45800
|
+
printTrialBanner(result, config);
|
|
45801
|
+
process.stderr.write("\n");
|
|
45802
|
+
return;
|
|
45803
|
+
}
|
|
45804
|
+
const output = renderResultStatic(result, config);
|
|
45805
|
+
(config.json ? process.stderr : process.stdout).write(output + "\n");
|
|
45806
|
+
printTrialBanner(result, config);
|
|
45807
|
+
const topLevel = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
|
|
45808
|
+
if (d.verdict === "warn") {
|
|
45809
|
+
process.stderr.write(` ${import_chalk5.default.yellow("\u26A0")} ${import_chalk5.default.bold("DG flagged")} ${topLevel}.
|
|
45810
|
+
`);
|
|
45811
|
+
} else if (d.verdict === "block") {
|
|
45812
|
+
if (d.outcome === "install") {
|
|
45813
|
+
process.stderr.write(import_chalk5.default.yellow(import_chalk5.default.bold(" --dg-force: Bypassing block. Install at your own risk.\n\n")));
|
|
45814
|
+
} else {
|
|
45815
|
+
const blockedSpecArg = topLevelSpecs.length > 0 ? topLevelSpecs.join(" ") : topLevel.split(", ").map((s) => s.replace(/ /g, "@")).join(" ");
|
|
45816
|
+
process.stderr.write(
|
|
45817
|
+
` ${import_chalk5.default.red("\u2717")} ${import_chalk5.default.bold("DG blocked")} ${topLevel}.
|
|
45818
|
+
Real install was NOT run. To override:
|
|
45819
|
+
` + import_chalk5.default.dim(` npm install ${blockedSpecArg} --dg-force --dg-force-reason="<reason>"
|
|
45820
|
+
|
|
45821
|
+
`)
|
|
45822
|
+
);
|
|
45823
|
+
}
|
|
45824
|
+
} else if (d.verdict === "analysis_incomplete") {
|
|
45825
|
+
if (d.outcome === "refuse") {
|
|
45826
|
+
const specArg = topLevelSpecs.length > 0 ? topLevelSpecs.join(" ") : resolved.map((p) => `${p.name}@${p.version}`).join(" ");
|
|
45827
|
+
process.stderr.write(
|
|
45828
|
+
` ${import_chalk5.default.cyan("?")} ${import_chalk5.default.bold("DG could not verify")} ${topLevel} \u2014 treating as unverified, not safe.
|
|
45829
|
+
Real install was NOT run (--mode block). To override:
|
|
45830
|
+
` + import_chalk5.default.dim(` npm install ${specArg} --dg-force --dg-force-reason="<reason>"
|
|
45831
|
+
|
|
45832
|
+
`)
|
|
45833
|
+
);
|
|
45834
|
+
} else {
|
|
45835
|
+
process.stderr.write(import_chalk5.default.dim(` DG could not fully verify ${topLevel}; proceeding (mode is not block).
|
|
45836
|
+
|
|
45837
|
+
`));
|
|
45838
|
+
}
|
|
45839
|
+
}
|
|
45840
|
+
},
|
|
45841
|
+
async confirmProceed() {
|
|
45842
|
+
const { promptYesNo: promptYesNo2 } = await Promise.resolve().then(() => (init_prompt(), prompt_exports));
|
|
45843
|
+
const proceed = await promptYesNo2({ defaultAnswer: "y", message: ` Proceed?` });
|
|
45844
|
+
if (!proceed) process.stderr.write(import_chalk5.default.dim(" Install cancelled by user.\n\n"));
|
|
45845
|
+
return proceed;
|
|
45846
|
+
},
|
|
45847
|
+
runInstall: (args) => runNpm(args, { stdoutToStderr: !!config.json }),
|
|
45848
|
+
async audit(kind) {
|
|
45849
|
+
const { dispatchInstallAudit: dispatchInstallAudit2 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
|
|
45850
|
+
await dispatchInstallAudit2({
|
|
45606
45851
|
ecosystem: "npm",
|
|
45607
45852
|
packages: result.packages,
|
|
45608
|
-
decisionAction:
|
|
45609
|
-
bypassed:
|
|
45610
|
-
bypassReason: parsed.dgForceReason
|
|
45853
|
+
decisionAction: kind,
|
|
45854
|
+
bypassed: kind === "override",
|
|
45855
|
+
bypassReason: kind === "override" ? parsed.dgForceReason : void 0
|
|
45611
45856
|
});
|
|
45612
|
-
|
|
45613
|
-
|
|
45614
|
-
import_chalk5.default.bold(
|
|
45615
|
-
" --dg-force: Bypassing block. Install at your own risk.\n\n"
|
|
45616
|
-
)
|
|
45617
|
-
)
|
|
45618
|
-
);
|
|
45619
|
-
const code = await runNpm(buildInstallArgs(parsed, topLevelSpecs, tree.packages, config), { stdoutToStderr: !!config.json });
|
|
45857
|
+
},
|
|
45858
|
+
emit(record) {
|
|
45620
45859
|
emitWrapperJson(config, {
|
|
45621
45860
|
ecosystem: "npm",
|
|
45622
|
-
packages: wrapperPackagesFromResult(result,
|
|
45623
|
-
scanVerdict:
|
|
45624
|
-
installRan:
|
|
45625
|
-
installExitCode:
|
|
45861
|
+
packages: wrapperPackagesFromResult(result, npmTopLevelNames),
|
|
45862
|
+
scanVerdict: record.scanVerdict,
|
|
45863
|
+
installRan: record.installRan,
|
|
45864
|
+
installExitCode: record.installExitCode,
|
|
45865
|
+
error: record.error
|
|
45626
45866
|
});
|
|
45627
|
-
process.exit(code);
|
|
45628
45867
|
}
|
|
45629
|
-
|
|
45630
|
-
|
|
45631
|
-
|
|
45632
|
-
|
|
45633
|
-
|
|
45634
|
-
|
|
45635
|
-
|
|
45636
|
-
|
|
45637
|
-
|
|
45638
|
-
|
|
45639
|
-
|
|
45640
|
-
|
|
45641
|
-
` + import_chalk5.default.dim(` npm install ${blockedSpecArg} --dg-force --dg-force-reason="<reason>"
|
|
45642
|
-
|
|
45643
|
-
`)
|
|
45644
|
-
);
|
|
45645
|
-
emitWrapperJson(config, {
|
|
45646
|
-
ecosystem: "npm",
|
|
45647
|
-
packages: wrapperPackagesFromResult(result, new Set(resolved.map((p) => p.name))),
|
|
45648
|
-
scanVerdict: "block",
|
|
45649
|
-
installRan: false,
|
|
45650
|
-
installExitCode: null
|
|
45651
|
-
});
|
|
45652
|
-
process.exit(2);
|
|
45653
|
-
}
|
|
45868
|
+
};
|
|
45869
|
+
const npmCtx = {
|
|
45870
|
+
ecosystem: "npm",
|
|
45871
|
+
apiKind: "npm",
|
|
45872
|
+
installArgs: npmInstallArgs,
|
|
45873
|
+
passthroughArgs: parsed.rawArgs,
|
|
45874
|
+
result,
|
|
45875
|
+
resolved,
|
|
45876
|
+
suppressedCount: 0,
|
|
45877
|
+
dgForceReason: parsed.dgForceReason
|
|
45878
|
+
};
|
|
45879
|
+
process.exit(await executeDecision(npmDecision, npmCtx, npmPresenter));
|
|
45654
45880
|
}
|
|
45655
45881
|
async function runStaticPip(pipArgs, config) {
|
|
45656
|
-
config = mergeProjectConfig(config, process.argv.slice(2));
|
|
45657
45882
|
const parsed = parsePipArgs(pipArgs);
|
|
45658
45883
|
if (!parsed.shouldScan) {
|
|
45659
45884
|
const code = await runPip(parsed.rawArgs, { stdoutToStderr: !!config.json });
|
|
@@ -45740,6 +45965,17 @@ async function runStaticPip(pipArgs, config) {
|
|
|
45740
45965
|
)
|
|
45741
45966
|
);
|
|
45742
45967
|
}
|
|
45968
|
+
const isRequirementsInstall = !!parsed.requirementsFile;
|
|
45969
|
+
if (isRequirementsInstall && !(pipTreeOk && pipTree.hashes.size > 0) && (config.mode === "block" || config.strict) && !parsed.dgForce) {
|
|
45970
|
+
process.stderr.write(
|
|
45971
|
+
import_chalk5.default.red(import_chalk5.default.bold(" BLOCKED: ")) + import_chalk5.default.red(`a -r requirements install cannot be pinned to exact versions and no dry-run hashes are available to verify the artifacts.
|
|
45972
|
+
`) + import_chalk5.default.dim(` Install aborted${config.strict ? " in --strict" : " in --mode block"} (resolve\u2192install mismatch risk). Use --mode warn or --dg-force to bypass.
|
|
45973
|
+
|
|
45974
|
+
`)
|
|
45975
|
+
);
|
|
45976
|
+
process.exit(2);
|
|
45977
|
+
}
|
|
45978
|
+
const pipInstallArgs = pinPipArgs(parsed.rawArgs, parsed.packages, resolved);
|
|
45743
45979
|
note(
|
|
45744
45980
|
config,
|
|
45745
45981
|
import_chalk5.default.dim(
|
|
@@ -45768,14 +46004,14 @@ async function runStaticPip(pipArgs, config) {
|
|
|
45768
46004
|
process.stderr.write(
|
|
45769
46005
|
import_chalk5.default.yellow(import_chalk5.default.bold(" --dg-force: Bypassing block. Install at your own risk.\n\n"))
|
|
45770
46006
|
);
|
|
45771
|
-
const code2 = await runPip(
|
|
46007
|
+
const code2 = await runPip(pipInstallArgs, { stdoutToStderr: !!config.json });
|
|
45772
46008
|
process.exit(code2);
|
|
45773
46009
|
}
|
|
45774
46010
|
process.stderr.write(
|
|
45775
46011
|
import_chalk5.default.yellow(` Warning: Scan failed (${msg}). Proceeding with install (mode=${config.mode}).
|
|
45776
46012
|
`)
|
|
45777
46013
|
);
|
|
45778
|
-
const code = await runPip(
|
|
46014
|
+
const code = await runPip(pipInstallArgs, { stdoutToStderr: !!config.json });
|
|
45779
46015
|
process.exit(code);
|
|
45780
46016
|
return;
|
|
45781
46017
|
}
|
|
@@ -45803,105 +46039,101 @@ async function runStaticPip(pipArgs, config) {
|
|
|
45803
46039
|
}
|
|
45804
46040
|
}
|
|
45805
46041
|
const pipTopLevelNames = new Set(resolved.map((p) => p.name));
|
|
45806
|
-
|
|
45807
|
-
|
|
45808
|
-
|
|
45809
|
-
|
|
45810
|
-
|
|
46042
|
+
const pipDecision = routeVerdict({
|
|
46043
|
+
verdict: verdictFromResult(result),
|
|
46044
|
+
mode: config.mode,
|
|
46045
|
+
strict: config.strict,
|
|
46046
|
+
dgForce: parsed.dgForce
|
|
46047
|
+
});
|
|
46048
|
+
const pipPresenter = {
|
|
46049
|
+
async announce(d) {
|
|
46050
|
+
if (d.verdict === "pass") {
|
|
46051
|
+
const topLevel2 = resolved.map((p) => `${p.name} ${p.version}`);
|
|
46052
|
+
const passLine = topLevel2.length === 1 ? ` ${import_chalk5.default.green("\u2713")} ${import_chalk5.default.bold("DG verified:")} ${topLevel2[0]} is safe` : ` ${import_chalk5.default.green("\u2713")} ${import_chalk5.default.bold("DG verified:")} ${topLevel2.length} packages safe`;
|
|
46053
|
+
const installLine = topLevel2.length === 1 ? ` ${import_chalk5.default.green("\u2713")} Installing ${topLevel2[0]}` : ` ${import_chalk5.default.green("\u2713")} Installing ${topLevel2.join(", ")}`;
|
|
46054
|
+
process.stderr.write(`${passLine}
|
|
45811
46055
|
${installLine}
|
|
45812
46056
|
`);
|
|
45813
|
-
|
|
45814
|
-
|
|
45815
|
-
|
|
45816
|
-
|
|
45817
|
-
|
|
45818
|
-
|
|
45819
|
-
|
|
45820
|
-
|
|
45821
|
-
|
|
45822
|
-
|
|
45823
|
-
|
|
45824
|
-
|
|
45825
|
-
|
|
45826
|
-
|
|
45827
|
-
|
|
45828
|
-
|
|
45829
|
-
|
|
45830
|
-
|
|
45831
|
-
|
|
45832
|
-
|
|
45833
|
-
|
|
45834
|
-
|
|
45835
|
-
|
|
45836
|
-
|
|
45837
|
-
|
|
45838
|
-
|
|
45839
|
-
|
|
45840
|
-
|
|
45841
|
-
|
|
45842
|
-
|
|
45843
|
-
|
|
45844
|
-
|
|
45845
|
-
|
|
45846
|
-
|
|
45847
|
-
|
|
45848
|
-
|
|
45849
|
-
|
|
45850
|
-
|
|
45851
|
-
|
|
45852
|
-
|
|
45853
|
-
|
|
45854
|
-
|
|
45855
|
-
|
|
45856
|
-
}
|
|
45857
|
-
|
|
45858
|
-
|
|
45859
|
-
|
|
45860
|
-
|
|
46057
|
+
printTrialBanner(result, config);
|
|
46058
|
+
process.stderr.write("\n");
|
|
46059
|
+
return;
|
|
46060
|
+
}
|
|
46061
|
+
const output = renderResultStatic(result, config);
|
|
46062
|
+
(config.json ? process.stderr : process.stdout).write(output + "\n");
|
|
46063
|
+
printTrialBanner(result, config);
|
|
46064
|
+
const topLevel = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
|
|
46065
|
+
if (d.verdict === "warn") {
|
|
46066
|
+
process.stderr.write(` ${import_chalk5.default.yellow("\u26A0")} ${import_chalk5.default.bold("DG flagged")} ${topLevel}.
|
|
46067
|
+
`);
|
|
46068
|
+
} else if (d.verdict === "block") {
|
|
46069
|
+
if (d.outcome === "install") {
|
|
46070
|
+
process.stderr.write(import_chalk5.default.yellow(import_chalk5.default.bold(" --dg-force: Bypassing block. Install at your own risk.\n\n")));
|
|
46071
|
+
} else {
|
|
46072
|
+
const pipBlockedSpecArg = resolved.map((p) => `${p.name}==${p.version}`).join(" ");
|
|
46073
|
+
process.stderr.write(
|
|
46074
|
+
` ${import_chalk5.default.red("\u2717")} ${import_chalk5.default.bold("DG blocked")} ${topLevel}.
|
|
46075
|
+
Real install was NOT run. To override:
|
|
46076
|
+
` + import_chalk5.default.dim(` pip install ${pipBlockedSpecArg} --dg-force --dg-force-reason="<reason>"
|
|
46077
|
+
|
|
46078
|
+
`)
|
|
46079
|
+
);
|
|
46080
|
+
}
|
|
46081
|
+
} else if (d.verdict === "analysis_incomplete") {
|
|
46082
|
+
if (d.outcome === "refuse") {
|
|
46083
|
+
const pipSpecArg = resolved.map((p) => `${p.name}==${p.version}`).join(" ");
|
|
46084
|
+
process.stderr.write(
|
|
46085
|
+
` ${import_chalk5.default.cyan("?")} ${import_chalk5.default.bold("DG could not verify")} ${topLevel} \u2014 treating as unverified, not safe.
|
|
46086
|
+
Real install was NOT run (--mode block). To override:
|
|
46087
|
+
` + import_chalk5.default.dim(` pip install ${pipSpecArg} --dg-force --dg-force-reason="<reason>"
|
|
46088
|
+
|
|
46089
|
+
`)
|
|
46090
|
+
);
|
|
46091
|
+
} else {
|
|
46092
|
+
process.stderr.write(import_chalk5.default.dim(` DG could not fully verify ${topLevel}; proceeding (mode is not block).
|
|
46093
|
+
|
|
46094
|
+
`));
|
|
46095
|
+
}
|
|
46096
|
+
}
|
|
46097
|
+
},
|
|
46098
|
+
async confirmProceed() {
|
|
46099
|
+
const { promptYesNo: promptYesNo2 } = await Promise.resolve().then(() => (init_prompt(), prompt_exports));
|
|
46100
|
+
const proceed = await promptYesNo2({ defaultAnswer: "y", message: " Proceed?" });
|
|
46101
|
+
if (!proceed) process.stderr.write(import_chalk5.default.dim(" Install cancelled by user.\n\n"));
|
|
46102
|
+
return proceed;
|
|
46103
|
+
},
|
|
46104
|
+
runInstall: (args) => runPip(args, { stdoutToStderr: !!config.json }),
|
|
46105
|
+
async audit(kind) {
|
|
46106
|
+
const { dispatchInstallAudit: dispatchInstallAudit2 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
|
|
46107
|
+
await dispatchInstallAudit2({
|
|
45861
46108
|
ecosystem: "pypi",
|
|
45862
46109
|
packages: result.packages,
|
|
45863
|
-
decisionAction:
|
|
45864
|
-
bypassed:
|
|
45865
|
-
bypassReason: parsed.dgForceReason
|
|
46110
|
+
decisionAction: kind,
|
|
46111
|
+
bypassed: kind === "override",
|
|
46112
|
+
bypassReason: kind === "override" ? parsed.dgForceReason : void 0
|
|
45866
46113
|
});
|
|
45867
|
-
|
|
45868
|
-
|
|
45869
|
-
);
|
|
45870
|
-
const code = await runPip(parsed.rawArgs, { stdoutToStderr: !!config.json });
|
|
46114
|
+
},
|
|
46115
|
+
emit(record) {
|
|
45871
46116
|
emitWrapperJson(config, {
|
|
45872
46117
|
ecosystem: "pypi",
|
|
45873
46118
|
packages: wrapperPackagesFromResult(result, pipTopLevelNames),
|
|
45874
|
-
scanVerdict:
|
|
45875
|
-
installRan:
|
|
45876
|
-
installExitCode:
|
|
46119
|
+
scanVerdict: record.scanVerdict,
|
|
46120
|
+
installRan: record.installRan,
|
|
46121
|
+
installExitCode: record.installExitCode,
|
|
46122
|
+
error: record.error
|
|
45877
46123
|
});
|
|
45878
|
-
process.exit(code);
|
|
45879
46124
|
}
|
|
45880
|
-
|
|
45881
|
-
|
|
45882
|
-
|
|
45883
|
-
|
|
45884
|
-
|
|
45885
|
-
|
|
45886
|
-
|
|
45887
|
-
|
|
45888
|
-
|
|
45889
|
-
|
|
45890
|
-
|
|
45891
|
-
|
|
45892
|
-
` + import_chalk5.default.dim(` pip install ${pipBlockedSpecArg} --dg-force --dg-force-reason="<reason>"
|
|
45893
|
-
|
|
45894
|
-
`)
|
|
45895
|
-
);
|
|
45896
|
-
emitWrapperJson(config, {
|
|
45897
|
-
ecosystem: "pypi",
|
|
45898
|
-
packages: wrapperPackagesFromResult(result, pipTopLevelNames),
|
|
45899
|
-
scanVerdict: "block",
|
|
45900
|
-
installRan: false,
|
|
45901
|
-
installExitCode: null
|
|
45902
|
-
});
|
|
45903
|
-
process.exit(2);
|
|
45904
|
-
}
|
|
46125
|
+
};
|
|
46126
|
+
const pipCtx = {
|
|
46127
|
+
ecosystem: "pypi",
|
|
46128
|
+
apiKind: "pypi",
|
|
46129
|
+
installArgs: pipInstallArgs,
|
|
46130
|
+
passthroughArgs: parsed.rawArgs,
|
|
46131
|
+
result,
|
|
46132
|
+
resolved,
|
|
46133
|
+
suppressedCount: 0,
|
|
46134
|
+
dgForceReason: parsed.dgForceReason
|
|
46135
|
+
};
|
|
46136
|
+
process.exit(await executeDecision(pipDecision, pipCtx, pipPresenter));
|
|
45905
46137
|
}
|
|
45906
46138
|
async function runStaticLogin() {
|
|
45907
46139
|
const {
|
|
@@ -46014,6 +46246,10 @@ var init_static_output = __esm({
|
|
|
46014
46246
|
init_lockfile();
|
|
46015
46247
|
init_npm_wrapper();
|
|
46016
46248
|
init_pip_wrapper();
|
|
46249
|
+
init_wrapper_shared();
|
|
46250
|
+
init_route();
|
|
46251
|
+
init_run();
|
|
46252
|
+
init_json();
|
|
46017
46253
|
init_artifact_integrity();
|
|
46018
46254
|
init_sanitize();
|
|
46019
46255
|
init_format_helpers();
|
|
@@ -46808,11 +47044,11 @@ var init_InteractiveResultsView = __esm({
|
|
|
46808
47044
|
const scanUsage = usageDisplay ? usageDisplay.text : result.freeScansRemaining !== void 0 ? `${result.freeScansRemaining.toLocaleString()} packages left` : scanUsageProp;
|
|
46809
47045
|
const usageNearLimit = usageDisplay?.nearLimit ?? false;
|
|
46810
47046
|
const flagged = (0, import_react30.useMemo)(
|
|
46811
|
-
() => result.packages.filter((p) => p.
|
|
47047
|
+
() => result.packages.filter((p) => (p.action ?? "pass") !== "pass"),
|
|
46812
47048
|
[result.packages]
|
|
46813
47049
|
);
|
|
46814
47050
|
const clean = (0, import_react30.useMemo)(
|
|
46815
|
-
() => result.packages.filter((p) => p.
|
|
47051
|
+
() => result.packages.filter((p) => (p.action ?? "pass") === "pass"),
|
|
46816
47052
|
[result.packages]
|
|
46817
47053
|
);
|
|
46818
47054
|
const total = result.packages.length;
|
|
@@ -47108,8 +47344,8 @@ var init_InteractiveResultsView = __esm({
|
|
|
47108
47344
|
const { body, ext } = formatExport(payload, scope, format);
|
|
47109
47345
|
const scopeTag = scope === "current-license" && currentLicenseIdx !== null ? `${(licenseGroups[currentLicenseIdx]?.spdx ?? "license").replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 32)}` : scope;
|
|
47110
47346
|
const filename = `dg-scan-${ts}-${scopeTag}.${ext}`;
|
|
47111
|
-
const
|
|
47112
|
-
writeFileSync11(
|
|
47347
|
+
const path = resolvePath2(process.cwd(), filename);
|
|
47348
|
+
writeFileSync11(path, body, "utf-8");
|
|
47113
47349
|
showExportMsg(`\u2713 Exported to ${filename}`);
|
|
47114
47350
|
} catch (e) {
|
|
47115
47351
|
showExportMsg(`Export failed: ${e.message}`);
|
|
@@ -48506,6 +48742,7 @@ var publish_check_exports = {};
|
|
|
48506
48742
|
__export(publish_check_exports, {
|
|
48507
48743
|
findPypiArtifacts: () => findPypiArtifacts,
|
|
48508
48744
|
npmPackDryRun: () => npmPackDryRun,
|
|
48745
|
+
publishCheckExitCode: () => publishCheckExitCode,
|
|
48509
48746
|
renderPublishCheckResult: () => renderPublishCheckResult,
|
|
48510
48747
|
runNpmPublishCheck: () => runNpmPublishCheck,
|
|
48511
48748
|
runPypiPublishCheck: () => runPypiPublishCheck,
|
|
@@ -48642,6 +48879,12 @@ function summarize(ecosystem, artifact, files, findings) {
|
|
|
48642
48879
|
action
|
|
48643
48880
|
};
|
|
48644
48881
|
}
|
|
48882
|
+
function publishCheckExitCode(action, force) {
|
|
48883
|
+
if (force) return 0;
|
|
48884
|
+
if (action === "block") return 2;
|
|
48885
|
+
if (action === "warn") return 1;
|
|
48886
|
+
return 0;
|
|
48887
|
+
}
|
|
48645
48888
|
async function runNpmPublishCheck(cwd2 = process.cwd()) {
|
|
48646
48889
|
const pack = await npmPackDryRun(cwd2);
|
|
48647
48890
|
if (!pack.ok) return { ok: false, errorMessage: pack.errorMessage };
|
|
@@ -48703,10 +48946,10 @@ function parseTar(buf) {
|
|
|
48703
48946
|
}
|
|
48704
48947
|
return out;
|
|
48705
48948
|
}
|
|
48706
|
-
async function readGzipped(
|
|
48949
|
+
async function readGzipped(path) {
|
|
48707
48950
|
return new Promise((resolve3, reject) => {
|
|
48708
48951
|
const chunks = [];
|
|
48709
|
-
const stream = createReadStream(
|
|
48952
|
+
const stream = createReadStream(path).pipe(createGunzip());
|
|
48710
48953
|
stream.on("data", (c) => chunks.push(c));
|
|
48711
48954
|
stream.on("end", () => resolve3(Buffer.concat(chunks)));
|
|
48712
48955
|
stream.on("error", reject);
|
|
@@ -48939,11 +49182,11 @@ function validateEntry(raw) {
|
|
|
48939
49182
|
};
|
|
48940
49183
|
}
|
|
48941
49184
|
function readRegistry() {
|
|
48942
|
-
const
|
|
48943
|
-
if (!existsSync20(
|
|
49185
|
+
const path = registryPath();
|
|
49186
|
+
if (!existsSync20(path)) return [];
|
|
48944
49187
|
let raw;
|
|
48945
49188
|
try {
|
|
48946
|
-
raw = readFileSync14(
|
|
49189
|
+
raw = readFileSync14(path, "utf-8");
|
|
48947
49190
|
} catch {
|
|
48948
49191
|
return [];
|
|
48949
49192
|
}
|
|
@@ -48964,13 +49207,13 @@ function readRegistry() {
|
|
|
48964
49207
|
return out;
|
|
48965
49208
|
}
|
|
48966
49209
|
function writeRegistry(entries) {
|
|
48967
|
-
const
|
|
48968
|
-
const parent = dirname12(
|
|
49210
|
+
const path = registryPath();
|
|
49211
|
+
const parent = dirname12(path);
|
|
48969
49212
|
if (!existsSync20(parent)) mkdirSync8(parent, { recursive: true, mode: 448 });
|
|
48970
49213
|
const payload = { version: 1, entries };
|
|
48971
|
-
writeFileSync12(
|
|
49214
|
+
writeFileSync12(path, JSON.stringify(payload, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
48972
49215
|
try {
|
|
48973
|
-
chmodSync4(
|
|
49216
|
+
chmodSync4(path, 384);
|
|
48974
49217
|
} catch {
|
|
48975
49218
|
}
|
|
48976
49219
|
}
|
|
@@ -49569,9 +49812,9 @@ function installPrefix(resolvedBinPath) {
|
|
|
49569
49812
|
if (idx < 0) return null;
|
|
49570
49813
|
return resolvedBinPath.slice(0, idx);
|
|
49571
49814
|
}
|
|
49572
|
-
function canWrite(
|
|
49815
|
+
function canWrite(path) {
|
|
49573
49816
|
try {
|
|
49574
|
-
accessSync(
|
|
49817
|
+
accessSync(path, constants2.W_OK);
|
|
49575
49818
|
return true;
|
|
49576
49819
|
} catch {
|
|
49577
49820
|
return false;
|
|
@@ -49994,9 +50237,9 @@ async function revokeApiKey(apiKey) {
|
|
|
49994
50237
|
return { ok: false, reason: e.message };
|
|
49995
50238
|
}
|
|
49996
50239
|
}
|
|
49997
|
-
function rmFile(
|
|
50240
|
+
function rmFile(path) {
|
|
49998
50241
|
try {
|
|
49999
|
-
unlinkSync7(
|
|
50242
|
+
unlinkSync7(path);
|
|
50000
50243
|
return { ok: true };
|
|
50001
50244
|
} catch (e) {
|
|
50002
50245
|
const code = e.code;
|
|
@@ -50004,9 +50247,9 @@ function rmFile(path2) {
|
|
|
50004
50247
|
return { ok: false, reason: e.message };
|
|
50005
50248
|
}
|
|
50006
50249
|
}
|
|
50007
|
-
function rmTree(
|
|
50250
|
+
function rmTree(path) {
|
|
50008
50251
|
try {
|
|
50009
|
-
rmSync2(
|
|
50252
|
+
rmSync2(path, { recursive: true, force: true });
|
|
50010
50253
|
return { ok: true };
|
|
50011
50254
|
} catch (e) {
|
|
50012
50255
|
return { ok: false, reason: e.message };
|
|
@@ -50673,6 +50916,11 @@ async function runNpmScan(packages, skippedCount, config, dispatch) {
|
|
|
50673
50916
|
dispatch({ type: "SCAN_COMPLETE", result, durationMs: Date.now() - startMs, skippedCount });
|
|
50674
50917
|
} catch (error) {
|
|
50675
50918
|
if (error instanceof FreeCapReachedError) {
|
|
50919
|
+
try {
|
|
50920
|
+
const { recordScanCapReached: recordScanCapReached2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
50921
|
+
recordScanCapReached2(error.scansUsed, error.maxScans, error.reason);
|
|
50922
|
+
} catch {
|
|
50923
|
+
}
|
|
50676
50924
|
dispatch({ type: "FREE_CAP_REACHED", scansUsed: error.scansUsed, maxScans: error.maxScans, capReason: error.reason });
|
|
50677
50925
|
return;
|
|
50678
50926
|
}
|
|
@@ -50752,6 +51000,11 @@ async function scanProjects(projects, config, dispatch) {
|
|
|
50752
51000
|
dispatch({ type: "SCAN_COMPLETE", result: merged, durationMs: merged.durationMs, skippedCount: 0, discoveredTotal });
|
|
50753
51001
|
} catch (error) {
|
|
50754
51002
|
if (error instanceof FreeCapReachedError) {
|
|
51003
|
+
try {
|
|
51004
|
+
const { recordScanCapReached: recordScanCapReached2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
51005
|
+
recordScanCapReached2(error.scansUsed, error.maxScans, error.reason);
|
|
51006
|
+
} catch {
|
|
51007
|
+
}
|
|
50755
51008
|
dispatch({ type: "FREE_CAP_REACHED", scansUsed: error.scansUsed, maxScans: error.maxScans, capReason: error.reason });
|
|
50756
51009
|
return;
|
|
50757
51010
|
}
|
|
@@ -50995,8 +51248,8 @@ var init_ProjectSelector = __esm({
|
|
|
50995
51248
|
const ecoCountPlainLen = `${proj.ecosystem} ${proj.packageCount} packages`.length;
|
|
50996
51249
|
const fixedPrefixLen = 4;
|
|
50997
51250
|
const pathColWidth = Math.max(20, termCols - fixedPrefixLen - ecoCountPlainLen - 3);
|
|
50998
|
-
const
|
|
50999
|
-
const pathTruncated =
|
|
51251
|
+
const path = sanitize(proj.relativePath);
|
|
51252
|
+
const pathTruncated = path.length > pathColWidth ? path.slice(0, Math.max(1, pathColWidth - 1)) + "\u2026" : path.padEnd(pathColWidth);
|
|
51000
51253
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { backgroundColor: isCursor ? "#1a1a2e" : void 0, wrap: "truncate-end", children: [
|
|
51001
51254
|
prefix,
|
|
51002
51255
|
check,
|
|
@@ -51091,6 +51344,7 @@ var init_App2 = __esm({
|
|
|
51091
51344
|
await init_ProjectSelector();
|
|
51092
51345
|
await init_SetupBanner();
|
|
51093
51346
|
await init_useTerminalSize();
|
|
51347
|
+
init_static_output();
|
|
51094
51348
|
init_terminal_state();
|
|
51095
51349
|
import_jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
|
|
51096
51350
|
App2 = ({ config, userStatus, scanUsage, setupIssues = [] }) => {
|
|
@@ -51129,16 +51383,7 @@ var init_App2 = __esm({
|
|
|
51129
51383
|
}, []);
|
|
51130
51384
|
const handleResultsExit = (0, import_react36.useCallback)(() => {
|
|
51131
51385
|
if (state.phase === "results") {
|
|
51132
|
-
|
|
51133
|
-
if (result.action === "block" && config.mode === "block") {
|
|
51134
|
-
process.exitCode = 2;
|
|
51135
|
-
} else if (result.action === "block" || result.action === "warn") {
|
|
51136
|
-
process.exitCode = 1;
|
|
51137
|
-
} else if (result.action === "analysis_incomplete") {
|
|
51138
|
-
process.exitCode = 4;
|
|
51139
|
-
} else {
|
|
51140
|
-
process.exitCode = 0;
|
|
51141
|
-
}
|
|
51386
|
+
process.exitCode = scanExitCode(state.result.action, config.mode);
|
|
51142
51387
|
}
|
|
51143
51388
|
leaveAltScreen();
|
|
51144
51389
|
exit();
|
|
@@ -51167,7 +51412,10 @@ var init_App2 = __esm({
|
|
|
51167
51412
|
`, 3);
|
|
51168
51413
|
return () => clearTimeout(timer);
|
|
51169
51414
|
}
|
|
51170
|
-
|
|
51415
|
+
if (state.phase === "results") {
|
|
51416
|
+
process.exitCode = scanExitCode(state.result.action, config.mode);
|
|
51417
|
+
}
|
|
51418
|
+
}, [state, config, exitWithMessage]);
|
|
51171
51419
|
use_input_default((input, key) => {
|
|
51172
51420
|
if (state.phase === "discovering" || state.phase === "scanning") {
|
|
51173
51421
|
if (input === "q" || key.escape) {
|
|
@@ -51317,9 +51565,9 @@ function locateInkInstancesPath() {
|
|
|
51317
51565
|
async function initInkInstances() {
|
|
51318
51566
|
if (realInstances) return;
|
|
51319
51567
|
try {
|
|
51320
|
-
const
|
|
51321
|
-
if (!
|
|
51322
|
-
const mod = await import(
|
|
51568
|
+
const path = locateInkInstancesPath();
|
|
51569
|
+
if (!path) return;
|
|
51570
|
+
const mod = await import(path);
|
|
51323
51571
|
realInstances = mod.default ?? null;
|
|
51324
51572
|
} catch {
|
|
51325
51573
|
realInstances = null;
|
|
@@ -51569,6 +51817,10 @@ function reducer4(_state, action) {
|
|
|
51569
51817
|
return { phase: "warn", result: action.result, dgForce: action.dgForce };
|
|
51570
51818
|
case "BLOCKED":
|
|
51571
51819
|
return { phase: "blocked", result: action.result, dgForce: action.dgForce };
|
|
51820
|
+
case "INCOMPLETE":
|
|
51821
|
+
return { phase: "incomplete", result: action.result, message: action.message, proceed: action.proceed };
|
|
51822
|
+
case "REFUSED":
|
|
51823
|
+
return { phase: "refused", result: action.result, message: action.message };
|
|
51572
51824
|
case "INSTALLING":
|
|
51573
51825
|
return { phase: "installing" };
|
|
51574
51826
|
case "DONE":
|
|
@@ -51603,12 +51855,13 @@ function useInstallWrapper(rawArgs, config, opts, exit) {
|
|
|
51603
51855
|
if (started.current) return;
|
|
51604
51856
|
started.current = true;
|
|
51605
51857
|
const parsed = parsedRef.current;
|
|
51858
|
+
let installArgs = parsed.rawArgs;
|
|
51606
51859
|
(async () => {
|
|
51607
51860
|
try {
|
|
51608
51861
|
if (!parsed.shouldScan) {
|
|
51609
51862
|
dispatch({ type: "PASSTHROUGH" });
|
|
51610
|
-
const
|
|
51611
|
-
dispatch({ type: "DONE", exitCode:
|
|
51863
|
+
const code2 = await opts.runInstall(parsed.rawArgs);
|
|
51864
|
+
dispatch({ type: "DONE", exitCode: code2 });
|
|
51612
51865
|
return;
|
|
51613
51866
|
}
|
|
51614
51867
|
let specs;
|
|
@@ -51616,8 +51869,8 @@ function useInstallWrapper(rawArgs, config, opts, exit) {
|
|
|
51616
51869
|
specs = opts.inferSpecsFromContext(parsed);
|
|
51617
51870
|
if (specs.length === 0) {
|
|
51618
51871
|
dispatch({ type: "PASSTHROUGH" });
|
|
51619
|
-
const
|
|
51620
|
-
dispatch({ type: "DONE", exitCode:
|
|
51872
|
+
const code2 = await opts.runInstall(parsed.rawArgs);
|
|
51873
|
+
dispatch({ type: "DONE", exitCode: code2 });
|
|
51621
51874
|
return;
|
|
51622
51875
|
}
|
|
51623
51876
|
} else {
|
|
@@ -51627,95 +51880,130 @@ function useInstallWrapper(rawArgs, config, opts, exit) {
|
|
|
51627
51880
|
const { resolved } = await opts.resolvePackages(specs);
|
|
51628
51881
|
if (resolved.length === 0) {
|
|
51629
51882
|
dispatch({ type: "PASSTHROUGH" });
|
|
51630
|
-
const
|
|
51631
|
-
dispatch({ type: "DONE", exitCode:
|
|
51883
|
+
const code2 = await opts.runInstall(parsed.rawArgs);
|
|
51884
|
+
dispatch({ type: "DONE", exitCode: code2 });
|
|
51632
51885
|
return;
|
|
51633
51886
|
}
|
|
51634
|
-
|
|
51635
|
-
|
|
51887
|
+
const isRequirementsInstall = opts.ecosystem === "pypi" && (parsed.rawArgs.includes("-r") || parsed.rawArgs.includes("--requirement"));
|
|
51888
|
+
if (isRequirementsInstall && (config.mode === "block" || config.strict) && !parsed.dgForce) {
|
|
51889
|
+
dispatch({
|
|
51890
|
+
type: "ERROR",
|
|
51891
|
+
message: `A -r requirements install cannot be pinned to the exact scanned versions; refusing in ${config.strict ? "--strict" : "--mode block"} (resolve\u2192install mismatch risk). Use --mode warn or --dg-force to bypass.`,
|
|
51892
|
+
proceed: false
|
|
51893
|
+
});
|
|
51894
|
+
dispatch({ type: "DONE", exitCode: 2 });
|
|
51895
|
+
return;
|
|
51896
|
+
}
|
|
51897
|
+
const pinnedArgs = isRequirementsInstall ? parsed.rawArgs : opts.ecosystem === "npm" ? pinTopLevelArgs(parsed.rawArgs, parsed.packages, resolved) : pinPipArgs(parsed.rawArgs, parsed.packages, resolved);
|
|
51898
|
+
installArgs = injectIgnoreScripts(pinnedArgs, {
|
|
51899
|
+
isNpmFamily: opts.ecosystem === "npm",
|
|
51900
|
+
strict: config.strict,
|
|
51901
|
+
dgNoScripts: parsed.dgNoScripts
|
|
51902
|
+
});
|
|
51903
|
+
let scanSet = resolved;
|
|
51904
|
+
if (opts.resolveTree) {
|
|
51905
|
+
const tree = await opts.resolveTree(specs);
|
|
51906
|
+
if (tree.ok && tree.packages.length > 0) {
|
|
51907
|
+
scanSet = tree.packages;
|
|
51908
|
+
} else if ((config.mode === "block" || config.strict) && !parsed.dgForce) {
|
|
51909
|
+
dispatch({
|
|
51910
|
+
type: "ERROR",
|
|
51911
|
+
message: `Could not enumerate the dependency tree (${tree.errorMessage ?? "dry-run produced no tree"}); transitive deps would install unscanned. Install aborted in ${config.strict ? "--strict" : "--mode block"}. Use --dg-force to bypass.`,
|
|
51912
|
+
proceed: false
|
|
51913
|
+
});
|
|
51914
|
+
dispatch({ type: "DONE", exitCode: 2 });
|
|
51915
|
+
return;
|
|
51916
|
+
}
|
|
51917
|
+
}
|
|
51918
|
+
dispatch({ type: "SCANNING", count: scanSet.length });
|
|
51919
|
+
const result = await opts.callAnalyze(scanSet, config);
|
|
51636
51920
|
if (result.action === "pass") {
|
|
51637
51921
|
if (exit) exit();
|
|
51638
51922
|
const chalk18 = (await Promise.resolve().then(() => __toESM(require_source(), 1))).default;
|
|
51639
51923
|
const line = formatPassLine(result, chalk18);
|
|
51640
51924
|
process.stderr.write(" " + line + "\n\n");
|
|
51641
|
-
const
|
|
51642
|
-
process.exit(
|
|
51925
|
+
const code2 = await opts.runInstall(installArgs);
|
|
51926
|
+
process.exit(code2);
|
|
51643
51927
|
return;
|
|
51644
51928
|
}
|
|
51645
|
-
|
|
51646
|
-
|
|
51647
|
-
|
|
51648
|
-
|
|
51649
|
-
|
|
51650
|
-
|
|
51651
|
-
|
|
51652
|
-
|
|
51653
|
-
|
|
51654
|
-
|
|
51655
|
-
|
|
51656
|
-
|
|
51657
|
-
|
|
51658
|
-
|
|
51659
|
-
|
|
51660
|
-
|
|
51661
|
-
dispatch({ type: "WARN", result, dgForce: false });
|
|
51662
|
-
const shouldProceed = await new Promise((resolve3) => {
|
|
51663
|
-
pendingInstall.current = () => resolve3(true);
|
|
51664
|
-
rejectRef.current = () => resolve3(false);
|
|
51929
|
+
const verdict = verdictFromResult(result);
|
|
51930
|
+
const decision = routeVerdict({
|
|
51931
|
+
verdict,
|
|
51932
|
+
mode: config.mode,
|
|
51933
|
+
strict: config.strict,
|
|
51934
|
+
dgForce: parsed.dgForce
|
|
51935
|
+
});
|
|
51936
|
+
const bypassVerdict = decision.verdict === "block" ? "block" : "warn";
|
|
51937
|
+
const recordBypass = async (trigger) => {
|
|
51938
|
+
const { recordBypassLocally: recordBypassLocally2 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
|
|
51939
|
+
recordBypassLocally2({
|
|
51940
|
+
ecosystem: opts.ecosystem,
|
|
51941
|
+
verdict: bypassVerdict,
|
|
51942
|
+
trigger,
|
|
51943
|
+
reason: trigger === "dg-force" ? parsed.dgForceReason : void 0,
|
|
51944
|
+
packages: result.packages.map((p) => ({ name: p.name, version: p.version, score: p.score }))
|
|
51665
51945
|
});
|
|
51666
|
-
|
|
51667
|
-
|
|
51668
|
-
|
|
51669
|
-
|
|
51670
|
-
|
|
51671
|
-
trigger: "interactive-confirm",
|
|
51672
|
-
packages: result.packages.map((p) => ({ name: p.name, version: p.version, score: p.score }))
|
|
51673
|
-
});
|
|
51674
|
-
dispatch({ type: "INSTALLING" });
|
|
51675
|
-
const code = await opts.runInstall(parsed.rawArgs);
|
|
51676
|
-
dispatch({ type: "DONE", exitCode: code });
|
|
51677
|
-
} else {
|
|
51678
|
-
dispatch({ type: "DONE", exitCode: 1 });
|
|
51946
|
+
};
|
|
51947
|
+
const refusedMessage = () => {
|
|
51948
|
+
const list = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
|
|
51949
|
+
if (decision.verdict === "block") {
|
|
51950
|
+
return `DG blocked ${list}. Real install was NOT run. Re-run with --dg-force --dg-force-reason="<reason>" to override.`;
|
|
51679
51951
|
}
|
|
51680
|
-
|
|
51681
|
-
|
|
51682
|
-
if (result.action === "block") {
|
|
51683
|
-
if (parsed.dgForce) {
|
|
51684
|
-
const { recordBypassLocally: recordBypassLocally2 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
|
|
51685
|
-
recordBypassLocally2({
|
|
51686
|
-
ecosystem: opts.ecosystem,
|
|
51687
|
-
verdict: "block",
|
|
51688
|
-
trigger: "dg-force",
|
|
51689
|
-
reason: parsed.dgForceReason,
|
|
51690
|
-
packages: result.packages.map((p) => ({ name: p.name, version: p.version, score: p.score }))
|
|
51691
|
-
});
|
|
51692
|
-
dispatch({ type: "BLOCKED", result, dgForce: true });
|
|
51693
|
-
dispatch({ type: "INSTALLING" });
|
|
51694
|
-
const code = await opts.runInstall(parsed.rawArgs);
|
|
51695
|
-
dispatch({ type: "DONE", exitCode: code });
|
|
51696
|
-
return;
|
|
51952
|
+
if (decision.verdict === "analysis_incomplete") {
|
|
51953
|
+
return `DG could not fully analyze ${list} (analysis incomplete). Refusing in ${config.strict ? "--strict" : "--mode block"} \u2014 unverified is not safe. Use --mode warn or --dg-force to bypass.`;
|
|
51697
51954
|
}
|
|
51698
|
-
|
|
51699
|
-
|
|
51700
|
-
|
|
51701
|
-
|
|
51702
|
-
|
|
51703
|
-
|
|
51704
|
-
|
|
51705
|
-
|
|
51706
|
-
|
|
51707
|
-
|
|
51708
|
-
|
|
51709
|
-
|
|
51955
|
+
return `DG flagged ${list}. Refusing in --strict. Use --mode warn or --dg-force to proceed.`;
|
|
51956
|
+
};
|
|
51957
|
+
const presenter = {
|
|
51958
|
+
announce(d) {
|
|
51959
|
+
if (d.outcome === "refuse") {
|
|
51960
|
+
dispatch({ type: "REFUSED", result, message: refusedMessage() });
|
|
51961
|
+
return;
|
|
51962
|
+
}
|
|
51963
|
+
switch (d.verdict) {
|
|
51964
|
+
case "warn":
|
|
51965
|
+
dispatch({ type: "WARN", result, dgForce: d.bypassed });
|
|
51966
|
+
return;
|
|
51967
|
+
case "block":
|
|
51968
|
+
dispatch({ type: "BLOCKED", result, dgForce: d.bypassed });
|
|
51969
|
+
return;
|
|
51970
|
+
case "analysis_incomplete":
|
|
51971
|
+
dispatch({ type: "INCOMPLETE", result, proceed: true, message: "DG could not fully analyze the install set (analysis incomplete)." });
|
|
51972
|
+
return;
|
|
51973
|
+
default:
|
|
51974
|
+
return;
|
|
51975
|
+
}
|
|
51976
|
+
},
|
|
51977
|
+
confirmProceed() {
|
|
51978
|
+
return new Promise((resolve3) => {
|
|
51979
|
+
pendingInstall.current = () => resolve3(true);
|
|
51980
|
+
rejectRef.current = () => resolve3(false);
|
|
51710
51981
|
});
|
|
51982
|
+
},
|
|
51983
|
+
async runInstall(args) {
|
|
51711
51984
|
dispatch({ type: "INSTALLING" });
|
|
51712
|
-
|
|
51713
|
-
|
|
51714
|
-
|
|
51715
|
-
|
|
51985
|
+
return opts.runInstall(args);
|
|
51986
|
+
},
|
|
51987
|
+
async audit(kind) {
|
|
51988
|
+
if (kind === "override") await recordBypass("dg-force");
|
|
51989
|
+
},
|
|
51990
|
+
onPromptAccepted: () => recordBypass("interactive-confirm"),
|
|
51991
|
+
emit() {
|
|
51716
51992
|
}
|
|
51717
|
-
|
|
51718
|
-
|
|
51993
|
+
};
|
|
51994
|
+
const ctx = {
|
|
51995
|
+
ecosystem: opts.ecosystem,
|
|
51996
|
+
apiKind: opts.ecosystem,
|
|
51997
|
+
installArgs,
|
|
51998
|
+
passthroughArgs: parsed.rawArgs,
|
|
51999
|
+
result,
|
|
52000
|
+
resolved,
|
|
52001
|
+
suppressedCount: 0,
|
|
52002
|
+
dgForceReason: parsed.dgForceReason
|
|
52003
|
+
};
|
|
52004
|
+
const code = await executeDecision(decision, ctx, presenter);
|
|
52005
|
+
dispatch({ type: "DONE", exitCode: code });
|
|
52006
|
+
return;
|
|
51719
52007
|
} catch (error) {
|
|
51720
52008
|
if (error instanceof FreeCapReachedError) {
|
|
51721
52009
|
dispatch({ type: "FREE_CAP_REACHED" });
|
|
@@ -51733,7 +52021,7 @@ function useInstallWrapper(rawArgs, config, opts, exit) {
|
|
|
51733
52021
|
}
|
|
51734
52022
|
dispatch({ type: "ERROR", message, proceed: true });
|
|
51735
52023
|
dispatch({ type: "INSTALLING" });
|
|
51736
|
-
const code = await opts.runInstall(
|
|
52024
|
+
const code = await opts.runInstall(installArgs);
|
|
51737
52025
|
dispatch({ type: "DONE", exitCode: code });
|
|
51738
52026
|
}
|
|
51739
52027
|
})();
|
|
@@ -51756,11 +52044,15 @@ var init_useWrapperBase = __esm({
|
|
|
51756
52044
|
"use strict";
|
|
51757
52045
|
import_react37 = __toESM(require_react(), 1);
|
|
51758
52046
|
init_client();
|
|
52047
|
+
init_wrapper_shared();
|
|
52048
|
+
init_route();
|
|
52049
|
+
init_run();
|
|
51759
52050
|
init_npm_wrapper();
|
|
51760
52051
|
init_pip_wrapper();
|
|
51761
52052
|
NPM_OPTIONS = {
|
|
51762
52053
|
parseArgs: parseNpmArgs,
|
|
51763
52054
|
resolvePackages,
|
|
52055
|
+
resolveTree: resolveTreeNpm,
|
|
51764
52056
|
callAnalyze: callAnalyzeAPI,
|
|
51765
52057
|
runInstall: runNpm,
|
|
51766
52058
|
inferSpecsFromContext: () => readBareInstallPackages(process.cwd()),
|
|
@@ -51769,6 +52061,7 @@ var init_useWrapperBase = __esm({
|
|
|
51769
52061
|
PIP_OPTIONS = {
|
|
51770
52062
|
parseArgs: parsePipArgs,
|
|
51771
52063
|
resolvePackages: resolvePackages2,
|
|
52064
|
+
resolveTree: resolveTreePip,
|
|
51772
52065
|
callAnalyze: callPyPIAnalyzeAPI,
|
|
51773
52066
|
runInstall: runPip,
|
|
51774
52067
|
inferSpecsFromContext: (parsed) => {
|
|
@@ -51832,8 +52125,8 @@ var init_ResultsView = __esm({
|
|
|
51832
52125
|
config: _config,
|
|
51833
52126
|
durationMs
|
|
51834
52127
|
}) => {
|
|
51835
|
-
const flagged = result.packages.filter((p) => p.
|
|
51836
|
-
const clean = result.packages.filter((p) => p.
|
|
52128
|
+
const flagged = result.packages.filter((p) => (p.action ?? "pass") !== "pass");
|
|
52129
|
+
const clean = result.packages.filter((p) => (p.action ?? "pass") === "pass");
|
|
51837
52130
|
const total = result.packages.length;
|
|
51838
52131
|
const groups = groupPackages(flagged);
|
|
51839
52132
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 2, children: [
|
|
@@ -51877,7 +52170,7 @@ var init_ResultsView = __esm({
|
|
|
51877
52170
|
import_chalk16.default.dim(`package${clean.length !== 1 ? "s" : ""} passed with score 0`)
|
|
51878
52171
|
] }),
|
|
51879
52172
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Newline, {}),
|
|
51880
|
-
groups.filter((g) => g.packages[0].
|
|
52173
|
+
groups.filter((g) => (g.packages[0].action ?? "pass") !== "pass").map((group) => {
|
|
51881
52174
|
const rep = group.packages[0];
|
|
51882
52175
|
const names = group.packages.length === 1 ? `${rep.name}@${rep.version}` : group.packages.length <= 3 ? group.packages.map((p) => `${p.name}@${p.version}`).join(", ") : `${rep.name}@${rep.version} + ${group.packages.length - 1} identical packages`;
|
|
51883
52176
|
const visibleFindings = rep.findings.filter((f) => f.severity > 1).sort((a, b) => b.severity - a.severity);
|
|
@@ -52163,9 +52456,18 @@ var init_WrapperApp = __esm({
|
|
|
52163
52456
|
case "blocked":
|
|
52164
52457
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Box_default, { flexDirection: "column", children: [
|
|
52165
52458
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(WrapperVerdictLine, { result: state.result, verdict: "block", dgForce: state.dgForce }),
|
|
52166
|
-
showDetails && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ResultsView, { result: state.result, config, durationMs: state.result.durationMs }) })
|
|
52167
|
-
!state.dgForce && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ConfirmPrompt, { message: "", onConfirm: handleConfirm, onReject: handleReject })
|
|
52459
|
+
showDetails && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ResultsView, { result: state.result, config, durationMs: state.result.durationMs }) })
|
|
52168
52460
|
] });
|
|
52461
|
+
case "refused":
|
|
52462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ErrorView, { error: new Error(state.message) });
|
|
52463
|
+
case "incomplete":
|
|
52464
|
+
if (state.proceed) {
|
|
52465
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Text, { color: "yellow", children: [
|
|
52466
|
+
state.message,
|
|
52467
|
+
" Proceeding with install."
|
|
52468
|
+
] });
|
|
52469
|
+
}
|
|
52470
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ErrorView, { error: new Error(state.message) });
|
|
52169
52471
|
case "installing":
|
|
52170
52472
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Spinner2, { label: labels.installing });
|
|
52171
52473
|
case "done":
|
|
@@ -52245,26 +52547,33 @@ function parseCondaArgs(args) {
|
|
|
52245
52547
|
async function resolveTopLevel(_parsed) {
|
|
52246
52548
|
return { resolved: [], failed: [] };
|
|
52247
52549
|
}
|
|
52248
|
-
async function runStaticConda(args) {
|
|
52550
|
+
async function runStaticConda(args, ecosystem, config) {
|
|
52249
52551
|
const parsed = parseCondaArgs(args);
|
|
52250
|
-
if (
|
|
52552
|
+
if (parsed.shouldScan && (config.mode === "block" || config.strict) && !parsed.dgForce) {
|
|
52251
52553
|
process.stderr.write(
|
|
52252
|
-
import_chalk18.default.
|
|
52253
|
-
`) + import_chalk18.default.dim(`
|
|
52554
|
+
import_chalk18.default.red(import_chalk18.default.bold(" \u2717 BLOCKED: ")) + import_chalk18.default.red(`${ecosystem} packages cannot be scanned (the scanner backend does not support this ecosystem).
|
|
52555
|
+
`) + import_chalk18.default.dim(` --mode ${config.strict ? "strict" : "block"} \u21D2 refusing to install unscanned packages. Use --mode warn or --dg-force to bypass.
|
|
52254
52556
|
|
|
52255
52557
|
`)
|
|
52256
52558
|
);
|
|
52559
|
+
return 2;
|
|
52257
52560
|
}
|
|
52258
|
-
|
|
52561
|
+
if (parsed.shouldScan && process.stderr.isTTY) {
|
|
52562
|
+
process.stderr.write(
|
|
52563
|
+
import_chalk18.default.yellow(`\u2139\uFE0F DG: ${ecosystem} packages aren't yet scanned (the scanner backend doesn't support this ecosystem yet).
|
|
52564
|
+
`) + import_chalk18.default.dim(` Passing through to real ${ecosystem}. Use \`dg verify\` for individual pypi-known packages.
|
|
52565
|
+
|
|
52566
|
+
`)
|
|
52567
|
+
);
|
|
52568
|
+
}
|
|
52569
|
+
const real = resolveRealBinary(ecosystem);
|
|
52259
52570
|
if (!real) {
|
|
52260
|
-
process.stderr.write(`dg: real
|
|
52571
|
+
process.stderr.write(`dg: real ${ecosystem} not found on PATH
|
|
52261
52572
|
`);
|
|
52262
52573
|
return 127;
|
|
52263
52574
|
}
|
|
52264
|
-
const nonce = readNonce();
|
|
52265
|
-
const env3 = nonce ? { ...process.env, DG_SHIM_ACTIVE: nonce } : { ...process.env };
|
|
52266
52575
|
return await new Promise((resolve3) => {
|
|
52267
|
-
const child = spawn5(real, parsed.rawArgs, { stdio: "inherit", env:
|
|
52576
|
+
const child = spawn5(real, parsed.rawArgs, { stdio: "inherit", env: childInstallEnv() });
|
|
52268
52577
|
child.on("close", (code) => resolve3(code ?? 1));
|
|
52269
52578
|
child.on("error", () => resolve3(1));
|
|
52270
52579
|
});
|
|
@@ -52644,7 +52953,11 @@ function parseUvArgs(args) {
|
|
|
52644
52953
|
for (let i = argStart; i < filtered.length; i++) {
|
|
52645
52954
|
const arg = filtered[i];
|
|
52646
52955
|
if (arg === "-r" || arg === "--requirement") {
|
|
52647
|
-
|
|
52956
|
+
const file = filtered[i + 1];
|
|
52957
|
+
if (file !== void 0) {
|
|
52958
|
+
i++;
|
|
52959
|
+
packages.push(...parseRequirementsFile(file));
|
|
52960
|
+
}
|
|
52648
52961
|
continue;
|
|
52649
52962
|
}
|
|
52650
52963
|
if (arg.startsWith("-")) {
|
|
@@ -52671,7 +52984,6 @@ async function resolveTopLevel5(parsed) {
|
|
|
52671
52984
|
if (at <= 0) return s;
|
|
52672
52985
|
return `${s.slice(0, at)}==${s.slice(at + 1)}`;
|
|
52673
52986
|
});
|
|
52674
|
-
void parsePipSpec;
|
|
52675
52987
|
return await resolvePackages2(normalized);
|
|
52676
52988
|
}
|
|
52677
52989
|
async function resolveTransitive4(parsed) {
|
|
@@ -52800,14 +53112,8 @@ __export(wrapper_factory_exports, {
|
|
|
52800
53112
|
runEcosystemWrapper: () => runEcosystemWrapper
|
|
52801
53113
|
});
|
|
52802
53114
|
import { spawn as spawn6 } from "node:child_process";
|
|
52803
|
-
function emitJson(config, result) {
|
|
52804
|
-
if (!config.json) return;
|
|
52805
|
-
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
52806
|
-
}
|
|
52807
53115
|
function shimSentinelEnv3() {
|
|
52808
|
-
|
|
52809
|
-
if (!nonce) return process.env;
|
|
52810
|
-
return { ...process.env, DG_SHIM_ACTIVE: nonce };
|
|
53116
|
+
return childInstallEnv();
|
|
52811
53117
|
}
|
|
52812
53118
|
async function spawnRealBinary(adapter7, args) {
|
|
52813
53119
|
const real = resolveRealBinary(adapter7.realBinaryName);
|
|
@@ -52852,8 +53158,46 @@ async function runEcosystemWrapper(adapter7, args, config) {
|
|
|
52852
53158
|
`)
|
|
52853
53159
|
);
|
|
52854
53160
|
}
|
|
53161
|
+
const isRequirementsInstall = adapter7.apiKind === "pypi" && (parsed.rawArgs.includes("-r") || parsed.rawArgs.includes("--requirement"));
|
|
53162
|
+
let pinnedArgs = parsed.rawArgs;
|
|
53163
|
+
if (adapter7.apiKind === "npm") {
|
|
53164
|
+
pinnedArgs = pinTopLevelArgs(parsed.rawArgs, parsed.packages, resolved);
|
|
53165
|
+
} else if (!isRequirementsInstall) {
|
|
53166
|
+
pinnedArgs = pinPipArgs(parsed.rawArgs, parsed.packages, resolved);
|
|
53167
|
+
}
|
|
53168
|
+
if (isRequirementsInstall && (config.mode === "block" || config.strict) && !parsed.dgForce) {
|
|
53169
|
+
if (!config.json && !config.quiet) {
|
|
53170
|
+
process.stderr.write(
|
|
53171
|
+
import_chalk19.default.red(import_chalk19.default.bold(" \u2717 BLOCKED: ")) + import_chalk19.default.red(`a -r requirements install cannot be pinned to the exact scanned versions.
|
|
53172
|
+
`) + import_chalk19.default.dim(` --mode ${config.strict ? "strict" : "block"} \u21D2 refusing (would risk a resolve\u2192install mismatch). Use --mode warn or --dg-force to bypass.
|
|
53173
|
+
|
|
53174
|
+
`)
|
|
53175
|
+
);
|
|
53176
|
+
}
|
|
53177
|
+
emitWrapperJson(config, {
|
|
53178
|
+
ecosystem: adapter7.ecosystem,
|
|
53179
|
+
packages: [],
|
|
53180
|
+
scanVerdict: "scan_failed",
|
|
53181
|
+
installRan: false,
|
|
53182
|
+
installExitCode: null,
|
|
53183
|
+
error: { code: "unpinnable_requirements", message: "-r requirements install cannot be pinned to exact versions" }
|
|
53184
|
+
});
|
|
53185
|
+
return 2;
|
|
53186
|
+
}
|
|
53187
|
+
if (isRequirementsInstall && !config.json && !config.quiet) {
|
|
53188
|
+
process.stderr.write(
|
|
53189
|
+
import_chalk19.default.dim(` Note: -r requirements install cannot be pinned to exact versions; installing as specified.
|
|
53190
|
+
`)
|
|
53191
|
+
);
|
|
53192
|
+
}
|
|
53193
|
+
const installArgs = injectIgnoreScripts(pinnedArgs, {
|
|
53194
|
+
isNpmFamily: adapter7.apiKind === "npm",
|
|
53195
|
+
strict: config.strict,
|
|
53196
|
+
dgNoScripts: parsed.dgNoScripts
|
|
53197
|
+
});
|
|
52855
53198
|
let scanSet = resolved;
|
|
52856
53199
|
let treeOk = true;
|
|
53200
|
+
let treeError;
|
|
52857
53201
|
if (adapter7.resolveTransitive) {
|
|
52858
53202
|
const tree = await adapter7.resolveTransitive(parsed);
|
|
52859
53203
|
if (tree.ok && tree.packages.length > 0) {
|
|
@@ -52873,15 +53217,36 @@ async function runEcosystemWrapper(adapter7, args, config) {
|
|
|
52873
53217
|
`)
|
|
52874
53218
|
);
|
|
52875
53219
|
}
|
|
52876
|
-
} else if (!tree.ok
|
|
53220
|
+
} else if (!tree.ok) {
|
|
52877
53221
|
treeOk = false;
|
|
53222
|
+
treeError = tree.errorMessage ?? "unknown";
|
|
53223
|
+
}
|
|
53224
|
+
}
|
|
53225
|
+
if (!treeOk && (config.mode === "block" || config.strict) && !parsed.dgForce) {
|
|
53226
|
+
if (!config.json && !config.quiet) {
|
|
52878
53227
|
process.stderr.write(
|
|
52879
|
-
import_chalk19.default.
|
|
53228
|
+
import_chalk19.default.red(import_chalk19.default.bold(" \u2717 BLOCKED: ")) + import_chalk19.default.red(`could not enumerate transitive dependencies (${treeError}); they would install unscanned.
|
|
53229
|
+
`) + import_chalk19.default.dim(` --mode block \u21D2 refusing install. Use --mode warn or --dg-force to bypass.
|
|
53230
|
+
|
|
52880
53231
|
`)
|
|
52881
53232
|
);
|
|
52882
53233
|
}
|
|
53234
|
+
emitWrapperJson(config, {
|
|
53235
|
+
ecosystem: adapter7.ecosystem,
|
|
53236
|
+
packages: [],
|
|
53237
|
+
scanVerdict: "scan_failed",
|
|
53238
|
+
installRan: false,
|
|
53239
|
+
installExitCode: null,
|
|
53240
|
+
error: { code: "tree_resolution_failed", message: treeError ?? "transitive resolution failed" }
|
|
53241
|
+
});
|
|
53242
|
+
return 2;
|
|
53243
|
+
}
|
|
53244
|
+
if (!treeOk && !config.json && !config.quiet) {
|
|
53245
|
+
process.stderr.write(
|
|
53246
|
+
import_chalk19.default.dim(` Transitive resolution unavailable (${treeError}); scanning top-level only.
|
|
53247
|
+
`)
|
|
53248
|
+
);
|
|
52883
53249
|
}
|
|
52884
|
-
void treeOk;
|
|
52885
53250
|
let result;
|
|
52886
53251
|
try {
|
|
52887
53252
|
if (adapter7.apiKind === "npm") {
|
|
@@ -52897,7 +53262,7 @@ async function runEcosystemWrapper(adapter7, args, config) {
|
|
|
52897
53262
|
|
|
52898
53263
|
`)
|
|
52899
53264
|
);
|
|
52900
|
-
|
|
53265
|
+
emitWrapperJson(config, {
|
|
52901
53266
|
ecosystem: adapter7.ecosystem,
|
|
52902
53267
|
packages: [],
|
|
52903
53268
|
scanVerdict: "scan_failed",
|
|
@@ -52907,14 +53272,14 @@ async function runEcosystemWrapper(adapter7, args, config) {
|
|
|
52907
53272
|
});
|
|
52908
53273
|
return 1;
|
|
52909
53274
|
}
|
|
52910
|
-
if (config.mode === "block" && !parsed.dgForce) {
|
|
53275
|
+
if ((config.mode === "block" || config.strict) && !parsed.dgForce) {
|
|
52911
53276
|
process.stderr.write(
|
|
52912
53277
|
import_chalk19.default.red(` \u2717 DG scan failed: ${err.message}
|
|
52913
|
-
`) + import_chalk19.default.dim(` --mode block + scan failure \u21D2 refusing install. Use --mode warn or --dg-force to bypass.
|
|
53278
|
+
`) + import_chalk19.default.dim(` --mode ${config.strict ? "strict" : "block"} + scan failure \u21D2 refusing install. Use --mode warn or --dg-force to bypass.
|
|
52914
53279
|
|
|
52915
53280
|
`)
|
|
52916
53281
|
);
|
|
52917
|
-
|
|
53282
|
+
emitWrapperJson(config, {
|
|
52918
53283
|
ecosystem: adapter7.ecosystem,
|
|
52919
53284
|
packages: [],
|
|
52920
53285
|
scanVerdict: "scan_failed",
|
|
@@ -52922,7 +53287,7 @@ async function runEcosystemWrapper(adapter7, args, config) {
|
|
|
52922
53287
|
installExitCode: null,
|
|
52923
53288
|
error: { code: "scan_failed", message: err.message }
|
|
52924
53289
|
});
|
|
52925
|
-
return
|
|
53290
|
+
return 2;
|
|
52926
53291
|
}
|
|
52927
53292
|
if (!config.json && !config.quiet) {
|
|
52928
53293
|
process.stderr.write(
|
|
@@ -52930,157 +53295,155 @@ async function runEcosystemWrapper(adapter7, args, config) {
|
|
|
52930
53295
|
`)
|
|
52931
53296
|
);
|
|
52932
53297
|
}
|
|
52933
|
-
const
|
|
52934
|
-
|
|
53298
|
+
const code = await spawnRealBinary(adapter7, installArgs);
|
|
53299
|
+
emitWrapperJson(config, {
|
|
52935
53300
|
ecosystem: adapter7.ecosystem,
|
|
52936
53301
|
packages: [],
|
|
52937
53302
|
scanVerdict: "scan_failed",
|
|
52938
53303
|
installRan: true,
|
|
52939
|
-
installExitCode:
|
|
53304
|
+
installExitCode: code,
|
|
52940
53305
|
error: { code: "scan_failed", message: err.message }
|
|
52941
53306
|
});
|
|
52942
|
-
return
|
|
53307
|
+
return code;
|
|
52943
53308
|
}
|
|
52944
53309
|
const allowlist = loadAllowlist(process.cwd());
|
|
52945
53310
|
const { result: filteredResult, suppressedCount } = applyAllowlist(allowlist, result, adapter7.apiKind);
|
|
52946
53311
|
result = filteredResult;
|
|
52947
53312
|
const topLevelNames = new Set(resolved.map((p) => p.name));
|
|
52948
|
-
|
|
52949
|
-
|
|
52950
|
-
|
|
52951
|
-
|
|
52952
|
-
|
|
52953
|
-
|
|
53313
|
+
const verdict = verdictFromResult(result);
|
|
53314
|
+
const decision = routeVerdict({
|
|
53315
|
+
verdict,
|
|
53316
|
+
mode: config.mode,
|
|
53317
|
+
strict: config.strict,
|
|
53318
|
+
dgForce: parsed.dgForce
|
|
53319
|
+
});
|
|
53320
|
+
const ctx = {
|
|
53321
|
+
ecosystem: adapter7.ecosystem,
|
|
53322
|
+
apiKind: adapter7.apiKind,
|
|
53323
|
+
installArgs,
|
|
53324
|
+
passthroughArgs: parsed.rawArgs,
|
|
53325
|
+
result,
|
|
53326
|
+
resolved,
|
|
53327
|
+
suppressedCount,
|
|
53328
|
+
dgForceReason: parsed.dgForceReason,
|
|
53329
|
+
error: verdict === "analysis_incomplete" && decision.outcome === "refuse" ? { code: "analysis_incomplete", message: "scanner could not fully analyze the install set" } : void 0
|
|
53330
|
+
};
|
|
53331
|
+
const presenter = {
|
|
53332
|
+
announce(d) {
|
|
53333
|
+
switch (d.verdict) {
|
|
53334
|
+
case "pass": {
|
|
53335
|
+
if (config.json || config.quiet) return;
|
|
53336
|
+
const topLevel = resolved.map((p) => `${p.name} ${p.version}`);
|
|
53337
|
+
const passLine = topLevel.length === 1 ? ` ${import_chalk19.default.green("\u2713")} ${import_chalk19.default.bold("DG verified:")} ${topLevel[0]} is safe` : ` ${import_chalk19.default.green("\u2713")} ${import_chalk19.default.bold("DG verified:")} ${topLevel.length} packages safe`;
|
|
53338
|
+
const installLine = topLevel.length === 1 ? ` ${import_chalk19.default.green("\u2713")} Installing ${topLevel[0]}` : ` ${import_chalk19.default.green("\u2713")} Installing ${topLevel.join(", ")}`;
|
|
53339
|
+
process.stderr.write(`${passLine}
|
|
52954
53340
|
${installLine}
|
|
52955
53341
|
`);
|
|
52956
|
-
|
|
52957
|
-
|
|
53342
|
+
if (suppressedCount > 0) {
|
|
53343
|
+
process.stderr.write(import_chalk19.default.dim(` (${suppressedCount} finding${suppressedCount === 1 ? "" : "s"} suppressed by .dg-allowlist.json)
|
|
52958
53344
|
`));
|
|
52959
|
-
|
|
52960
|
-
|
|
52961
|
-
|
|
52962
|
-
|
|
52963
|
-
|
|
52964
|
-
|
|
52965
|
-
|
|
52966
|
-
|
|
52967
|
-
installRan: true,
|
|
52968
|
-
installExitCode: code2,
|
|
52969
|
-
suppressedByAllowlist: suppressedCount > 0 ? suppressedCount : void 0
|
|
52970
|
-
});
|
|
52971
|
-
return code2;
|
|
52972
|
-
}
|
|
52973
|
-
if (result.action === "warn") {
|
|
52974
|
-
if (!config.json && !config.quiet) {
|
|
52975
|
-
const topLevelList = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
|
|
52976
|
-
process.stderr.write(` ${import_chalk19.default.yellow("\u26A0")} ${import_chalk19.default.bold("DG flagged")} ${topLevelList}.
|
|
53345
|
+
}
|
|
53346
|
+
process.stderr.write("\n");
|
|
53347
|
+
return;
|
|
53348
|
+
}
|
|
53349
|
+
case "warn": {
|
|
53350
|
+
if (config.json || config.quiet) return;
|
|
53351
|
+
const topLevelList = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
|
|
53352
|
+
process.stderr.write(` ${import_chalk19.default.yellow("\u26A0")} ${import_chalk19.default.bold("DG flagged")} ${topLevelList}.
|
|
52977
53353
|
`);
|
|
52978
|
-
|
|
52979
|
-
|
|
52980
|
-
|
|
52981
|
-
|
|
52982
|
-
|
|
53354
|
+
const flaggedPkgs = result.packages.filter((p) => derivePackageActionPublic(p) === "warn");
|
|
53355
|
+
for (const p of flaggedPkgs.slice(0, 5)) {
|
|
53356
|
+
if (p.findings && p.findings.length > 0) {
|
|
53357
|
+
for (const f of p.findings.slice(0, 3)) {
|
|
53358
|
+
process.stderr.write(import_chalk19.default.dim(` \u2022 ${f.title ?? "finding"}
|
|
53359
|
+
`));
|
|
53360
|
+
}
|
|
53361
|
+
}
|
|
53362
|
+
}
|
|
53363
|
+
if (suppressedCount > 0) {
|
|
53364
|
+
process.stderr.write(import_chalk19.default.dim(` (${suppressedCount} additional finding${suppressedCount === 1 ? "" : "s"} suppressed by .dg-allowlist.json)
|
|
52983
53365
|
`));
|
|
52984
53366
|
}
|
|
53367
|
+
return;
|
|
52985
53368
|
}
|
|
52986
|
-
|
|
52987
|
-
|
|
52988
|
-
|
|
53369
|
+
case "block": {
|
|
53370
|
+
if (d.outcome === "install") {
|
|
53371
|
+
if (!config.json && !config.quiet) {
|
|
53372
|
+
process.stderr.write(import_chalk19.default.yellow.bold(` --dg-force: bypassing block. Install at your own risk.
|
|
53373
|
+
|
|
52989
53374
|
`));
|
|
53375
|
+
}
|
|
53376
|
+
} else if (!config.json) {
|
|
53377
|
+
const blockedList = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
|
|
53378
|
+
process.stderr.write(
|
|
53379
|
+
` ${import_chalk19.default.red("\u2717")} ${import_chalk19.default.bold("DG blocked")} ${blockedList}.
|
|
53380
|
+
Real install was NOT run. To override:
|
|
53381
|
+
` + import_chalk19.default.dim(` ${adapter7.realBinaryName} ${parsed.rawArgs.join(" ")} --dg-force --dg-force-reason="<reason>"
|
|
53382
|
+
|
|
53383
|
+
`)
|
|
53384
|
+
);
|
|
53385
|
+
}
|
|
53386
|
+
return;
|
|
53387
|
+
}
|
|
53388
|
+
case "analysis_incomplete": {
|
|
53389
|
+
const list = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
|
|
53390
|
+
if (d.outcome === "refuse") {
|
|
53391
|
+
if (!config.json) {
|
|
53392
|
+
process.stderr.write(
|
|
53393
|
+
` ${import_chalk19.default.red("\u2717")} ${import_chalk19.default.bold("DG could not verify")} ${list} \u2014 analysis incomplete.
|
|
53394
|
+
` + import_chalk19.default.dim(` --mode ${config.strict ? "strict" : "block"} \u21D2 refusing install (unverified is not safe). Use --mode warn or --dg-force to bypass.
|
|
53395
|
+
|
|
53396
|
+
`)
|
|
53397
|
+
);
|
|
53398
|
+
}
|
|
53399
|
+
} else if (!config.json && !config.quiet) {
|
|
53400
|
+
process.stderr.write(
|
|
53401
|
+
import_chalk19.default.yellow(` \u26A0 DG could not fully verify ${list} (analysis incomplete). Proceeding with install (mode=${config.mode}).
|
|
53402
|
+
`)
|
|
53403
|
+
);
|
|
53404
|
+
}
|
|
53405
|
+
return;
|
|
53406
|
+
}
|
|
53407
|
+
default:
|
|
53408
|
+
return;
|
|
53409
|
+
}
|
|
53410
|
+
},
|
|
53411
|
+
async confirmProceed() {
|
|
53412
|
+
if (!(process.stderr.isTTY && !process.env.CI && !config.json)) {
|
|
53413
|
+
if (!config.json && !config.quiet) process.stderr.write(import_chalk19.default.dim(" Proceeding (non-interactive).\n"));
|
|
53414
|
+
return true;
|
|
52990
53415
|
}
|
|
52991
|
-
}
|
|
52992
|
-
if (process.stderr.isTTY && !process.env.CI && !config.json) {
|
|
52993
53416
|
const { promptYesNo: promptYesNo2 } = await Promise.resolve().then(() => (init_prompt(), prompt_exports));
|
|
52994
53417
|
const proceed = await promptYesNo2({ defaultAnswer: "y", message: " Proceed?" });
|
|
52995
|
-
if (!proceed)
|
|
52996
|
-
|
|
52997
|
-
|
|
52998
|
-
|
|
52999
|
-
|
|
53000
|
-
scanVerdict: "warn",
|
|
53001
|
-
installRan: false,
|
|
53002
|
-
installExitCode: null
|
|
53003
|
-
});
|
|
53004
|
-
return 1;
|
|
53005
|
-
}
|
|
53006
|
-
} else if (!config.json && !config.quiet) {
|
|
53007
|
-
process.stderr.write(import_chalk19.default.dim(" Proceeding (non-interactive).\n"));
|
|
53008
|
-
}
|
|
53009
|
-
const code2 = await spawnRealBinary(adapter7, parsed.rawArgs);
|
|
53010
|
-
emitJson(config, {
|
|
53011
|
-
ecosystem: adapter7.ecosystem,
|
|
53012
|
-
packages: packagesFromResult(result, topLevelNames),
|
|
53013
|
-
scanVerdict: "warn",
|
|
53014
|
-
installRan: true,
|
|
53015
|
-
installExitCode: code2,
|
|
53016
|
-
suppressedByAllowlist: suppressedCount > 0 ? suppressedCount : void 0
|
|
53017
|
-
});
|
|
53018
|
-
return code2;
|
|
53019
|
-
}
|
|
53020
|
-
if (result.action === "block") {
|
|
53021
|
-
if (parsed.dgForce) {
|
|
53418
|
+
if (!proceed) process.stderr.write(import_chalk19.default.dim(" Install cancelled by user.\n\n"));
|
|
53419
|
+
return proceed;
|
|
53420
|
+
},
|
|
53421
|
+
runInstall: (args2) => spawnRealBinary(adapter7, args2),
|
|
53422
|
+
async audit(kind) {
|
|
53022
53423
|
try {
|
|
53023
53424
|
await dispatchInstallAudit({
|
|
53024
53425
|
ecosystem: adapter7.apiKind,
|
|
53025
53426
|
packages: result.packages,
|
|
53026
|
-
decisionAction:
|
|
53027
|
-
bypassed:
|
|
53028
|
-
bypassReason: parsed.dgForceReason
|
|
53427
|
+
decisionAction: kind,
|
|
53428
|
+
bypassed: kind === "override",
|
|
53429
|
+
bypassReason: kind === "override" ? parsed.dgForceReason : void 0
|
|
53029
53430
|
});
|
|
53030
53431
|
} catch {
|
|
53031
53432
|
}
|
|
53032
|
-
|
|
53033
|
-
|
|
53034
|
-
|
|
53035
|
-
`));
|
|
53036
|
-
}
|
|
53037
|
-
const code2 = await spawnRealBinary(adapter7, parsed.rawArgs);
|
|
53038
|
-
emitJson(config, {
|
|
53433
|
+
},
|
|
53434
|
+
emit(record) {
|
|
53435
|
+
emitWrapperJson(config, {
|
|
53039
53436
|
ecosystem: adapter7.ecosystem,
|
|
53040
53437
|
packages: packagesFromResult(result, topLevelNames),
|
|
53041
|
-
scanVerdict:
|
|
53042
|
-
installRan:
|
|
53043
|
-
installExitCode:
|
|
53438
|
+
scanVerdict: record.scanVerdict,
|
|
53439
|
+
installRan: record.installRan,
|
|
53440
|
+
installExitCode: record.installExitCode,
|
|
53441
|
+
error: record.error,
|
|
53442
|
+
suppressedByAllowlist: record.suppressedByAllowlist
|
|
53044
53443
|
});
|
|
53045
|
-
return code2;
|
|
53046
53444
|
}
|
|
53047
|
-
|
|
53048
|
-
|
|
53049
|
-
ecosystem: adapter7.apiKind,
|
|
53050
|
-
packages: result.packages,
|
|
53051
|
-
decisionAction: "block",
|
|
53052
|
-
bypassed: false
|
|
53053
|
-
});
|
|
53054
|
-
} catch {
|
|
53055
|
-
}
|
|
53056
|
-
const blockedList = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
|
|
53057
|
-
if (!config.json) {
|
|
53058
|
-
process.stderr.write(
|
|
53059
|
-
` ${import_chalk19.default.red("\u2717")} ${import_chalk19.default.bold("DG blocked")} ${blockedList}.
|
|
53060
|
-
Real install was NOT run. To override:
|
|
53061
|
-
` + import_chalk19.default.dim(` ${adapter7.realBinaryName} ${parsed.rawArgs.join(" ")} --dg-force --dg-force-reason="<reason>"
|
|
53062
|
-
|
|
53063
|
-
`)
|
|
53064
|
-
);
|
|
53065
|
-
}
|
|
53066
|
-
emitJson(config, {
|
|
53067
|
-
ecosystem: adapter7.ecosystem,
|
|
53068
|
-
packages: packagesFromResult(result, topLevelNames),
|
|
53069
|
-
scanVerdict: "block",
|
|
53070
|
-
installRan: false,
|
|
53071
|
-
installExitCode: null
|
|
53072
|
-
});
|
|
53073
|
-
return 2;
|
|
53074
|
-
}
|
|
53075
|
-
const code = await spawnRealBinary(adapter7, parsed.rawArgs);
|
|
53076
|
-
emitJson(config, {
|
|
53077
|
-
ecosystem: adapter7.ecosystem,
|
|
53078
|
-
packages: packagesFromResult(result, topLevelNames),
|
|
53079
|
-
scanVerdict: "skipped",
|
|
53080
|
-
installRan: true,
|
|
53081
|
-
installExitCode: code
|
|
53082
|
-
});
|
|
53083
|
-
return code;
|
|
53445
|
+
};
|
|
53446
|
+
return await executeDecision(decision, ctx, presenter);
|
|
53084
53447
|
}
|
|
53085
53448
|
var import_chalk19;
|
|
53086
53449
|
var init_wrapper_factory = __esm({
|
|
@@ -53092,6 +53455,12 @@ var init_wrapper_factory = __esm({
|
|
|
53092
53455
|
init_install();
|
|
53093
53456
|
init_audit_dispatcher();
|
|
53094
53457
|
init_allowlist();
|
|
53458
|
+
init_wrapper_shared();
|
|
53459
|
+
init_npm_wrapper();
|
|
53460
|
+
init_pip_wrapper();
|
|
53461
|
+
init_route();
|
|
53462
|
+
init_run();
|
|
53463
|
+
init_json();
|
|
53095
53464
|
}
|
|
53096
53465
|
});
|
|
53097
53466
|
|
|
@@ -53312,7 +53681,7 @@ async function main() {
|
|
|
53312
53681
|
const v = args[ecoArgIdx + 1];
|
|
53313
53682
|
if (v === "npm" || v === "pypi") ecosystem = v;
|
|
53314
53683
|
}
|
|
53315
|
-
const { runNpmPublishCheck: runNpmPublishCheck2, runPypiPublishCheck: runPypiPublishCheck2, renderPublishCheckResult: renderPublishCheckResult2 } = await Promise.resolve().then(() => (init_publish_check(), publish_check_exports));
|
|
53684
|
+
const { runNpmPublishCheck: runNpmPublishCheck2, runPypiPublishCheck: runPypiPublishCheck2, renderPublishCheckResult: renderPublishCheckResult2, publishCheckExitCode: publishCheckExitCode2 } = await Promise.resolve().then(() => (init_publish_check(), publish_check_exports));
|
|
53316
53685
|
const { existsSync: existsSync25 } = await import("node:fs");
|
|
53317
53686
|
const { join: join15 } = await import("node:path");
|
|
53318
53687
|
if (ecosystem === "auto") {
|
|
@@ -53342,7 +53711,7 @@ async function main() {
|
|
|
53342
53711
|
} else {
|
|
53343
53712
|
process.stderr.write(renderPublishCheckResult2(result));
|
|
53344
53713
|
}
|
|
53345
|
-
if (result.action === "block"
|
|
53714
|
+
if (result.action === "block") {
|
|
53346
53715
|
try {
|
|
53347
53716
|
const reasonIdx = args.indexOf("--dg-force-reason");
|
|
53348
53717
|
const bypassReason = reasonIdx >= 0 ? args[reasonIdx + 1] : void 0;
|
|
@@ -53362,9 +53731,7 @@ async function main() {
|
|
|
53362
53731
|
} catch {
|
|
53363
53732
|
}
|
|
53364
53733
|
}
|
|
53365
|
-
|
|
53366
|
-
if (result.action === "analysis_incomplete") process.exit(4);
|
|
53367
|
-
process.exit(0);
|
|
53734
|
+
process.exit(publishCheckExitCode2(result.action, force));
|
|
53368
53735
|
}
|
|
53369
53736
|
if (rawCommand === "hook") {
|
|
53370
53737
|
const { handleHookCommand: handleHookCommand2 } = await Promise.resolve().then(() => (init_hook(), hook_exports));
|
|
@@ -53568,10 +53935,8 @@ async function handleWrapInternal(argv) {
|
|
|
53568
53935
|
const ecoTyped = ecosystem;
|
|
53569
53936
|
const spawnReal = async (real, args) => {
|
|
53570
53937
|
const { spawn: spawn7 } = await import("node:child_process");
|
|
53571
|
-
const {
|
|
53572
|
-
const
|
|
53573
|
-
const env3 = nonce ? { ...process.env, DG_SHIM_ACTIVE: nonce } : { ...process.env };
|
|
53574
|
-
const child = spawn7(real, args, { stdio: "inherit", env: env3 });
|
|
53938
|
+
const { childInstallEnv: childInstallEnv2 } = await Promise.resolve().then(() => (init_install(), install_exports));
|
|
53939
|
+
const child = spawn7(real, args, { stdio: "inherit", env: childInstallEnv2() });
|
|
53575
53940
|
return await new Promise((resolve3) => {
|
|
53576
53941
|
child.on("close", (code) => resolve3(code ?? 1));
|
|
53577
53942
|
child.on("error", () => resolve3(1));
|
|
@@ -53621,7 +53986,7 @@ async function handleWrapInternal(argv) {
|
|
|
53621
53986
|
}
|
|
53622
53987
|
if (ecosystem === "conda" || ecosystem === "mamba") {
|
|
53623
53988
|
const { runStaticConda: runStaticConda2 } = await Promise.resolve().then(() => (init_conda_wrapper(), conda_wrapper_exports));
|
|
53624
|
-
return await runStaticConda2(wrapperArgs);
|
|
53989
|
+
return await runStaticConda2(wrapperArgs, ecosystem, config);
|
|
53625
53990
|
}
|
|
53626
53991
|
const adapterImports = {
|
|
53627
53992
|
pnpm: () => Promise.resolve().then(() => (init_pnpm_wrapper(), pnpm_wrapper_exports)),
|