@oxygen-agent/cli 1.46.0 → 1.64.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -1
- package/dist/credentials.d.ts +25 -0
- package/dist/credentials.js +214 -45
- package/dist/index.js +1107 -181
- package/dist/local-custom-http-column.js +1 -1
- package/dist/skills.d.ts +41 -0
- package/dist/skills.js +325 -0
- package/dist/update.d.ts +34 -0
- package/dist/update.js +123 -0
- package/node_modules/@oxygen/shared/dist/billing.d.ts +2 -1
- package/node_modules/@oxygen/shared/dist/billing.js +2 -1
- package/node_modules/@oxygen/shared/dist/cell-format.d.ts +60 -0
- package/node_modules/@oxygen/shared/dist/cell-format.js +277 -0
- package/node_modules/@oxygen/shared/dist/column-types.d.ts +2 -1
- package/node_modules/@oxygen/shared/dist/column-types.js +3 -2
- package/node_modules/@oxygen/shared/dist/file-import.js +1 -1
- package/node_modules/@oxygen/shared/dist/index.d.ts +2 -0
- package/node_modules/@oxygen/shared/dist/index.js +2 -0
- package/node_modules/@oxygen/shared/dist/log.js +1 -1
- package/node_modules/@oxygen/shared/dist/provider-request-outcomes.d.ts +3 -0
- package/node_modules/@oxygen/shared/dist/provider-request-outcomes.js +5 -0
- package/node_modules/@oxygen/shared/dist/version.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/version.js +1 -1
- package/node_modules/@oxygen/workflows/dist/index.d.ts +145 -143
- package/node_modules/@oxygen/workflows/dist/index.js +66 -29
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import * as vm from "node:vm";
|
|
2
|
+
import * as vm from "node:vm"; // skipcq: JS-C1003
|
|
3
3
|
export const WORKFLOW_MANIFEST_VERSION = 1;
|
|
4
4
|
export const WORKFLOW_COMPILER_VERSION = "oxygen-workflows-v1";
|
|
5
5
|
export const DURABLE_RECIPE_COMPILER_VERSION = "oxygen-recipes-v2";
|
|
@@ -8,16 +8,16 @@ export const DEFAULT_WORKFLOW_CRON_TIMEZONE = "UTC";
|
|
|
8
8
|
// Compatibility and determinism lint only. The Vercel sandbox process,
|
|
9
9
|
// denied network policy, and runtime global guards are the security boundary.
|
|
10
10
|
const UNSAFE_RECIPE_BUNDLE_PATTERNS = [
|
|
11
|
-
{ token: "globalThis", pattern: /\bglobalThis\b/ },
|
|
11
|
+
{ token: "globalThis", pattern: /\bglobalThis\b/ }, // skipcq: SCT-A000
|
|
12
12
|
{ token: "global", pattern: /\bglobal\b/ },
|
|
13
13
|
{ token: "process", pattern: /\bprocess\b/ },
|
|
14
14
|
{ token: "fetch", pattern: /\bfetch\b/ },
|
|
15
|
-
{ token: "XMLHttpRequest", pattern: /\bXMLHttpRequest\b/ },
|
|
15
|
+
{ token: "XMLHttpRequest", pattern: /\bXMLHttpRequest\b/ }, // skipcq: SCT-A000
|
|
16
16
|
{ token: "WebSocket", pattern: /\bWebSocket\b/ },
|
|
17
|
-
{ token: "EventSource", pattern: /\bEventSource\b/ },
|
|
17
|
+
{ token: "EventSource", pattern: /\bEventSource\b/ }, // skipcq: SCT-A000
|
|
18
18
|
{ token: "require", pattern: /\brequire\b/ },
|
|
19
|
-
{ token: "dynamic import", pattern: /\bimport(?:\s|\/\*[\s\S]*?\*\/)*\(/ },
|
|
20
|
-
{ token: "node module import", pattern: /\b(?:node:)?(?:fs|child_process|net|tls|http|https|dns|dgram|worker_threads)\b/ },
|
|
19
|
+
{ token: "dynamic import", pattern: /\bimport(?:\s|\/\*[\s\S]*?\*\/)*\(/ }, // skipcq: SCT-A000
|
|
20
|
+
{ token: "node module import", pattern: /\b(?:node:)?(?:fs|child_process|net|tls|http|https|dns|dgram|worker_threads)\b/ }, // skipcq: SCT-A000
|
|
21
21
|
{ token: "eval", pattern: /\beval\b/ },
|
|
22
22
|
{ token: "Function", pattern: /\bFunction\b/ },
|
|
23
23
|
{ token: "constructor", pattern: /\bconstructor\b/ },
|
|
@@ -26,7 +26,7 @@ const UNSAFE_RECIPE_BUNDLE_PATTERNS = [
|
|
|
26
26
|
{ token: "Math.random", pattern: /\bMath\s*\.\s*random\b/ },
|
|
27
27
|
{ token: "crypto.randomUUID", pattern: /\bcrypto\s*\.\s*randomUUID\b/ },
|
|
28
28
|
{ token: "setTimeout", pattern: /\bsetTimeout\b/ },
|
|
29
|
-
{ token: "setInterval", pattern: /\bsetInterval\b/ },
|
|
29
|
+
{ token: "setInterval", pattern: /\bsetInterval\b/ }, // skipcq: SCT-A000
|
|
30
30
|
];
|
|
31
31
|
export function defineWorkflow(input) {
|
|
32
32
|
return {
|
|
@@ -195,7 +195,8 @@ export function buildRecipeManifest(input) {
|
|
|
195
195
|
};
|
|
196
196
|
return manifest;
|
|
197
197
|
}
|
|
198
|
-
export function lintWorkflowManifest(
|
|
198
|
+
export function lintWorkflowManifest(// skipcq: JS-R1005
|
|
199
|
+
value, options = {}) {
|
|
199
200
|
if (isRecord(value)
|
|
200
201
|
&& typeof value.compiler_version === "string"
|
|
201
202
|
&& value.compiler_version.startsWith("oxygen-recipes-")) {
|
|
@@ -294,7 +295,8 @@ export function lintWorkflowManifest(value, options = {}) {
|
|
|
294
295
|
}
|
|
295
296
|
return { ok: issues.length === 0, issues };
|
|
296
297
|
}
|
|
297
|
-
export function lintRecipeManifest(
|
|
298
|
+
export function lintRecipeManifest(// skipcq: JS-R1005
|
|
299
|
+
value, options = {}) {
|
|
298
300
|
const issues = [];
|
|
299
301
|
const add = (path, code, message) => issues.push({ path, code, message });
|
|
300
302
|
if (!isRecord(value)) {
|
|
@@ -409,31 +411,49 @@ export async function runPureWorkflowFunction(input) {
|
|
|
409
411
|
const first = issues[0];
|
|
410
412
|
throw new Error(first ? `${first.code}: ${first.message}` : "Invalid workflow function source.");
|
|
411
413
|
}
|
|
414
|
+
// Cross the host/sandbox boundary as a JSON string, then parse INSIDE the
|
|
415
|
+
// vm context. If we passed the host object directly its prototype chain
|
|
416
|
+
// would point at the host's Object/Function, and the regex token blacklist
|
|
417
|
+
// is trivially bypassed (e.g. "con"+"structor") to reach
|
|
418
|
+
// __oxygen_context.constructor.constructor === host Function — which is
|
|
419
|
+
// not affected by the new context's codeGeneration setting and yields
|
|
420
|
+
// worker-process RCE. Parsing inside the context rebinds the prototype to
|
|
421
|
+
// the sandboxed Object, so the same walk reaches the sandboxed Function,
|
|
422
|
+
// which then trips contextCodeGeneration.strings=false below.
|
|
412
423
|
const context = toJsonValue(input.context, "context");
|
|
424
|
+
const contextJson = JSON.stringify(context);
|
|
413
425
|
const sandbox = Object.create(null);
|
|
414
|
-
sandbox.
|
|
415
|
-
|
|
416
|
-
|
|
426
|
+
sandbox.__oxygen_context_json = contextJson;
|
|
427
|
+
// Shadow dangerous globals on the sandbox surface. Defense-in-depth: the
|
|
428
|
+
// load-bearing block is contextCodeGeneration; this just removes the
|
|
429
|
+
// obvious top-level handles.
|
|
430
|
+
sandbox.Function = undefined;
|
|
431
|
+
sandbox.eval = undefined;
|
|
432
|
+
sandbox.setTimeout = undefined;
|
|
433
|
+
sandbox.setInterval = undefined;
|
|
434
|
+
sandbox.setImmediate = undefined;
|
|
435
|
+
sandbox.queueMicrotask = undefined;
|
|
436
|
+
sandbox.WebAssembly = undefined;
|
|
437
|
+
const script = new vm.Script(`"use strict";\n`
|
|
438
|
+
+ `const __oxygen_context = JSON.parse(__oxygen_context_json);\n`
|
|
439
|
+
+ `const __oxygen_fn = (${input.source});\n`
|
|
440
|
+
+ `__oxygen_fn(__oxygen_context);`);
|
|
441
|
+
// Disable dynamic code generation in the sandboxed context. Combined with
|
|
442
|
+
// the JSON re-parse above, this means every prototype-walk path to
|
|
443
|
+
// Function — direct, via context.constructor.constructor, or any other
|
|
444
|
+
// reachable Function instance — throws EvalError when called with source.
|
|
445
|
+
const result = script.runInNewContext(sandbox, {
|
|
446
|
+
timeout: timeoutMs,
|
|
447
|
+
contextCodeGeneration: {
|
|
448
|
+
strings: false,
|
|
449
|
+
wasm: false,
|
|
450
|
+
},
|
|
451
|
+
});
|
|
417
452
|
const resolved = isPromiseLike(result)
|
|
418
453
|
? await withTimeout(result, timeoutMs)
|
|
419
454
|
: result;
|
|
420
455
|
return enforceJsonOutput(resolved, maxOutputBytes);
|
|
421
456
|
}
|
|
422
|
-
export function getWorkflowApplySchema() {
|
|
423
|
-
return workflowApplySchema;
|
|
424
|
-
}
|
|
425
|
-
export function getWorkflowSchema(subject = "apply") {
|
|
426
|
-
const schemas = {
|
|
427
|
-
apply: workflowApplySchema,
|
|
428
|
-
call: workflowCallSchema,
|
|
429
|
-
event: workflowEventEmitSchema,
|
|
430
|
-
trigger: workflowTriggerSchema,
|
|
431
|
-
manifest: workflowManifestSchema,
|
|
432
|
-
};
|
|
433
|
-
if (subject === "all")
|
|
434
|
-
return { schemas };
|
|
435
|
-
return schemas[subject];
|
|
436
|
-
}
|
|
437
457
|
export const workflowApplySchema = {
|
|
438
458
|
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
439
459
|
title: "OXYGEN Workflow Apply Input",
|
|
@@ -516,7 +536,23 @@ export const workflowManifestSchema = {
|
|
|
516
536
|
additionalProperties: true,
|
|
517
537
|
required: ["manifest_version", "workflow", "steps", "source_hash", "compiler_version"],
|
|
518
538
|
};
|
|
519
|
-
function
|
|
539
|
+
export function getWorkflowApplySchema() {
|
|
540
|
+
return workflowApplySchema;
|
|
541
|
+
}
|
|
542
|
+
export function getWorkflowSchema(subject = "apply") {
|
|
543
|
+
const schemas = {
|
|
544
|
+
apply: workflowApplySchema,
|
|
545
|
+
call: workflowCallSchema,
|
|
546
|
+
event: workflowEventEmitSchema,
|
|
547
|
+
trigger: workflowTriggerSchema,
|
|
548
|
+
manifest: workflowManifestSchema,
|
|
549
|
+
};
|
|
550
|
+
if (subject === "all")
|
|
551
|
+
return { schemas };
|
|
552
|
+
return schemas[subject];
|
|
553
|
+
}
|
|
554
|
+
function validateJsonSchemaValueInto(// skipcq: JS-R1005
|
|
555
|
+
value, schema, path, issues) {
|
|
520
556
|
const startCount = issues.length;
|
|
521
557
|
if (schema.const !== undefined && !jsonEqual(value, schema.const)) {
|
|
522
558
|
issues.push({
|
|
@@ -638,7 +674,8 @@ function formatSchemaTypes(types) {
|
|
|
638
674
|
function jsonEqual(left, right) {
|
|
639
675
|
return JSON.stringify(left) === JSON.stringify(right);
|
|
640
676
|
}
|
|
641
|
-
function validateTrigger(
|
|
677
|
+
function validateTrigger(// skipcq: JS-R1005
|
|
678
|
+
value, path, add) {
|
|
642
679
|
if (!isRecord(value)) {
|
|
643
680
|
add(path, "invalid_trigger", "Workflow trigger must be an object.");
|
|
644
681
|
return;
|