@rulvar/planner 1.37.0 → 1.39.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.
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { ScriptRejected } from "@rulvar/core";
|
|
2
|
+
import * as acorn from "acorn";
|
|
3
|
+
import { scanDialect } from "eslint-plugin-rulvar";
|
|
2
4
|
//#region src/compile.ts
|
|
3
5
|
/**
|
|
4
6
|
* The exact curated sandbox global set, in canonical order.
|
|
@@ -164,6 +166,63 @@ function scanImports(source, blanked, allowImports) {
|
|
|
164
166
|
}
|
|
165
167
|
return diagnostics;
|
|
166
168
|
}
|
|
169
|
+
const CODEGEN_DIAGNOSTIC = {
|
|
170
|
+
eval: {
|
|
171
|
+
ruleId: "no-eval",
|
|
172
|
+
message: "eval is not part of the sandbox dialect; dynamically generated code reopens the import allowlist and the ambient capability surface the dialect closes"
|
|
173
|
+
},
|
|
174
|
+
"function-constructor": {
|
|
175
|
+
ruleId: "no-function-constructor",
|
|
176
|
+
message: "the Function constructor is not part of the sandbox dialect; it compiles arbitrary code that bypasses the import allowlist (use only the curated globals)"
|
|
177
|
+
},
|
|
178
|
+
"constructor-access": {
|
|
179
|
+
ruleId: "no-constructor-access",
|
|
180
|
+
message: "constructor access is not part of the sandbox dialect; it reaches the Function constructor from any function value and reopens dynamic code generation"
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
/**
|
|
184
|
+
* Rejects dynamic code generation. `eval` and the Function constructor
|
|
185
|
+
* compile attacker supplied text in a fresh scope where the import
|
|
186
|
+
* expression, ambient time, and host capability are back in reach, so
|
|
187
|
+
* banning `import` while allowing `new Function("return import(x)")` closes
|
|
188
|
+
* nothing. Constructor reconstruction is the same vector by another name:
|
|
189
|
+
* every function value exposes the Function constructor through its prototype
|
|
190
|
+
* ((function(){}).constructor === Function), reachable as `.constructor`,
|
|
191
|
+
* `["constructor"]`, a computed key that folds to the constant, a
|
|
192
|
+
* `{ constructor: x }` destructuring, or `Reflect.get(fn, "constructor")`.
|
|
193
|
+
*
|
|
194
|
+
* The scan runs the SAME shared AST policy the `no-code-generation` ESLint
|
|
195
|
+
* rule uses (`scanDialect`), so the linter and this structural gate reach one
|
|
196
|
+
* decision for every statically visible form. A truly dynamic key
|
|
197
|
+
* (`fn[valueFromAnAgent]`) cannot be resolved statically without rejecting
|
|
198
|
+
* every dynamic property access, so it is left to the worker realm, which
|
|
199
|
+
* neutralizes the runtime reconstruction path. A syntax error is reported by
|
|
200
|
+
* the AsyncFunction construction below, so a parse failure here yields no
|
|
201
|
+
* diagnostics rather than a duplicate.
|
|
202
|
+
*/
|
|
203
|
+
function scanCodegen(source) {
|
|
204
|
+
let program;
|
|
205
|
+
try {
|
|
206
|
+
program = acorn.parse(source, {
|
|
207
|
+
ecmaVersion: "latest",
|
|
208
|
+
sourceType: "module",
|
|
209
|
+
allowReturnOutsideFunction: true,
|
|
210
|
+
allowAwaitOutsideFunction: true,
|
|
211
|
+
locations: true
|
|
212
|
+
});
|
|
213
|
+
} catch {
|
|
214
|
+
return [];
|
|
215
|
+
}
|
|
216
|
+
return scanDialect(program).map((finding) => {
|
|
217
|
+
const { ruleId, message } = CODEGEN_DIAGNOSTIC[finding.kind];
|
|
218
|
+
return {
|
|
219
|
+
ruleId,
|
|
220
|
+
message,
|
|
221
|
+
line: finding.line,
|
|
222
|
+
column: finding.column
|
|
223
|
+
};
|
|
224
|
+
});
|
|
225
|
+
}
|
|
167
226
|
/**
|
|
168
227
|
* Validates and compiles planner-generated source into a CompiledWorkflow.
|
|
169
228
|
* The source is an async function body over the sandbox
|
|
@@ -180,6 +239,7 @@ function compileScript(source, o) {
|
|
|
180
239
|
}] } });
|
|
181
240
|
const blanked = blankLiterals(source);
|
|
182
241
|
diagnostics.push(...scanImports(source, blanked, allowImports));
|
|
242
|
+
diagnostics.push(...scanCodegen(source));
|
|
183
243
|
try {
|
|
184
244
|
new AsyncFunctionCtor(...SANDBOX_GLOBALS, source);
|
|
185
245
|
} catch (error) {
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { n as compileScript, r as scriptDiagnosticsOf, t as SANDBOX_GLOBALS } from "./compile-
|
|
1
|
+
import { n as compileScript, r as scriptDiagnosticsOf, t as SANDBOX_GLOBALS } from "./compile-DjzdBuva.js";
|
|
2
2
|
import { ConfigError, InMemoryStore, SANDBOX_AGENT_OPT_KEYS, SandboxError, ScriptRejected, createEngine, createSandboxBridge, defineWorkflow, readRunMeta, toJournalValue } from "@rulvar/core";
|
|
3
|
+
import { toJsonDiagnostics, workflowsConfig } from "eslint-plugin-rulvar";
|
|
3
4
|
import { createHash } from "node:crypto";
|
|
4
5
|
import { Linter } from "eslint";
|
|
5
|
-
import { toJsonDiagnostics, workflowsConfig } from "eslint-plugin-rulvar";
|
|
6
6
|
import { MessageChannel, Worker } from "node:worker_threads";
|
|
7
7
|
//#region src/api-card.ts
|
|
8
8
|
/**
|
package/dist/sandbox-worker.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as SANDBOX_GLOBALS } from "./compile-
|
|
1
|
+
import { t as SANDBOX_GLOBALS } from "./compile-DjzdBuva.js";
|
|
2
2
|
import { NonSerializableValueError, toJournalValue } from "@rulvar/core";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import { parentPort } from "node:worker_threads";
|
|
@@ -135,6 +135,24 @@ function main(port, init) {
|
|
|
135
135
|
Math.random = shimRandom;
|
|
136
136
|
Reflect.set(globalThis, "fetch", void 0);
|
|
137
137
|
Reflect.set(globalThis, "process", void 0);
|
|
138
|
+
Reflect.set(globalThis, "eval", void 0);
|
|
139
|
+
Reflect.set(globalThis, "Function", void 0);
|
|
140
|
+
const asyncProto = Object.getPrototypeOf(shimAsyncMarker);
|
|
141
|
+
const AsyncFunctionCtor = asyncProto.constructor;
|
|
142
|
+
const denyCodegen = function constructor() {
|
|
143
|
+
throw new EvalError("dynamic code generation is not available in the sandbox dialect");
|
|
144
|
+
};
|
|
145
|
+
for (const proto of [
|
|
146
|
+
Object.getPrototypeOf(shimRegularMarker),
|
|
147
|
+
asyncProto,
|
|
148
|
+
Object.getPrototypeOf(shimGeneratorMarker),
|
|
149
|
+
Object.getPrototypeOf(shimAsyncGeneratorMarker)
|
|
150
|
+
]) Object.defineProperty(proto, "constructor", {
|
|
151
|
+
value: denyCodegen,
|
|
152
|
+
writable: false,
|
|
153
|
+
enumerable: false,
|
|
154
|
+
configurable: false
|
|
155
|
+
});
|
|
138
156
|
const sandboxGlobals = {
|
|
139
157
|
agent: (prompt, opts) => callHost("agent", {
|
|
140
158
|
prompt,
|
|
@@ -268,7 +286,6 @@ function main(port, init) {
|
|
|
268
286
|
default: return;
|
|
269
287
|
}
|
|
270
288
|
});
|
|
271
|
-
const AsyncFunctionCtor = Object.getPrototypeOf(shimAsyncMarker).constructor;
|
|
272
289
|
enterFrame();
|
|
273
290
|
(async () => {
|
|
274
291
|
try {
|
|
@@ -286,8 +303,13 @@ function main(port, init) {
|
|
|
286
303
|
}
|
|
287
304
|
})();
|
|
288
305
|
}
|
|
289
|
-
/**
|
|
306
|
+
/** Markers reaching each Function family constructor prototype; never invoked. */
|
|
290
307
|
const shimAsyncMarker = async () => void 0;
|
|
308
|
+
const shimRegularMarker = () => void 0;
|
|
309
|
+
function* shimGeneratorMarker() {}
|
|
310
|
+
async function* shimAsyncGeneratorMarker() {
|
|
311
|
+
return void 0;
|
|
312
|
+
}
|
|
291
313
|
parentPort?.once("message", (init) => {
|
|
292
314
|
main(init.port, init);
|
|
293
315
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/planner",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.39.0",
|
|
4
4
|
"description": "Rulvar flagship hybrid mode: plan agent, compileScript, WorkerSandboxRunner, self-repair loop.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -22,15 +22,16 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
+
"acorn": "^8.17.0",
|
|
25
26
|
"eslint": "^9.39.4",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
27
|
+
"eslint-plugin-rulvar": "1.39.0",
|
|
28
|
+
"@rulvar/core": "1.39.0"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
30
31
|
"@types/node": "^22.20.0",
|
|
31
32
|
"tsdown": "^0.22.3",
|
|
32
33
|
"typescript": "~6.0.3",
|
|
33
|
-
"@rulvar/testing": "1.
|
|
34
|
+
"@rulvar/testing": "1.39.0"
|
|
34
35
|
},
|
|
35
36
|
"repository": {
|
|
36
37
|
"type": "git",
|