mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-03 01:29:56 +00:00
fix: probe SQLite when Node denies worker threads (#152075)
Some checks are pending
ClawSweeper Dispatch / dispatch (push) Waiting to run
CodeQL / Security High (actions) (push) Waiting to run
CodeQL / Security High (channel-runtime-boundary) (push) Waiting to run
CodeQL / Security High (core-auth-secrets) (push) Waiting to run
CodeQL / Security High (mcp-process-tool-boundary) (push) Waiting to run
CodeQL / Security High (network-ssrf-boundary) (push) Waiting to run
CodeQL / Security High (plugin-trust-boundary) (push) Waiting to run
CodeQL / Security High (process-exec-boundary) (push) Waiting to run
Control UI Locale Refresh / resolve-base (push) Waiting to run
Control UI Locale Refresh / Verify generated PR App permissions (push) Blocked by required conditions
Control UI Locale Refresh / Refresh (push) Blocked by required conditions
Control UI Locale Refresh / Commit control UI locale refresh (push) Blocked by required conditions
Docs Sync Publish Repo / sync-publish-repo (push) Waiting to run
Docs / docs (push) Waiting to run
Native App Locale Refresh / Refresh native th (push) Blocked by required conditions
Native App Locale Refresh / Refresh native tr (push) Blocked by required conditions
Native App Locale Refresh / Refresh native uk (push) Blocked by required conditions
Native App Locale Refresh / Refresh native vi (push) Blocked by required conditions
Native App Locale Refresh / Refresh native zh-CN (push) Blocked by required conditions
Native App Locale Refresh / Refresh native zh-TW (push) Blocked by required conditions
Native App Locale Refresh / Commit native locale refresh (push) Blocked by required conditions
Native App Locale Refresh / Refresh native nl (push) Blocked by required conditions
Native App Locale Refresh / Refresh native pl (push) Blocked by required conditions
Native App Locale Refresh / Refresh native pt-BR (push) Blocked by required conditions
Native App Locale Refresh / Refresh native ru (push) Blocked by required conditions
Native App Locale Refresh / Refresh native sv (push) Blocked by required conditions
Native App Locale Refresh / resolve-base (push) Waiting to run
Native App Locale Refresh / Verify generated PR App permissions (push) Blocked by required conditions
Native App Locale Refresh / Refresh native ar (push) Blocked by required conditions
Native App Locale Refresh / Refresh native de (push) Blocked by required conditions
Native App Locale Refresh / Refresh native es (push) Blocked by required conditions
Native App Locale Refresh / Refresh native fa (push) Blocked by required conditions
Native App Locale Refresh / Refresh native fr (push) Blocked by required conditions
Native App Locale Refresh / Refresh native hi (push) Blocked by required conditions
Native App Locale Refresh / Refresh native id (push) Blocked by required conditions
Native App Locale Refresh / Refresh native it (push) Blocked by required conditions
Native App Locale Refresh / Refresh native ja-JP (push) Blocked by required conditions
Native App Locale Refresh / Refresh native ko (push) Blocked by required conditions
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Waiting to run
Plugin NPM Release / Validate release publish approval (push) Blocked by required conditions
Plugin NPM Release / preview_plugin_pack (push) Blocked by required conditions
Plugin NPM Release / Preflight plugin npm package () (push) Blocked by required conditions
Plugin NPM Release / Seal prepared plugin npm release (push) Blocked by required conditions
Plugin NPM Release / Trusted publisher OIDC exchange (push) Blocked by required conditions
Workflow Sanity / actionlint (push) Waiting to run
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Blocked by required conditions
Plugin Init Scaffold Validation / Validate provider scaffold (push) Waiting to run
Plugin NPM Release / preview_plugins_npm (push) Waiting to run
Plugin NPM Release / publish_plugins_npm (push) Blocked by required conditions
Plugin NPM Release / verify_plugins_npm (push) Blocked by required conditions
Vitest Cache Warm / warm (push) Waiting to run
Workflow Sanity / no-tabs (push) Waiting to run
Workflow Sanity / generated-doc-baselines (push) Waiting to run
Some checks are pending
ClawSweeper Dispatch / dispatch (push) Waiting to run
CodeQL / Security High (actions) (push) Waiting to run
CodeQL / Security High (channel-runtime-boundary) (push) Waiting to run
CodeQL / Security High (core-auth-secrets) (push) Waiting to run
CodeQL / Security High (mcp-process-tool-boundary) (push) Waiting to run
CodeQL / Security High (network-ssrf-boundary) (push) Waiting to run
CodeQL / Security High (plugin-trust-boundary) (push) Waiting to run
CodeQL / Security High (process-exec-boundary) (push) Waiting to run
Control UI Locale Refresh / resolve-base (push) Waiting to run
Control UI Locale Refresh / Verify generated PR App permissions (push) Blocked by required conditions
Control UI Locale Refresh / Refresh (push) Blocked by required conditions
Control UI Locale Refresh / Commit control UI locale refresh (push) Blocked by required conditions
Docs Sync Publish Repo / sync-publish-repo (push) Waiting to run
Docs / docs (push) Waiting to run
Native App Locale Refresh / Refresh native th (push) Blocked by required conditions
Native App Locale Refresh / Refresh native tr (push) Blocked by required conditions
Native App Locale Refresh / Refresh native uk (push) Blocked by required conditions
Native App Locale Refresh / Refresh native vi (push) Blocked by required conditions
Native App Locale Refresh / Refresh native zh-CN (push) Blocked by required conditions
Native App Locale Refresh / Refresh native zh-TW (push) Blocked by required conditions
Native App Locale Refresh / Commit native locale refresh (push) Blocked by required conditions
Native App Locale Refresh / Refresh native nl (push) Blocked by required conditions
Native App Locale Refresh / Refresh native pl (push) Blocked by required conditions
Native App Locale Refresh / Refresh native pt-BR (push) Blocked by required conditions
Native App Locale Refresh / Refresh native ru (push) Blocked by required conditions
Native App Locale Refresh / Refresh native sv (push) Blocked by required conditions
Native App Locale Refresh / resolve-base (push) Waiting to run
Native App Locale Refresh / Verify generated PR App permissions (push) Blocked by required conditions
Native App Locale Refresh / Refresh native ar (push) Blocked by required conditions
Native App Locale Refresh / Refresh native de (push) Blocked by required conditions
Native App Locale Refresh / Refresh native es (push) Blocked by required conditions
Native App Locale Refresh / Refresh native fa (push) Blocked by required conditions
Native App Locale Refresh / Refresh native fr (push) Blocked by required conditions
Native App Locale Refresh / Refresh native hi (push) Blocked by required conditions
Native App Locale Refresh / Refresh native id (push) Blocked by required conditions
Native App Locale Refresh / Refresh native it (push) Blocked by required conditions
Native App Locale Refresh / Refresh native ja-JP (push) Blocked by required conditions
Native App Locale Refresh / Refresh native ko (push) Blocked by required conditions
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Waiting to run
Plugin NPM Release / Validate release publish approval (push) Blocked by required conditions
Plugin NPM Release / preview_plugin_pack (push) Blocked by required conditions
Plugin NPM Release / Preflight plugin npm package () (push) Blocked by required conditions
Plugin NPM Release / Seal prepared plugin npm release (push) Blocked by required conditions
Plugin NPM Release / Trusted publisher OIDC exchange (push) Blocked by required conditions
Workflow Sanity / actionlint (push) Waiting to run
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Blocked by required conditions
Plugin Init Scaffold Validation / Validate provider scaffold (push) Waiting to run
Plugin NPM Release / preview_plugins_npm (push) Waiting to run
Plugin NPM Release / publish_plugins_npm (push) Blocked by required conditions
Plugin NPM Release / verify_plugins_npm (push) Blocked by required conditions
Vitest Cache Warm / warm (push) Waiting to run
Workflow Sanity / no-tabs (push) Waiting to run
Workflow Sanity / generated-doc-baselines (push) Waiting to run
This commit is contained in:
parent
f953dbdf47
commit
d2a5196a2f
2 changed files with 86 additions and 3 deletions
|
|
@ -56,12 +56,17 @@ function isSqliteCapabilities(value) {
|
|||
);
|
||||
}
|
||||
|
||||
async function probeCurrentSqliteInWorker() {
|
||||
async function probeCurrentSqlite() {
|
||||
let worker;
|
||||
try {
|
||||
if (typeof process.getBuiltinModule?.("node:sqlite")?.DatabaseSync !== "function") {
|
||||
const DatabaseSync = process.getBuiltinModule?.("node:sqlite")?.DatabaseSync;
|
||||
if (typeof DatabaseSync !== "function") {
|
||||
return unavailableSqliteCapabilities(new Error("node:sqlite is unavailable"));
|
||||
}
|
||||
// Keep the real capability check when Node's permission policy forbids workers.
|
||||
if (!process.versions.bun && process.permission?.has("worker") === false) {
|
||||
return probeSqlite(DatabaseSync);
|
||||
}
|
||||
const env = Object.fromEntries(
|
||||
Object.entries(process.env).filter(([name]) => !/^(NODE_OPTIONS|BUN_OPTIONS)$/i.test(name)),
|
||||
);
|
||||
|
|
@ -126,7 +131,7 @@ async function probeCurrentSqliteInWorker() {
|
|||
|
||||
export function detectCurrentSqliteCapabilities() {
|
||||
// Publish the Promise before Worker construction can notify another startup caller.
|
||||
globalThis[capabilityCacheKey] ??= Promise.resolve().then(probeCurrentSqliteInWorker);
|
||||
globalThis[capabilityCacheKey] ??= Promise.resolve().then(probeCurrentSqlite);
|
||||
return Promise.resolve(globalThis[capabilityCacheKey]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { DatabaseSync } from "node:sqlite";
|
|||
import { runInNewContext } from "node:vm";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { SQLITE_CAPABILITY_PROBE } from "../../node-sqlite.mjs";
|
||||
import { resolveTestNodeExecPath } from "../test-utils/node-process.js";
|
||||
|
||||
function probeSqlite(Database: unknown): unknown {
|
||||
return runInNewContext(SQLITE_CAPABILITY_PROBE, {
|
||||
|
|
@ -142,4 +143,81 @@ describe("SQLite NUL capability probe", () => {
|
|||
counts: { prepare: 0, exec: 0, get: 0, all: 0, run: 0, iterate: 0 },
|
||||
});
|
||||
});
|
||||
|
||||
it.each([false, true])(
|
||||
"validates real SQLite when Node denies workers (SQL failure=%s)",
|
||||
(sqlFailure) => {
|
||||
const moduleUrl = new URL("../../node-sqlite.mjs", import.meta.url).href;
|
||||
const output = execFileSync(
|
||||
resolveTestNodeExecPath(),
|
||||
[
|
||||
"--input-type=module",
|
||||
"-e",
|
||||
`
|
||||
import { DatabaseSync } from "node:sqlite";
|
||||
import { Worker } from "node:worker_threads";
|
||||
let closed = 0;
|
||||
const close = DatabaseSync.prototype.close;
|
||||
DatabaseSync.prototype.close = function (...args) {
|
||||
closed++;
|
||||
return Reflect.apply(close, this, args);
|
||||
};
|
||||
if (${sqlFailure}) {
|
||||
DatabaseSync.prototype.exec = function () {
|
||||
throw new Error("injected SQL failure");
|
||||
};
|
||||
}
|
||||
let workersStarted = 0;
|
||||
process.on("worker", () => workersStarted++);
|
||||
const { detectCurrentSqliteCapabilities, nodeRuntimeFailure } = await import(${JSON.stringify(moduleUrl)});
|
||||
const pending = detectCurrentSqliteCapabilities();
|
||||
const samePending = pending === detectCurrentSqliteCapabilities();
|
||||
const capabilities = await pending;
|
||||
const sameResult = capabilities === await detectCurrentSqliteCapabilities();
|
||||
let workerDenied;
|
||||
try {
|
||||
new Worker("", { eval: true });
|
||||
} catch (error) {
|
||||
workerDenied = { code: error.code, permission: error.permission };
|
||||
}
|
||||
process.stdout.write(JSON.stringify({
|
||||
asynchronous: pending instanceof Promise, samePending, sameResult,
|
||||
capabilities, failure: nodeRuntimeFailure(process.versions.node, capabilities),
|
||||
closed, workersStarted, workerDenied,
|
||||
permissions: {
|
||||
worker: process.permission.has("worker"),
|
||||
write: process.permission.has("fs.write"),
|
||||
child: process.permission.has("child"),
|
||||
},
|
||||
}));
|
||||
`,
|
||||
],
|
||||
{
|
||||
encoding: "utf8",
|
||||
timeout: 10_000,
|
||||
env: { ...process.env, NODE_OPTIONS: "--permission --allow-fs-read=*" },
|
||||
},
|
||||
);
|
||||
expect(JSON.parse(output)).toMatchObject({
|
||||
asynchronous: true,
|
||||
samePending: true,
|
||||
sameResult: true,
|
||||
capabilities: {
|
||||
available: true,
|
||||
version: expect.any(String),
|
||||
text: !sqlFailure,
|
||||
blob: !sqlFailure,
|
||||
json: !sqlFailure,
|
||||
...(sqlFailure ? { error: "injected SQL failure" } : {}),
|
||||
},
|
||||
failure: sqlFailure
|
||||
? expect.stringContaining("node:sqlite NUL round-trip capability probe failed")
|
||||
: null,
|
||||
closed: 1,
|
||||
workersStarted: 0,
|
||||
workerDenied: { code: "ERR_ACCESS_DENIED", permission: "WorkerThreads" },
|
||||
permissions: { worker: false, write: false, child: false },
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue