skalpel 4.0.21 → 4.0.23
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/package.json +1 -1
- package/stats.mjs +2 -3
- package/verify-shadow.mjs +12 -1
package/package.json
CHANGED
package/stats.mjs
CHANGED
|
@@ -63,9 +63,8 @@ for (const ev of Object.keys(counts)) {
|
|
|
63
63
|
}
|
|
64
64
|
const L = lat[ev] || [];
|
|
65
65
|
if (L.length) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
);
|
|
66
|
+
const maxMs = L.reduce((a, b) => (b > a ? b : a), -Infinity);
|
|
67
|
+
console.log(` latency p50=${pct(L, 50)}ms p95=${pct(L, 95)}ms max=${maxMs}ms`);
|
|
69
68
|
}
|
|
70
69
|
console.log(
|
|
71
70
|
` → inject rate ${((100 * ok) / n).toFixed(1)}% cold-abort rate ${((100 * cold) / n).toFixed(1)}%\n`,
|
package/verify-shadow.mjs
CHANGED
|
@@ -139,7 +139,14 @@ function pmPositionals(args) {
|
|
|
139
139
|
return pos;
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
+
// SHARP-5: `--node-options` (npm/pnpm/yarn config flag) is passed through to the lifecycle script's
|
|
143
|
+
// node as NODE_OPTIONS, so `--node-options=--require <any>.js` loads attacker JS before the test runs —
|
|
144
|
+
// arbitrary code execution, exactly the SHARP-2 class but via the PM itself. shell:false does NOT help
|
|
145
|
+
// (the PM applies the flag). Refuse the whole invocation if it appears, in any `=`/space form.
|
|
146
|
+
const NODE_OPTIONS_FLAG = /^--node-options(=|$)/;
|
|
147
|
+
|
|
142
148
|
function validatePM(base, args) {
|
|
149
|
+
if (args.some((x) => NODE_OPTIONS_FLAG.test(x))) return false; // SHARP-5
|
|
143
150
|
const pos = pmPositionals(args);
|
|
144
151
|
if (!pos.length) return false;
|
|
145
152
|
const p0 = pos[0];
|
|
@@ -161,6 +168,7 @@ function validateNPX(args) {
|
|
|
161
168
|
// plain `npx <allowed-tool> [value-less flags]` is a proof.
|
|
162
169
|
for (const a of args) {
|
|
163
170
|
if (/^(-p|--package|-c|--call)(=|$)/.test(a)) return false;
|
|
171
|
+
if (NODE_OPTIONS_FLAG.test(a)) return false; // SHARP-5: npx also forwards --node-options → NODE_OPTIONS
|
|
164
172
|
}
|
|
165
173
|
for (let i = 0; i < args.length; i++) {
|
|
166
174
|
const a = args[i];
|
|
@@ -482,7 +490,10 @@ export function rerunProof({ cmd, args, cwd }) {
|
|
|
482
490
|
maxBuffer: MAX_OUTPUT_BYTES,
|
|
483
491
|
windowsHide: true,
|
|
484
492
|
shell: false, // RED LINE: never a shell
|
|
485
|
-
|
|
493
|
+
// SHARP-5 (defense in depth): neutralize NODE_OPTIONS so neither a `--node-options` flag the
|
|
494
|
+
// allowlist somehow let through, nor an inherited NODE_OPTIONS in the parent env, can inject a
|
|
495
|
+
// `--require <attacker>.js` into the proof tool's node process.
|
|
496
|
+
env: { ...process.env, NODE_OPTIONS: "" },
|
|
486
497
|
},
|
|
487
498
|
(err, stdout, stderr) => {
|
|
488
499
|
const tail = (String(stdout || "") + String(stderr || "")).replace(/\s+$/, "");
|