Vendor OpenClaw source as Adolf fork baseline
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11), free to diverge. Tree copied sans upstream .git; upstream remote added for future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19. Preserves docs/ARCHITECTURE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
This commit is contained in:
310
scripts/check-temp-path-guardrails.ts
Normal file
310
scripts/check-temp-path-guardrails.ts
Normal file
@@ -0,0 +1,310 @@
|
||||
// Check Temp Path Guardrails script supports OpenClaw repository automation.
|
||||
import { execFileSync } from "node:child_process";
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
type QuoteChar = "'" | '"' | "`";
|
||||
|
||||
type QuoteScanState = {
|
||||
quote: QuoteChar | null;
|
||||
escaped: boolean;
|
||||
};
|
||||
|
||||
type RuntimeSourceGuardrailFile = {
|
||||
relativePath: string;
|
||||
source: string;
|
||||
};
|
||||
|
||||
const WEAK_RANDOM_SAME_LINE_PATTERN =
|
||||
/(?:Date\.now[^\r\n]*Math\.random|Math\.random[^\r\n]*Date\.now)/u;
|
||||
const PATH_JOIN_CALL_PATTERN = /path\s*\.\s*join\s*\(/u;
|
||||
const OS_TMPDIR_CALL_PATTERN = /os\s*\.\s*tmpdir\s*\(/u;
|
||||
const FILE_READ_CONCURRENCY = 24;
|
||||
const DEFAULT_GUARDRAIL_SKIP_PATTERNS = [
|
||||
/\.test\.tsx?$/,
|
||||
/\.test-helpers\.tsx?$/,
|
||||
/\.test-utils\.tsx?$/,
|
||||
/\.test-harness\.tsx?$/,
|
||||
/\.test-support\.tsx?$/,
|
||||
/\.suite\.tsx?$/,
|
||||
/\.e2e\.tsx?$/,
|
||||
/\.d\.ts$/,
|
||||
/[\\/](?:__tests__|tests|test-helpers|test-utils|test-support)[\\/]/,
|
||||
/[\\/][^\\/]*test-helpers(?:\.[^\\/]+)?\.ts$/,
|
||||
/[\\/][^\\/]*test-utils(?:\.[^\\/]+)?\.ts$/,
|
||||
/[\\/][^\\/]*test-harness(?:\.[^\\/]+)?\.ts$/,
|
||||
/[\\/][^\\/]*test-support(?:\.[^\\/]+)?\.ts$/,
|
||||
];
|
||||
|
||||
function shouldSkipGuardrailRuntimeSource(relativePath: string): boolean {
|
||||
return DEFAULT_GUARDRAIL_SKIP_PATTERNS.some((pattern) => pattern.test(relativePath));
|
||||
}
|
||||
|
||||
function stripCommentsForScan(input: string): string {
|
||||
return input.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1");
|
||||
}
|
||||
|
||||
function beginQuotedSection(state: QuoteScanState, ch: string): boolean {
|
||||
if (ch !== "'" && ch !== '"' && ch !== "`") {
|
||||
return false;
|
||||
}
|
||||
state.quote = ch;
|
||||
return true;
|
||||
}
|
||||
|
||||
function consumeQuotedChar(state: QuoteScanState, ch: string): boolean {
|
||||
if (!state.quote) {
|
||||
return false;
|
||||
}
|
||||
if (state.escaped) {
|
||||
state.escaped = false;
|
||||
return true;
|
||||
}
|
||||
if (ch === "\\") {
|
||||
state.escaped = true;
|
||||
return true;
|
||||
}
|
||||
if (ch === state.quote) {
|
||||
state.quote = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function findMatchingParen(source: string, openIndex: number): number {
|
||||
let depth = 1;
|
||||
const quoteState: QuoteScanState = { quote: null, escaped: false };
|
||||
for (let i = openIndex + 1; i < source.length; i += 1) {
|
||||
const ch = source[i];
|
||||
if (consumeQuotedChar(quoteState, ch)) {
|
||||
continue;
|
||||
}
|
||||
if (beginQuotedSection(quoteState, ch)) {
|
||||
continue;
|
||||
}
|
||||
if (ch === "(") {
|
||||
depth += 1;
|
||||
continue;
|
||||
}
|
||||
if (ch === ")") {
|
||||
depth -= 1;
|
||||
if (depth === 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function splitTopLevelArguments(source: string): string[] {
|
||||
const out: string[] = [];
|
||||
let current = "";
|
||||
let parenDepth = 0;
|
||||
let bracketDepth = 0;
|
||||
let braceDepth = 0;
|
||||
const quoteState: QuoteScanState = { quote: null, escaped: false };
|
||||
for (const ch of source) {
|
||||
if (quoteState.quote) {
|
||||
current += ch;
|
||||
consumeQuotedChar(quoteState, ch);
|
||||
continue;
|
||||
}
|
||||
if (beginQuotedSection(quoteState, ch)) {
|
||||
current += ch;
|
||||
continue;
|
||||
}
|
||||
if (ch === "(") {
|
||||
parenDepth += 1;
|
||||
current += ch;
|
||||
continue;
|
||||
}
|
||||
if (ch === ")") {
|
||||
if (parenDepth > 0) {
|
||||
parenDepth -= 1;
|
||||
}
|
||||
current += ch;
|
||||
continue;
|
||||
}
|
||||
if (ch === "[") {
|
||||
bracketDepth += 1;
|
||||
current += ch;
|
||||
continue;
|
||||
}
|
||||
if (ch === "]") {
|
||||
if (bracketDepth > 0) {
|
||||
bracketDepth -= 1;
|
||||
}
|
||||
current += ch;
|
||||
continue;
|
||||
}
|
||||
if (ch === "{") {
|
||||
braceDepth += 1;
|
||||
current += ch;
|
||||
continue;
|
||||
}
|
||||
if (ch === "}") {
|
||||
if (braceDepth > 0) {
|
||||
braceDepth -= 1;
|
||||
}
|
||||
current += ch;
|
||||
continue;
|
||||
}
|
||||
if (ch === "," && parenDepth === 0 && bracketDepth === 0 && braceDepth === 0) {
|
||||
out.push(current.trim());
|
||||
current = "";
|
||||
continue;
|
||||
}
|
||||
current += ch;
|
||||
}
|
||||
if (current.trim()) {
|
||||
out.push(current.trim());
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function isOsTmpdirExpression(argument: string): boolean {
|
||||
return /^os\s*\.\s*tmpdir\s*\(\s*\)$/u.test(argument.trim());
|
||||
}
|
||||
|
||||
function mightContainDynamicTmpdirJoin(source: string): boolean {
|
||||
if (!source.includes("path") || !source.includes("join") || !source.includes("tmpdir")) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
(source.includes("path.join") || PATH_JOIN_CALL_PATTERN.test(source)) &&
|
||||
(source.includes("os.tmpdir") || OS_TMPDIR_CALL_PATTERN.test(source)) &&
|
||||
source.includes("`") &&
|
||||
source.includes("${")
|
||||
);
|
||||
}
|
||||
|
||||
function hasDynamicTmpdirJoin(source: string): boolean {
|
||||
if (!mightContainDynamicTmpdirJoin(source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const scanSource = stripCommentsForScan(source);
|
||||
const joinPattern = /path\s*\.\s*join\s*\(/gu;
|
||||
let match: RegExpExecArray | null = joinPattern.exec(scanSource);
|
||||
while (match) {
|
||||
const openParenIndex = scanSource.indexOf("(", match.index);
|
||||
if (openParenIndex !== -1) {
|
||||
const closeParenIndex = findMatchingParen(scanSource, openParenIndex);
|
||||
if (closeParenIndex !== -1) {
|
||||
const argsSource = scanSource.slice(openParenIndex + 1, closeParenIndex);
|
||||
const args = splitTopLevelArguments(argsSource);
|
||||
if (args.length >= 2 && isOsTmpdirExpression(args[0])) {
|
||||
for (const arg of args.slice(1)) {
|
||||
const trimmed = arg.trim();
|
||||
if (trimmed.startsWith("`") && trimmed.includes("${")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
match = joinPattern.exec(scanSource);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function listTrackedRuntimeSourceFiles(repoRoot: string): string[] {
|
||||
const stdout = execFileSync("git", ["-C", repoRoot, "ls-files", "--", "src", "extensions"], {
|
||||
encoding: "utf8",
|
||||
stdio: ["ignore", "pipe", "inherit"],
|
||||
});
|
||||
return stdout
|
||||
.split(/\r?\n/u)
|
||||
.filter(Boolean)
|
||||
.filter((relativePath) => relativePath.endsWith(".ts") || relativePath.endsWith(".tsx"))
|
||||
.filter((relativePath) => !shouldSkipGuardrailRuntimeSource(relativePath))
|
||||
.map((relativePath) => path.join(repoRoot, relativePath));
|
||||
}
|
||||
|
||||
async function readRuntimeSourceFiles(
|
||||
repoRoot: string,
|
||||
absolutePaths: string[],
|
||||
): Promise<RuntimeSourceGuardrailFile[]> {
|
||||
const output: Array<RuntimeSourceGuardrailFile | undefined> = Array.from({
|
||||
length: absolutePaths.length,
|
||||
});
|
||||
let nextIndex = 0;
|
||||
|
||||
const worker = async () => {
|
||||
for (;;) {
|
||||
const index = nextIndex;
|
||||
nextIndex += 1;
|
||||
if (index >= absolutePaths.length) {
|
||||
return;
|
||||
}
|
||||
const absolutePath = absolutePaths[index];
|
||||
if (!absolutePath) {
|
||||
continue;
|
||||
}
|
||||
let source: string;
|
||||
try {
|
||||
source = await fs.readFile(absolutePath, "utf8");
|
||||
} catch {
|
||||
// File tracked by git but deleted on disk (e.g. pending deletion).
|
||||
continue;
|
||||
}
|
||||
output[index] = {
|
||||
relativePath: path.relative(repoRoot, absolutePath),
|
||||
source,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const workers = Array.from(
|
||||
{ length: Math.min(FILE_READ_CONCURRENCY, Math.max(1, absolutePaths.length)) },
|
||||
() => worker(),
|
||||
);
|
||||
await Promise.all(workers);
|
||||
return output.filter((entry): entry is RuntimeSourceGuardrailFile => entry !== undefined);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const repoRoot = process.cwd();
|
||||
const files = await readRuntimeSourceFiles(repoRoot, listTrackedRuntimeSourceFiles(repoRoot));
|
||||
const offenders: string[] = [];
|
||||
const weakRandomMatches: string[] = [];
|
||||
|
||||
for (const file of files) {
|
||||
const source = file.source;
|
||||
const mightContainTmpdirJoin =
|
||||
source.includes("tmpdir") &&
|
||||
source.includes("path") &&
|
||||
source.includes("join") &&
|
||||
source.includes("`");
|
||||
const mightContainWeakRandom = source.includes("Date.now") && source.includes("Math.random");
|
||||
|
||||
if (!mightContainTmpdirJoin && !mightContainWeakRandom) {
|
||||
continue;
|
||||
}
|
||||
if (mightContainTmpdirJoin && hasDynamicTmpdirJoin(source)) {
|
||||
offenders.push(file.relativePath);
|
||||
}
|
||||
if (mightContainWeakRandom && WEAK_RANDOM_SAME_LINE_PATTERN.test(source)) {
|
||||
weakRandomMatches.push(file.relativePath);
|
||||
}
|
||||
}
|
||||
|
||||
if (offenders.length === 0 && weakRandomMatches.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (offenders.length > 0) {
|
||||
console.error("Dynamic os.tmpdir()/path.join() template paths found:");
|
||||
for (const offender of offenders) {
|
||||
console.error(`- ${offender}`);
|
||||
}
|
||||
}
|
||||
if (weakRandomMatches.length > 0) {
|
||||
console.error("Weak Date.now()+Math.random() same-line IDs found:");
|
||||
for (const offender of weakRandomMatches) {
|
||||
console.error(`- ${offender}`);
|
||||
}
|
||||
}
|
||||
process.exitCode = 1;
|
||||
}
|
||||
|
||||
await main();
|
||||
Reference in New Issue
Block a user