@orygn/opa-mcp 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +583 -4
- package/README.md +144 -98
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +9 -3
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +14 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +91 -19
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +1 -6
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +17 -3
- package/dist/constants.js.map +1 -1
- package/dist/lib/bundle-signatures.d.ts +23 -0
- package/dist/lib/bundle-signatures.d.ts.map +1 -0
- package/dist/lib/bundle-signatures.js +152 -0
- package/dist/lib/bundle-signatures.js.map +1 -0
- package/dist/lib/child-env.d.ts +9 -2
- package/dist/lib/child-env.d.ts.map +1 -1
- package/dist/lib/child-env.js +38 -6
- package/dist/lib/child-env.js.map +1 -1
- package/dist/lib/conftest-cli.d.ts +25 -10
- package/dist/lib/conftest-cli.d.ts.map +1 -1
- package/dist/lib/conftest-cli.js +233 -50
- package/dist/lib/conftest-cli.js.map +1 -1
- package/dist/lib/errors.d.ts +4 -5
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +15 -3
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/inline-paths.d.ts +37 -0
- package/dist/lib/inline-paths.d.ts.map +1 -0
- package/dist/lib/inline-paths.js +162 -0
- package/dist/lib/inline-paths.js.map +1 -0
- package/dist/lib/install-id.d.ts.map +1 -1
- package/dist/lib/install-id.js +18 -3
- package/dist/lib/install-id.js.map +1 -1
- package/dist/lib/json-stream.d.ts +26 -0
- package/dist/lib/json-stream.d.ts.map +1 -0
- package/dist/lib/json-stream.js +69 -0
- package/dist/lib/json-stream.js.map +1 -0
- package/dist/lib/opa-cli.d.ts +74 -16
- package/dist/lib/opa-cli.d.ts.map +1 -1
- package/dist/lib/opa-cli.js +107 -30
- package/dist/lib/opa-cli.js.map +1 -1
- package/dist/lib/opa-client.d.ts +27 -1
- package/dist/lib/opa-client.d.ts.map +1 -1
- package/dist/lib/opa-client.js +98 -14
- package/dist/lib/opa-client.js.map +1 -1
- package/dist/lib/opa-paths.d.ts +34 -0
- package/dist/lib/opa-paths.d.ts.map +1 -0
- package/dist/lib/opa-paths.js +101 -0
- package/dist/lib/opa-paths.js.map +1 -0
- package/dist/lib/output.d.ts.map +1 -1
- package/dist/lib/output.js +83 -10
- package/dist/lib/output.js.map +1 -1
- package/dist/lib/regal-cli.d.ts +16 -1
- package/dist/lib/regal-cli.d.ts.map +1 -1
- package/dist/lib/regal-cli.js +40 -6
- package/dist/lib/regal-cli.js.map +1 -1
- package/dist/lib/rego-ast-walker.d.ts +0 -6
- package/dist/lib/rego-ast-walker.d.ts.map +1 -1
- package/dist/lib/rego-ast-walker.js +181 -55
- package/dist/lib/rego-ast-walker.js.map +1 -1
- package/dist/lib/rego-counterexample.d.ts +15 -2
- package/dist/lib/rego-counterexample.d.ts.map +1 -1
- package/dist/lib/rego-counterexample.js +63 -15
- package/dist/lib/rego-counterexample.js.map +1 -1
- package/dist/lib/rego-input-path.d.ts +20 -0
- package/dist/lib/rego-input-path.d.ts.map +1 -0
- package/dist/lib/rego-input-path.js +70 -0
- package/dist/lib/rego-input-path.js.map +1 -0
- package/dist/lib/rego-ir.d.ts +34 -3
- package/dist/lib/rego-ir.d.ts.map +1 -1
- package/dist/lib/rego-smt-encoder.d.ts +88 -5
- package/dist/lib/rego-smt-encoder.d.ts.map +1 -1
- package/dist/lib/rego-smt-encoder.js +270 -31
- package/dist/lib/rego-smt-encoder.js.map +1 -1
- package/dist/lib/rego-type-inferencer.d.ts +27 -2
- package/dist/lib/rego-type-inferencer.d.ts.map +1 -1
- package/dist/lib/rego-type-inferencer.js +71 -3
- package/dist/lib/rego-type-inferencer.js.map +1 -1
- package/dist/lib/rego-verify-engine.d.ts.map +1 -1
- package/dist/lib/rego-verify-engine.js +203 -90
- package/dist/lib/rego-verify-engine.js.map +1 -1
- package/dist/lib/rego-z3.d.ts +66 -0
- package/dist/lib/rego-z3.d.ts.map +1 -1
- package/dist/lib/rego-z3.js +312 -5
- package/dist/lib/rego-z3.js.map +1 -1
- package/dist/lib/security.d.ts +8 -0
- package/dist/lib/security.d.ts.map +1 -1
- package/dist/lib/security.js +130 -54
- package/dist/lib/security.js.map +1 -1
- package/dist/lib/subprocess.d.ts +13 -0
- package/dist/lib/subprocess.d.ts.map +1 -1
- package/dist/lib/subprocess.js +153 -18
- package/dist/lib/subprocess.js.map +1 -1
- package/dist/lib/tool-helpers.d.ts +12 -25
- package/dist/lib/tool-helpers.d.ts.map +1 -1
- package/dist/lib/tool-helpers.js +66 -40
- package/dist/lib/tool-helpers.js.map +1 -1
- package/dist/prompts/index.js +2 -2
- package/dist/resources/index.js +1 -1
- package/dist/resources/index.js.map +1 -1
- package/dist/resources/patterns.d.ts +1 -1
- package/dist/resources/patterns.d.ts.map +1 -1
- package/dist/resources/patterns.js +42 -15
- package/dist/resources/patterns.js.map +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +50 -7
- package/dist/server.js.map +1 -1
- package/dist/tools/authoring/capabilities.d.ts +4 -0
- package/dist/tools/authoring/capabilities.d.ts.map +1 -1
- package/dist/tools/authoring/capabilities.js +41 -4
- package/dist/tools/authoring/capabilities.js.map +1 -1
- package/dist/tools/authoring/check-schema.d.ts +6 -0
- package/dist/tools/authoring/check-schema.d.ts.map +1 -1
- package/dist/tools/authoring/check-schema.js +56 -3
- package/dist/tools/authoring/check-schema.js.map +1 -1
- package/dist/tools/authoring/format.d.ts.map +1 -1
- package/dist/tools/authoring/format.js +2 -2
- package/dist/tools/authoring/format.js.map +1 -1
- package/dist/tools/authoring/lint.d.ts.map +1 -1
- package/dist/tools/authoring/lint.js +8 -6
- package/dist/tools/authoring/lint.js.map +1 -1
- package/dist/tools/authoring/migrate-v1.d.ts.map +1 -1
- package/dist/tools/authoring/migrate-v1.js +20 -4
- package/dist/tools/authoring/migrate-v1.js.map +1 -1
- package/dist/tools/authoring/parse.d.ts.map +1 -1
- package/dist/tools/authoring/parse.js +3 -3
- package/dist/tools/authoring/parse.js.map +1 -1
- package/dist/tools/bundles/build.d.ts.map +1 -1
- package/dist/tools/bundles/build.js +12 -4
- package/dist/tools/bundles/build.js.map +1 -1
- package/dist/tools/bundles/sign.d.ts +9 -2
- package/dist/tools/bundles/sign.d.ts.map +1 -1
- package/dist/tools/bundles/sign.js +125 -19
- package/dist/tools/bundles/sign.js.map +1 -1
- package/dist/tools/bundles/verify.d.ts +1 -1
- package/dist/tools/bundles/verify.d.ts.map +1 -1
- package/dist/tools/bundles/verify.js +58 -19
- package/dist/tools/bundles/verify.js.map +1 -1
- package/dist/tools/conftest/index.d.ts +5 -0
- package/dist/tools/conftest/index.d.ts.map +1 -1
- package/dist/tools/conftest/index.js.map +1 -1
- package/dist/tools/conftest/pull.d.ts.map +1 -1
- package/dist/tools/conftest/pull.js +24 -10
- package/dist/tools/conftest/pull.js.map +1 -1
- package/dist/tools/conftest/push.d.ts.map +1 -1
- package/dist/tools/conftest/push.js +17 -7
- package/dist/tools/conftest/push.js.map +1 -1
- package/dist/tools/conftest/test.d.ts +10 -6
- package/dist/tools/conftest/test.d.ts.map +1 -1
- package/dist/tools/conftest/test.js +61 -39
- package/dist/tools/conftest/test.js.map +1 -1
- package/dist/tools/conftest/verify.d.ts +10 -6
- package/dist/tools/conftest/verify.d.ts.map +1 -1
- package/dist/tools/conftest/verify.js +40 -32
- package/dist/tools/conftest/verify.js.map +1 -1
- package/dist/tools/evaluation/_shared.js +9 -12
- package/dist/tools/evaluation/_shared.js.map +1 -1
- package/dist/tools/evaluation/bench.d.ts +29 -2
- package/dist/tools/evaluation/bench.d.ts.map +1 -1
- package/dist/tools/evaluation/bench.js +53 -9
- package/dist/tools/evaluation/bench.js.map +1 -1
- package/dist/tools/evaluation/compile.js +4 -4
- package/dist/tools/evaluation/compile.js.map +1 -1
- package/dist/tools/evaluation/eval.d.ts.map +1 -1
- package/dist/tools/evaluation/eval.js +12 -16
- package/dist/tools/evaluation/eval.js.map +1 -1
- package/dist/tools/evaluation/exec.d.ts +16 -0
- package/dist/tools/evaluation/exec.d.ts.map +1 -1
- package/dist/tools/evaluation/exec.js +38 -6
- package/dist/tools/evaluation/exec.js.map +1 -1
- package/dist/tools/evaluation/test-multiroot.d.ts +6 -0
- package/dist/tools/evaluation/test-multiroot.d.ts.map +1 -1
- package/dist/tools/evaluation/test-multiroot.js +35 -8
- package/dist/tools/evaluation/test-multiroot.js.map +1 -1
- package/dist/tools/evaluation/test.d.ts +45 -0
- package/dist/tools/evaluation/test.d.ts.map +1 -1
- package/dist/tools/evaluation/test.js +153 -32
- package/dist/tools/evaluation/test.js.map +1 -1
- package/dist/tools/helpers/coverage-gaps.d.ts +11 -3
- package/dist/tools/helpers/coverage-gaps.d.ts.map +1 -1
- package/dist/tools/helpers/coverage-gaps.js +7 -7
- package/dist/tools/helpers/coverage-gaps.js.map +1 -1
- package/dist/tools/helpers/describe-policy.d.ts.map +1 -1
- package/dist/tools/helpers/describe-policy.js +2 -2
- package/dist/tools/helpers/describe-policy.js.map +1 -1
- package/dist/tools/helpers/explain-decision.d.ts.map +1 -1
- package/dist/tools/helpers/explain-decision.js +3 -4
- package/dist/tools/helpers/explain-decision.js.map +1 -1
- package/dist/tools/helpers/explain-undefined.d.ts +9 -3
- package/dist/tools/helpers/explain-undefined.d.ts.map +1 -1
- package/dist/tools/helpers/explain-undefined.js +214 -73
- package/dist/tools/helpers/explain-undefined.js.map +1 -1
- package/dist/tools/helpers/fix.d.ts +11 -5
- package/dist/tools/helpers/fix.d.ts.map +1 -1
- package/dist/tools/helpers/fix.js +88 -45
- package/dist/tools/helpers/fix.js.map +1 -1
- package/dist/tools/helpers/generate-test-skeleton.d.ts.map +1 -1
- package/dist/tools/helpers/generate-test-skeleton.js +105 -21
- package/dist/tools/helpers/generate-test-skeleton.js.map +1 -1
- package/dist/tools/helpers/playground-share.d.ts +4 -2
- package/dist/tools/helpers/playground-share.d.ts.map +1 -1
- package/dist/tools/helpers/playground-share.js +13 -3
- package/dist/tools/helpers/playground-share.js.map +1 -1
- package/dist/tools/helpers/policy-diff.d.ts.map +1 -1
- package/dist/tools/helpers/policy-diff.js +3 -4
- package/dist/tools/helpers/policy-diff.js.map +1 -1
- package/dist/tools/helpers/security-audit.d.ts.map +1 -1
- package/dist/tools/helpers/security-audit.js +19 -19
- package/dist/tools/helpers/security-audit.js.map +1 -1
- package/dist/tools/helpers/verify.d.ts.map +1 -1
- package/dist/tools/helpers/verify.js +5 -1
- package/dist/tools/helpers/verify.js.map +1 -1
- package/dist/tools/meta/index.d.ts +1 -1
- package/dist/tools/server-management/_shared.d.ts +15 -4
- package/dist/tools/server-management/_shared.d.ts.map +1 -1
- package/dist/tools/server-management/_shared.js +86 -13
- package/dist/tools/server-management/_shared.js.map +1 -1
- package/dist/tools/server-management/data.d.ts.map +1 -1
- package/dist/tools/server-management/data.js +88 -23
- package/dist/tools/server-management/data.js.map +1 -1
- package/dist/tools/server-management/decisions.d.ts.map +1 -1
- package/dist/tools/server-management/decisions.js +16 -3
- package/dist/tools/server-management/decisions.js.map +1 -1
- package/dist/tools/server-management/policies.d.ts.map +1 -1
- package/dist/tools/server-management/policies.js +44 -7
- package/dist/tools/server-management/policies.js.map +1 -1
- package/dist/tools/server-management/status.d.ts.map +1 -1
- package/dist/tools/server-management/status.js +80 -13
- package/dist/tools/server-management/status.js.map +1 -1
- package/dist/types.d.ts +10 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -1
package/dist/lib/rego-z3.js
CHANGED
|
@@ -1,29 +1,336 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Z3 singleton initialization.
|
|
3
3
|
*
|
|
4
|
-
* The z3-solver WASM module takes ~500ms to load and
|
|
5
|
-
*
|
|
6
|
-
* same promise. Each verification call
|
|
7
|
-
* from the shared Context
|
|
4
|
+
* The z3-solver WASM module takes ~500ms to load and is initialized once,
|
|
5
|
+
* unless it faults, in which case a fresh one replaces it (see getZ3).
|
|
6
|
+
* Concurrent calls safely await the same promise. Each verification call
|
|
7
|
+
* creates its own fresh Solver from the shared Context and releases it, and
|
|
8
|
+
* its model, as it finishes; that is what keeps the heap bounded.
|
|
9
|
+
*
|
|
10
|
+
* A fresh Solver is NOT enough to make concurrent verification safe. The whole
|
|
11
|
+
* Context lives in one single-threaded WASM heap, and `check()` is async, so two
|
|
12
|
+
* overlapping solves interleave on that heap and corrupt each other: observed
|
|
13
|
+
* symptoms were verdicts degrading to `inconclusive` and an allocator crash
|
|
14
|
+
* inside the WASM module. Everything touching the Context must therefore run
|
|
15
|
+
* under `withZ3Lock`.
|
|
8
16
|
*/
|
|
17
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
9
18
|
import { init } from 'z3-solver';
|
|
19
|
+
/**
|
|
20
|
+
* Ceiling on Z3's own allocations, in megabytes. Reached, Z3 raises an
|
|
21
|
+
* ordinary exception that the engine turns into an inconclusive verdict.
|
|
22
|
+
* Without it the WASM heap itself runs out, and that abort surfaces outside
|
|
23
|
+
* every try/catch as an uncaughtException that ends the server.
|
|
24
|
+
*/
|
|
25
|
+
export const Z3_MEMORY_MAX_MB = 1024;
|
|
26
|
+
/**
|
|
27
|
+
* The solver's own bound, checked at its checkpoints, where running out
|
|
28
|
+
* degrades to an "unknown" answer. It sits well below the process ceiling on
|
|
29
|
+
* purpose: at the same value the allocator's exception won the race, and an
|
|
30
|
+
* allocation failing inside a destructor ends in an abort rather than an
|
|
31
|
+
* error. Measured in review: equal caps aborted four times in four; a lower
|
|
32
|
+
* solver bound answered "unknown" four times in four.
|
|
33
|
+
*/
|
|
34
|
+
export const Z3_SOLVER_MAX_MEMORY_MB = 768;
|
|
10
35
|
// Module-level singleton
|
|
11
36
|
let z3InitPromise = null;
|
|
37
|
+
let z3Api;
|
|
38
|
+
/** Set once Z3 has failed outside a try/catch; it is not trusted again. */
|
|
39
|
+
let z3Unusable;
|
|
40
|
+
/** Number of Z3 critical sections currently running (0 or 1). */
|
|
41
|
+
let z3Depth = 0;
|
|
42
|
+
/** Rejects the section in flight; set while one is running. */
|
|
43
|
+
let poisonInFlight;
|
|
44
|
+
/** Generation of the module in use; a finalizer from an earlier one is dropped. */
|
|
45
|
+
let z3Generation = 0;
|
|
46
|
+
/** Finalizers that arrived while a solve was running, to run once it is not. */
|
|
47
|
+
let deferredFinalizers = [];
|
|
48
|
+
/** Fresh modules this process may still bring up after a fault. */
|
|
49
|
+
let recoveriesLeft = 3;
|
|
50
|
+
/**
|
|
51
|
+
* The registry class this process started with, and the identity of each
|
|
52
|
+
* init along its own async chain: z3-solver builds its registry in the
|
|
53
|
+
* continuation after its WASM loads, so the store there names the init that
|
|
54
|
+
* owns it, however inits interleave.
|
|
55
|
+
*/
|
|
56
|
+
const NativeRegistry = globalThis.FinalizationRegistry;
|
|
57
|
+
const registryGlobal = globalThis;
|
|
58
|
+
const initInFlight = new AsyncLocalStorage();
|
|
59
|
+
/**
|
|
60
|
+
* Inits whose window is open; the global goes back when the last closes. An
|
|
61
|
+
* init that never settles leaves it on the subclass, which behaves natively
|
|
62
|
+
* for everything off an init's chain: only the class identity differs.
|
|
63
|
+
*/
|
|
64
|
+
let initWindows = 0;
|
|
65
|
+
/**
|
|
66
|
+
* The stack at the call, with enough frames kept to reach the caller's module
|
|
67
|
+
* whatever `Error.stackTraceLimit` the host has chosen: a limit of zero, a
|
|
68
|
+
* common speed setting, would otherwise leave nothing to read and the wrap
|
|
69
|
+
* would quietly not happen.
|
|
70
|
+
*/
|
|
71
|
+
function stackHere() {
|
|
72
|
+
const limit = Error.stackTraceLimit;
|
|
73
|
+
Error.stackTraceLimit = 20;
|
|
74
|
+
try {
|
|
75
|
+
return new Error().stack ?? '';
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
Error.stackTraceLimit = limit;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The registry z3-solver gets while an init runs.
|
|
83
|
+
*
|
|
84
|
+
* z3-solver frees every AST, solver and model from one FinalizationRegistry,
|
|
85
|
+
* built inside its createApi, whose callbacks run on the main thread whenever
|
|
86
|
+
* the collector gets to them. A solve runs on a worker over the same shared
|
|
87
|
+
* memory, and a callback landing mid-solve raced it on Z3's allocator and
|
|
88
|
+
* faulted the heap (measured: a collection forced mid-solve crashed inside a
|
|
89
|
+
* hundred solves; the same collection while the worker was idle ran 1500
|
|
90
|
+
* clean). So a finalizer that arrives while a section is open waits for the
|
|
91
|
+
* section to close, and one from a module that has since faulted is dropped.
|
|
92
|
+
*
|
|
93
|
+
* Each construction looks at its own stack and async context: one from
|
|
94
|
+
* z3-solver on an init's chain is wrapped with that init's generation; any
|
|
95
|
+
* other gets the real behaviour. Inits can overlap, since a recovery starts
|
|
96
|
+
* the next while the one given up on is still coming up, and each still
|
|
97
|
+
* gets its own generation: the frees of the abandoned module are dropped
|
|
98
|
+
* and the recovered module's are routed.
|
|
99
|
+
*
|
|
100
|
+
* Releasing the solver and model as each solve ends removes most of the
|
|
101
|
+
* finalizer traffic that made the race reachable; the deferral covers what
|
|
102
|
+
* a collection still frees.
|
|
103
|
+
*/
|
|
104
|
+
class DeferringRegistry extends NativeRegistry {
|
|
105
|
+
constructor(callback) {
|
|
106
|
+
const owner = initInFlight.getStore();
|
|
107
|
+
const mine = owner !== undefined && stackHere().includes('z3-solver') ? owner : undefined;
|
|
108
|
+
const generation = mine?.generation;
|
|
109
|
+
super(mine === undefined
|
|
110
|
+
? callback
|
|
111
|
+
: (held) => {
|
|
112
|
+
if (generation !== z3Generation)
|
|
113
|
+
return;
|
|
114
|
+
if (z3Depth > 0)
|
|
115
|
+
deferredFinalizers.push(() => callback(held));
|
|
116
|
+
else
|
|
117
|
+
callback(held);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/** Bring up z3-solver with its finalizers routed through this module. */
|
|
122
|
+
async function initModule() {
|
|
123
|
+
initWindows++;
|
|
124
|
+
registryGlobal.FinalizationRegistry = DeferringRegistry;
|
|
125
|
+
try {
|
|
126
|
+
return await initInFlight.run({ generation: z3Generation }, () => init());
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
if (--initWindows === 0)
|
|
130
|
+
registryGlobal.FinalizationRegistry = NativeRegistry;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Run the finalizers held back during a solve; only called with the worker
|
|
135
|
+
* idle. Each is a dec_ref; one that throws must not take the rest, or the
|
|
136
|
+
* lock, with it.
|
|
137
|
+
*/
|
|
138
|
+
function runDeferredFinalizers() {
|
|
139
|
+
const run = deferredFinalizers;
|
|
140
|
+
deferredFinalizers = [];
|
|
141
|
+
for (const finalizer of run) {
|
|
142
|
+
try {
|
|
143
|
+
finalizer();
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// A free that fails leaks one object; the section still closes.
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
12
150
|
/**
|
|
13
151
|
* Return the shared Z3 Context, initializing WASM on first call.
|
|
14
152
|
* Safe to call from concurrent async paths.
|
|
15
153
|
*/
|
|
16
154
|
export async function getZ3() {
|
|
155
|
+
if (z3Unusable !== undefined) {
|
|
156
|
+
if (recoveriesLeft === 0) {
|
|
157
|
+
throw new Error(`Z3 is unavailable in this process after repeated failures (${z3Unusable}). Restart the server to verify again.`);
|
|
158
|
+
}
|
|
159
|
+
// The heap that faulted cannot be trusted, so bring up a fresh module.
|
|
160
|
+
// Every init() is a new WASM instance with its own memory and worker
|
|
161
|
+
// (measured: two live side by side, independent, ~100 ms each), so
|
|
162
|
+
// nothing is shared with the one that faulted; its finalizers were
|
|
163
|
+
// dropped by generation when it was given up on. The faulted instance
|
|
164
|
+
// is retained, about 30 MB and one worker each, which is why the number
|
|
165
|
+
// of recoveries is bounded for the life of the process.
|
|
166
|
+
recoveriesLeft--;
|
|
167
|
+
z3Unusable = undefined;
|
|
168
|
+
z3InitPromise = null;
|
|
169
|
+
z3Api = undefined;
|
|
170
|
+
}
|
|
17
171
|
if (z3InitPromise === null) {
|
|
18
|
-
|
|
172
|
+
const started = initModule().then((api) => {
|
|
173
|
+
// An init a recovery superseded while it was coming up must not
|
|
174
|
+
// become the module in use; whoever was waiting on it is told.
|
|
175
|
+
if (z3InitPromise !== started)
|
|
176
|
+
throw new Error('Z3 init superseded by a recovery');
|
|
177
|
+
api.setParam('memory_max_size', Z3_MEMORY_MAX_MB);
|
|
178
|
+
z3Api = api;
|
|
179
|
+
return api.Context('main');
|
|
180
|
+
});
|
|
181
|
+
z3InitPromise = started;
|
|
19
182
|
}
|
|
20
183
|
return z3InitPromise;
|
|
21
184
|
}
|
|
185
|
+
/** Read back a Z3 global parameter, after initialisation. */
|
|
186
|
+
export async function getZ3Param(name) {
|
|
187
|
+
await getZ3();
|
|
188
|
+
return z3Api?.getParam(name) ?? null;
|
|
189
|
+
}
|
|
190
|
+
/** Whether a Z3 critical section is running right now. */
|
|
191
|
+
export function isZ3Busy() {
|
|
192
|
+
return z3Depth > 0;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Give up on the Z3 module in use. Called when it failed outside a try/catch:
|
|
196
|
+
* the heap it lives in cannot be trusted. The next call brings up a fresh
|
|
197
|
+
* module, a bounded number of times per process.
|
|
198
|
+
*/
|
|
199
|
+
export function markZ3Unusable(reason) {
|
|
200
|
+
z3Unusable = reason;
|
|
201
|
+
// Move the generation now, before anything unwinds: the poison below ends
|
|
202
|
+
// the section, whose close would otherwise run every deferred free into
|
|
203
|
+
// the heap that just faulted, and any finalizer that arrives later from
|
|
204
|
+
// this module must be dropped rather than run.
|
|
205
|
+
z3Generation++;
|
|
206
|
+
deferredFinalizers = [];
|
|
207
|
+
// A heap abort arrives from the WASM worker and leaves the solve's promise
|
|
208
|
+
// unsettled for good. Settle it here, so the section releases the lock and
|
|
209
|
+
// the calls queued behind it are answered instead of hanging.
|
|
210
|
+
poisonInFlight?.(new Error(`Z3 became unusable during the solve (${reason}).`));
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Whether an error message is one of the two this module produces once Z3
|
|
214
|
+
* has been given up on. The engine passes such a message through to the
|
|
215
|
+
* caller verbatim, since a restart is the one thing they can do about it.
|
|
216
|
+
*/
|
|
217
|
+
export function isZ3UnavailableMessage(detail) {
|
|
218
|
+
return /Z3 (is unavailable|became unusable)/.test(detail);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Whether a failure is the solve in flight being cut short by a fault, which
|
|
222
|
+
* a fresh module can answer: the engine retries such a call once.
|
|
223
|
+
*/
|
|
224
|
+
export function isZ3RecoverableMessage(detail) {
|
|
225
|
+
return /Z3 became unusable during the solve/.test(detail);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* How many fresh modules this process may still bring up after a fault.
|
|
229
|
+
* Three for the life of the process, however far apart the faults: each
|
|
230
|
+
* retained instance costs memory, and a fourth fault is a pattern to
|
|
231
|
+
* restart out of, not to ride.
|
|
232
|
+
*/
|
|
233
|
+
export function z3RecoveriesLeft() {
|
|
234
|
+
return recoveriesLeft;
|
|
235
|
+
}
|
|
236
|
+
/** For tests: how many finalizers are waiting for the open section to close. */
|
|
237
|
+
export function deferredFinalizersForTesting() {
|
|
238
|
+
return deferredFinalizers.length;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* For tests: what z3-solver's finalizers go through. Runs at once when no
|
|
242
|
+
* section is open, otherwise once the open one closes.
|
|
243
|
+
*/
|
|
244
|
+
export function enqueueFinalizerForTesting(finalizer) {
|
|
245
|
+
if (z3Depth > 0)
|
|
246
|
+
deferredFinalizers.push(finalizer);
|
|
247
|
+
else
|
|
248
|
+
finalizer();
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Whether an uncaught error is the WASM heap giving out, rather than some
|
|
252
|
+
* unrelated failure that happened while a solve was running.
|
|
253
|
+
*/
|
|
254
|
+
export function isZ3Failure(e) {
|
|
255
|
+
// A WebAssembly.RuntimeError is named just that; the global is not in this
|
|
256
|
+
// project's compiler libs, so the name is the check.
|
|
257
|
+
if (e instanceof Error && e.name === 'RuntimeError')
|
|
258
|
+
return true;
|
|
259
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
260
|
+
// A call-stack overflow was also seen once as a symptom of a corrupted
|
|
261
|
+
// heap; it counts only when the stack shows it came from the WASM glue,
|
|
262
|
+
// so an overflow elsewhere does not spend a recovery. With no frames to
|
|
263
|
+
// read (a host that keeps none) the conservative answer stands: while a
|
|
264
|
+
// solve is running, the overflow is Z3's.
|
|
265
|
+
if (/Maximum call stack size exceeded/.test(message)) {
|
|
266
|
+
if (!(e instanceof Error))
|
|
267
|
+
return false;
|
|
268
|
+
const stack = e.stack ?? '';
|
|
269
|
+
if (!/\n\s+at /.test(stack))
|
|
270
|
+
return true;
|
|
271
|
+
return stack.includes('z3-built');
|
|
272
|
+
}
|
|
273
|
+
return /Aborted\(|memory access out of bounds|out of memory|unreachable executed/i.test(message);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Tail of the queue of pending Z3 critical sections. Each acquirer waits on the
|
|
277
|
+
* current tail and installs its own completion as the new tail, so sections run
|
|
278
|
+
* in call order with no overlap.
|
|
279
|
+
*/
|
|
280
|
+
let z3LockTail = Promise.resolve();
|
|
281
|
+
/**
|
|
282
|
+
* Run `fn` with exclusive access to the shared Z3 Context.
|
|
283
|
+
*
|
|
284
|
+
* Serializes rather than parallelizes: an MCP client is free to issue several
|
|
285
|
+
* rego_verify calls at once, and letting them into the WASM heap together
|
|
286
|
+
* crashes it. Solve times are in the tens of milliseconds, so queueing is
|
|
287
|
+
* cheaper than the alternative of one Context per call, which would re-pay the
|
|
288
|
+
* WASM init cost every time.
|
|
289
|
+
*/
|
|
290
|
+
export async function withZ3Lock(fn) {
|
|
291
|
+
let release;
|
|
292
|
+
const mine = new Promise((resolve) => {
|
|
293
|
+
release = resolve;
|
|
294
|
+
});
|
|
295
|
+
const predecessor = z3LockTail;
|
|
296
|
+
z3LockTail = predecessor.then(() => mine);
|
|
297
|
+
await predecessor;
|
|
298
|
+
z3Depth++;
|
|
299
|
+
const poisoned = new Promise((_resolve, reject) => {
|
|
300
|
+
poisonInFlight = reject;
|
|
301
|
+
});
|
|
302
|
+
try {
|
|
303
|
+
return await Promise.race([fn(), poisoned]);
|
|
304
|
+
}
|
|
305
|
+
finally {
|
|
306
|
+
poisonInFlight = undefined;
|
|
307
|
+
z3Depth--;
|
|
308
|
+
try {
|
|
309
|
+
// The worker is idle: whatever the collector noticed mid-solve can be
|
|
310
|
+
// freed now.
|
|
311
|
+
if (z3Depth === 0)
|
|
312
|
+
runDeferredFinalizers();
|
|
313
|
+
}
|
|
314
|
+
finally {
|
|
315
|
+
// Whatever happened above, the lock must pass on, or every later call
|
|
316
|
+
// waits for ever.
|
|
317
|
+
release();
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
22
321
|
/**
|
|
23
322
|
* Reset the singleton - intended for test teardown only.
|
|
24
323
|
* Do NOT call in production paths; re-init is expensive.
|
|
25
324
|
*/
|
|
26
325
|
export function resetZ3ForTesting() {
|
|
27
326
|
z3InitPromise = null;
|
|
327
|
+
z3Api = undefined;
|
|
328
|
+
z3Unusable = undefined;
|
|
329
|
+
z3Depth = 0;
|
|
330
|
+
poisonInFlight = undefined;
|
|
331
|
+
z3LockTail = Promise.resolve();
|
|
332
|
+
z3Generation++;
|
|
333
|
+
deferredFinalizers = [];
|
|
334
|
+
recoveriesLeft = 3;
|
|
28
335
|
}
|
|
29
336
|
//# sourceMappingURL=rego-z3.js.map
|
package/dist/lib/rego-z3.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rego-z3.js","sourceRoot":"","sources":["../../src/lib/rego-z3.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rego-z3.js","sourceRoot":"","sources":["../../src/lib/rego-z3.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/security.d.ts
CHANGED
|
@@ -7,6 +7,14 @@ export interface PathValidationResult {
|
|
|
7
7
|
/**
|
|
8
8
|
* Resolve `inputPath` and confirm it is contained within at least one
|
|
9
9
|
* `allowedRoots` entry. Returns the resolved absolute path on success.
|
|
10
|
+
*
|
|
11
|
+
* Two checks, both of which must pass. The first is syntactic: `..` segments
|
|
12
|
+
* are collapsed without touching the disk and the result must sit under a
|
|
13
|
+
* root as written. The second follows the filesystem: the path's real
|
|
14
|
+
* location, including the part of it that does not exist yet, must sit under
|
|
15
|
+
* a root's real location. A link is still followed at read or write time by
|
|
16
|
+
* the tool that receives the path, so the check is against the layout at the
|
|
17
|
+
* moment of validation.
|
|
10
18
|
*/
|
|
11
19
|
export declare function validatePath(inputPath: string, allowedRoots: string[], options?: {
|
|
12
20
|
mustExist?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/lib/security.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;CAC7B;
|
|
1
|
+
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/lib/security.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;CAC7B;AA6ED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EAAE,EACtB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GACpC,oBAAoB,CAsGtB;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMjD"}
|
package/dist/lib/security.js
CHANGED
|
@@ -5,12 +5,90 @@
|
|
|
5
5
|
* `validatePath` to prevent reading or writing outside the
|
|
6
6
|
* agreed-upon roots.
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
9
|
-
import { isAbsolute, resolve, sep } from 'node:path';
|
|
8
|
+
import { lstatSync, realpathSync, statSync } from 'node:fs';
|
|
9
|
+
import { basename, dirname, isAbsolute, join, resolve, sep } from 'node:path';
|
|
10
10
|
import { err } from './errors.js';
|
|
11
|
+
const WINDOWS = process.platform === 'win32';
|
|
12
|
+
/**
|
|
13
|
+
* Canonical form of an existing path: every link resolved, and on Windows
|
|
14
|
+
* 8.3 short names expanded and on-disk casing restored. The JavaScript
|
|
15
|
+
* `realpathSync` resolves links but leaves short names and casing alone, so
|
|
16
|
+
* two spellings of one directory could compare unequal.
|
|
17
|
+
*/
|
|
18
|
+
function canonical(p) {
|
|
19
|
+
return realpathSync.native(p);
|
|
20
|
+
}
|
|
21
|
+
/** Does `p` fall under at least one of `roots`? */
|
|
22
|
+
function isUnderRoots(p, roots, caseInsensitive) {
|
|
23
|
+
const fold = (s) => (caseInsensitive ? s.toLowerCase() : s);
|
|
24
|
+
const candidate = fold(p);
|
|
25
|
+
return roots.some((root) => {
|
|
26
|
+
const r = fold(root);
|
|
27
|
+
const rootWithSep = r.endsWith(sep) ? r : r + sep;
|
|
28
|
+
return candidate === r || candidate.startsWith(rootWithSep);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Where a path really leads, whether or not it exists yet.
|
|
33
|
+
*
|
|
34
|
+
* Walks up from `p` to the nearest entry that exists, resolves that entry's
|
|
35
|
+
* real location, and re-attaches the segments below it. A write to `p` lands
|
|
36
|
+
* under that real location, so that is what has to be checked against the
|
|
37
|
+
* roots. Checking only paths that already exist left every not-yet-created
|
|
38
|
+
* write target unchecked, and a junction or symlink inside a root could point
|
|
39
|
+
* it anywhere.
|
|
40
|
+
*
|
|
41
|
+
* An entry that exists only as a link to something that does not exist (a
|
|
42
|
+
* dangling link) is reported on its own: a write through it would create the
|
|
43
|
+
* target wherever the link points.
|
|
44
|
+
*/
|
|
45
|
+
function realLocation(p) {
|
|
46
|
+
const below = [];
|
|
47
|
+
let cur = p;
|
|
48
|
+
for (;;) {
|
|
49
|
+
let entry;
|
|
50
|
+
try {
|
|
51
|
+
entry = lstatSync(cur);
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
const code = e.code;
|
|
55
|
+
if (code === 'ENOENT' || code === 'ENOTDIR') {
|
|
56
|
+
const parent = dirname(cur);
|
|
57
|
+
if (parent === cur)
|
|
58
|
+
return { kind: 'unresolvable', reason: 'no existing ancestor' };
|
|
59
|
+
below.unshift(basename(cur));
|
|
60
|
+
cur = parent;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
return { kind: 'unresolvable', reason: code ?? String(e) };
|
|
64
|
+
}
|
|
65
|
+
let real;
|
|
66
|
+
try {
|
|
67
|
+
real = canonical(cur);
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
if (entry.isSymbolicLink())
|
|
71
|
+
return { kind: 'dangling', link: cur };
|
|
72
|
+
return { kind: 'unresolvable', reason: e.code ?? String(e) };
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
kind: 'real',
|
|
76
|
+
path: below.length === 0 ? real : join(real, ...below),
|
|
77
|
+
exists: below.length === 0,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
11
81
|
/**
|
|
12
82
|
* Resolve `inputPath` and confirm it is contained within at least one
|
|
13
83
|
* `allowedRoots` entry. Returns the resolved absolute path on success.
|
|
84
|
+
*
|
|
85
|
+
* Two checks, both of which must pass. The first is syntactic: `..` segments
|
|
86
|
+
* are collapsed without touching the disk and the result must sit under a
|
|
87
|
+
* root as written. The second follows the filesystem: the path's real
|
|
88
|
+
* location, including the part of it that does not exist yet, must sit under
|
|
89
|
+
* a root's real location. A link is still followed at read or write time by
|
|
90
|
+
* the tool that receives the path, so the check is against the layout at the
|
|
91
|
+
* moment of validation.
|
|
14
92
|
*/
|
|
15
93
|
export function validatePath(inputPath, allowedRoots, options = {}) {
|
|
16
94
|
if (typeof inputPath !== 'string' || inputPath.length === 0) {
|
|
@@ -28,24 +106,42 @@ export function validatePath(inputPath, allowedRoots, options = {}) {
|
|
|
28
106
|
};
|
|
29
107
|
}
|
|
30
108
|
const resolved = isAbsolute(inputPath) ? resolve(inputPath) : resolve(process.cwd(), inputPath);
|
|
31
|
-
// Helper: confirm p falls under at least one of the provided root strings.
|
|
32
|
-
const isUnderRoots = (p, roots) => roots.some((root) => {
|
|
33
|
-
const rootWithSep = root.endsWith(sep) ? root : root + sep;
|
|
34
|
-
return p === root || p.startsWith(rootWithSep);
|
|
35
|
-
});
|
|
36
|
-
// Phase 1: syntactic traversal check. path.resolve() collapses `..`
|
|
37
|
-
// segments without I/O, so this catches plain traversal attacks cheaply.
|
|
38
109
|
const resolvedRoots = allowedRoots.map((r) => resolve(r));
|
|
39
|
-
|
|
110
|
+
const outsideHint = 'Set OPA_MCP_ALLOWED_PATHS to a comma-separated list of directories, or use a path under the current allowed roots.';
|
|
111
|
+
// Phase 1: syntactic containment, cheap and free of I/O. It is not the
|
|
112
|
+
// decision on its own: a root spelled through a link (macOS /var, a Windows
|
|
113
|
+
// short name, a junction) and a path spelled through the target land in the
|
|
114
|
+
// same real place and must be accepted. It settles which message an
|
|
115
|
+
// escaping path gets. Windows compares without regard to case.
|
|
116
|
+
const syntacticallyInside = isUnderRoots(resolved, resolvedRoots, WINDOWS);
|
|
117
|
+
const outsideRoots = () => err('PATH_NOT_ALLOWED', `Path is outside allowed roots: ${inputPath}`, {
|
|
118
|
+
hint: outsideHint,
|
|
119
|
+
details: { resolved, allowedRoots },
|
|
120
|
+
});
|
|
121
|
+
// Phase 2: real location. This is the decision.
|
|
122
|
+
const location = realLocation(resolved);
|
|
123
|
+
if (location.kind === 'dangling') {
|
|
124
|
+
return {
|
|
125
|
+
ok: false,
|
|
126
|
+
error: err('PATH_NOT_ALLOWED', `Path goes through a link whose target does not exist: ${inputPath}`, {
|
|
127
|
+
hint: 'A write through a dangling link would create its target wherever the link points. Remove the link or use a path that does not go through it.',
|
|
128
|
+
details: { resolved, link: location.link },
|
|
129
|
+
}),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (location.kind === 'unresolvable') {
|
|
133
|
+
if (!syntacticallyInside)
|
|
134
|
+
return { ok: false, error: outsideRoots() };
|
|
40
135
|
return {
|
|
41
136
|
ok: false,
|
|
42
|
-
error: err('
|
|
43
|
-
|
|
44
|
-
details: { resolved, allowedRoots },
|
|
137
|
+
error: err('PATH_NOT_FOUND', `Path could not be fully resolved: ${inputPath}`, {
|
|
138
|
+
details: { resolved, reason: location.reason },
|
|
45
139
|
}),
|
|
46
140
|
};
|
|
47
141
|
}
|
|
48
|
-
if (options.mustExist && !
|
|
142
|
+
if (options.mustExist && !location.exists) {
|
|
143
|
+
if (!syntacticallyInside)
|
|
144
|
+
return { ok: false, error: outsideRoots() };
|
|
49
145
|
return {
|
|
50
146
|
ok: false,
|
|
51
147
|
error: err('PATH_NOT_FOUND', `Path does not exist: ${inputPath}`, {
|
|
@@ -53,51 +149,31 @@ export function validatePath(inputPath, allowedRoots, options = {}) {
|
|
|
53
149
|
}),
|
|
54
150
|
};
|
|
55
151
|
}
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
//
|
|
61
|
-
// We validate via realpath but return `resolved` (the syntactic path)
|
|
62
|
-
// for backward compatibility across OSes where system directories are
|
|
63
|
-
// themselves symlinks (e.g. macOS /var -> /private/var). Callers pass
|
|
64
|
-
// the returned path to OPA/regal; the OS follows any remaining symlinks
|
|
65
|
-
// at read time, which is safe because we have verified the real target.
|
|
66
|
-
if (existsSync(resolved)) {
|
|
67
|
-
let realPath;
|
|
152
|
+
// A root that is itself a link, or spelled with a short name, compares
|
|
153
|
+
// correctly only in canonical form. A root that does not exist stays as
|
|
154
|
+
// written; nothing under it can resolve to it anyway.
|
|
155
|
+
const realRoots = resolvedRoots.map((r) => {
|
|
68
156
|
try {
|
|
69
|
-
|
|
157
|
+
return canonical(r);
|
|
70
158
|
}
|
|
71
159
|
catch {
|
|
72
|
-
|
|
73
|
-
// insufficient permissions to read the symlink chain. Fail closed.
|
|
74
|
-
return {
|
|
75
|
-
ok: false,
|
|
76
|
-
error: err('PATH_NOT_FOUND', `Path could not be fully resolved: ${inputPath}`, {
|
|
77
|
-
details: { resolved },
|
|
78
|
-
}),
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
// Also realpath the roots themselves so that a root that is a symlink
|
|
82
|
-
// compares correctly against the realpath of the input.
|
|
83
|
-
const realRoots = resolvedRoots.map((r) => {
|
|
84
|
-
try {
|
|
85
|
-
return existsSync(r) ? realpathSync(r) : r;
|
|
86
|
-
}
|
|
87
|
-
catch {
|
|
88
|
-
return r;
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
if (!isUnderRoots(realPath, realRoots)) {
|
|
92
|
-
return {
|
|
93
|
-
ok: false,
|
|
94
|
-
error: err('PATH_NOT_ALLOWED', `Path resolves outside allowed roots via symlink: ${inputPath}`, {
|
|
95
|
-
hint: 'Set OPA_MCP_ALLOWED_PATHS to a comma-separated list of directories, or use a path under the current allowed roots.',
|
|
96
|
-
details: { resolved, realPath, allowedRoots },
|
|
97
|
-
}),
|
|
98
|
-
};
|
|
160
|
+
return r;
|
|
99
161
|
}
|
|
162
|
+
});
|
|
163
|
+
if (!isUnderRoots(location.path, realRoots, false)) {
|
|
164
|
+
if (!syntacticallyInside)
|
|
165
|
+
return { ok: false, error: outsideRoots() };
|
|
166
|
+
return {
|
|
167
|
+
ok: false,
|
|
168
|
+
error: err('PATH_NOT_ALLOWED', `Path resolves outside allowed roots via a link: ${inputPath}`, {
|
|
169
|
+
hint: outsideHint,
|
|
170
|
+
details: { resolved, realPath: location.path, allowedRoots },
|
|
171
|
+
}),
|
|
172
|
+
};
|
|
100
173
|
}
|
|
174
|
+
// The syntactic path is returned, not the canonical one: on macOS the
|
|
175
|
+
// system temp directory is itself a link, and tools compare and report
|
|
176
|
+
// paths as the caller spelled them.
|
|
101
177
|
return { ok: true, resolved };
|
|
102
178
|
}
|
|
103
179
|
/** Convenience: returns true if the path is a directory (after validation). */
|
package/dist/lib/security.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/lib/security.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/lib/security.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAE9E,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AASlC,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;AAE7C;;;;;GAKG;AACH,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,mDAAmD;AACnD,SAAS,YAAY,CAAC,CAAS,EAAE,KAAe,EAAE,eAAwB;IACxE,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpE,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;QACzB,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,MAAM,WAAW,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;QAClD,OAAO,SAAS,KAAK,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC;AAOD;;;;;;;;;;;;;GAaG;AACH,SAAS,YAAY,CAAC,CAAS;IAC7B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,SAAS,CAAC;QACR,IAAI,KAAK,CAAC;QACV,IAAI,CAAC;YACH,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,GAAI,CAA2B,CAAC,IAAI,CAAC;YAC/C,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;gBAC5B,IAAI,MAAM,KAAK,GAAG;oBAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;gBACpF,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC7B,GAAG,GAAG,MAAM,CAAC;gBACb,SAAS;YACX,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,CAAC;QACD,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,KAAK,CAAC,cAAc,EAAE;gBAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;YACnE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAG,CAA2B,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1F,CAAC;QACD,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC;YACtD,MAAM,EAAE,KAAK,CAAC,MAAM,KAAK,CAAC;SAC3B,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAC1B,SAAiB,EACjB,YAAsB,EACtB,UAAmC,EAAE;IAErC,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5D,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,GAAG,CAAC,eAAe,EAAE,iCAAiC,CAAC;SAC/D,CAAC;IACJ,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,GAAG,CACR,kBAAkB,EAClB,uEAAuE,EACvE;gBACE,IAAI,EAAE,kGAAkG;aACzG,CACF;SACF,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;IAChG,MAAM,aAAa,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,MAAM,WAAW,GACf,oHAAoH,CAAC;IAEvH,uEAAuE;IACvE,4EAA4E;IAC5E,4EAA4E;IAC5E,oEAAoE;IACpE,+DAA+D;IAC/D,MAAM,mBAAmB,GAAG,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;IAC3E,MAAM,YAAY,GAAG,GAAG,EAAE,CACxB,GAAG,CAAC,kBAAkB,EAAE,kCAAkC,SAAS,EAAE,EAAE;QACrE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE;KACpC,CAAC,CAAC;IAEL,gDAAgD;IAChD,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACxC,IAAI,QAAQ,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QACjC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,GAAG,CACR,kBAAkB,EAClB,yDAAyD,SAAS,EAAE,EACpE;gBACE,IAAI,EAAE,8IAA8I;gBACpJ,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE;aAC3C,CACF;SACF,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;QACrC,IAAI,CAAC,mBAAmB;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC;QACtE,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,GAAG,CAAC,gBAAgB,EAAE,qCAAqC,SAAS,EAAE,EAAE;gBAC7E,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE;aAC/C,CAAC;SACH,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,SAAS,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC1C,IAAI,CAAC,mBAAmB;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC;QACtE,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,GAAG,CAAC,gBAAgB,EAAE,wBAAwB,SAAS,EAAE,EAAE;gBAChE,OAAO,EAAE,EAAE,QAAQ,EAAE;aACtB,CAAC;SACH,CAAC;IACJ,CAAC;IAED,uEAAuE;IACvE,wEAAwE;IACxE,sDAAsD;IACtD,MAAM,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACxC,IAAI,CAAC;YACH,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;QACnD,IAAI,CAAC,mBAAmB;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC;QACtE,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,GAAG,CACR,kBAAkB,EAClB,mDAAmD,SAAS,EAAE,EAC9D;gBACE,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE;aAC7D,CACF;SACF,CAAC;IACJ,CAAC;IAED,sEAAsE;IACtE,uEAAuE;IACvE,oCAAoC;IACpC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAChC,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
package/dist/lib/subprocess.d.ts
CHANGED
|
@@ -54,7 +54,20 @@ export interface SpawnResult {
|
|
|
54
54
|
* valid; absent means "not truncated".
|
|
55
55
|
*/
|
|
56
56
|
outputTruncated?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* The signal that ended the child, when one did. Set for the server's own
|
|
59
|
+
* kills (timeout, cancellation, output cap) and for kills from outside it,
|
|
60
|
+
* such as the kernel's out-of-memory killer. Optional for the same reason as
|
|
61
|
+
* `outputTruncated`.
|
|
62
|
+
*/
|
|
63
|
+
signal?: NodeJS.Signals | null;
|
|
57
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Signal every child still running. A child sits in its own process group on
|
|
67
|
+
* POSIX, so a signal that stops the server does not reach it on its own; the
|
|
68
|
+
* server calls this on the way out. Returns how many were signalled.
|
|
69
|
+
*/
|
|
70
|
+
export declare function terminateChildren(sig?: NodeJS.Signals): number;
|
|
58
71
|
/**
|
|
59
72
|
* Run a binary and return its captured output. Never throws -- failures are
|
|
60
73
|
* reflected in `exitCode` / `timedOut` / `outputTruncated`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subprocess.d.ts","sourceRoot":"","sources":["../../src/lib/subprocess.ts"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,wBAAwB,QAAmB,CAAC;AAEzD,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,wDAAwD;IACxD,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,mEAAmE;IACnE,OAAO,EAAE,OAAO,CAAC;IACjB,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"subprocess.d.ts","sourceRoot":"","sources":["../../src/lib/subprocess.ts"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,wBAAwB,QAAmB,CAAC;AAEzD,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,wDAAwD;IACxD,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,mEAAmE;IACnE,OAAO,EAAE,OAAO,CAAC;IACjB,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;CAChC;AAgDD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAM,CAAC,OAAmB,GAAG,MAAM,CAOzE;AA6CD;;;GAGG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CA4MxF"}
|