clawguard-cli 0.2.0 → 0.2.1
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/dist/index.js +90 -60
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -407,15 +407,6 @@ function checkCredentials(openclawPath) {
|
|
|
407
407
|
} catch {
|
|
408
408
|
}
|
|
409
409
|
}
|
|
410
|
-
const envFiles = [
|
|
411
|
-
path2.join(openclawPath, ".env"),
|
|
412
|
-
path2.join(openclawPath, "workspace", ".env")
|
|
413
|
-
];
|
|
414
|
-
for (const envFile of envFiles) {
|
|
415
|
-
if (fs2.existsSync(envFile)) {
|
|
416
|
-
configFiles.push(envFile);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
410
|
const allHits = [];
|
|
420
411
|
for (const filepath of configFiles) {
|
|
421
412
|
if (fs2.existsSync(filepath)) {
|
|
@@ -430,10 +421,10 @@ function checkCredentials(openclawPath) {
|
|
|
430
421
|
findings.push(
|
|
431
422
|
createFinding({
|
|
432
423
|
severity: Severity.CRITICAL,
|
|
433
|
-
title: `${allHits.length} API key(s) stored in plaintext`,
|
|
424
|
+
title: `${allHits.length} API key(s) stored in plaintext config files`,
|
|
434
425
|
details: allHits.slice(0, 10),
|
|
435
426
|
// Show max 10
|
|
436
|
-
fix: '
|
|
427
|
+
fix: 'Move keys to .env and use env var refs: "apiKey": "${ANTHROPIC_API_KEY}"',
|
|
437
428
|
category: "credentials"
|
|
438
429
|
})
|
|
439
430
|
);
|
|
@@ -518,34 +509,36 @@ function checkCredentials(openclawPath) {
|
|
|
518
509
|
}
|
|
519
510
|
|
|
520
511
|
// src/checks/gateway.ts
|
|
512
|
+
import { execSync } from "child_process";
|
|
521
513
|
import fs3 from "fs";
|
|
522
|
-
import net from "net";
|
|
523
514
|
import path3 from "path";
|
|
524
515
|
import JSON53 from "json5";
|
|
525
516
|
function checkPortExposed(port) {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
resolve(false);
|
|
517
|
+
if (process.platform !== "linux") {
|
|
518
|
+
return false;
|
|
519
|
+
}
|
|
520
|
+
try {
|
|
521
|
+
const output = execSync(`ss -tlnp`, { encoding: "utf-8", timeout: 5e3 });
|
|
522
|
+
const lines = output.split("\n");
|
|
523
|
+
for (const line of lines) {
|
|
524
|
+
const columns = line.trim().split(/\s+/);
|
|
525
|
+
if (columns.length < 5) continue;
|
|
526
|
+
const localAddr = columns[3];
|
|
527
|
+
const lastColon = localAddr.lastIndexOf(":");
|
|
528
|
+
if (lastColon === -1) continue;
|
|
529
|
+
const portStr = localAddr.substring(lastColon + 1);
|
|
530
|
+
if (parseInt(portStr, 10) !== port) continue;
|
|
531
|
+
const host = localAddr.substring(0, lastColon);
|
|
532
|
+
if (host === "0.0.0.0" || host === "*" || host === "[::]" || host === "::") {
|
|
533
|
+
return true;
|
|
534
|
+
}
|
|
545
535
|
}
|
|
546
|
-
|
|
536
|
+
return false;
|
|
537
|
+
} catch {
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
547
540
|
}
|
|
548
|
-
|
|
541
|
+
function checkGateway(openclawPath) {
|
|
549
542
|
const findings = [];
|
|
550
543
|
const configFile = path3.join(openclawPath, "openclaw.json");
|
|
551
544
|
if (!fs3.existsSync(configFile)) {
|
|
@@ -616,7 +609,7 @@ async function checkGateway(openclawPath) {
|
|
|
616
609
|
);
|
|
617
610
|
}
|
|
618
611
|
const port = gateway.port ?? 18789;
|
|
619
|
-
const portExposed =
|
|
612
|
+
const portExposed = checkPortExposed(port);
|
|
620
613
|
if (portExposed) {
|
|
621
614
|
findings.push(
|
|
622
615
|
createFinding({
|
|
@@ -1347,42 +1340,60 @@ function checkAgents(openclawPath) {
|
|
|
1347
1340
|
agentCount++;
|
|
1348
1341
|
const agentName = entry.name;
|
|
1349
1342
|
const keyHits = scanFileForKeys(modelsJsonPath);
|
|
1343
|
+
const openclawUsesEnvRefs = keyHits.length > 0 ? checkOpenclawModelsUseEnvRefs(openclawPath) : false;
|
|
1350
1344
|
if (keyHits.length > 0) {
|
|
1351
|
-
|
|
1352
|
-
const details = keyHits.slice(0, 5).map(
|
|
1353
|
-
(h) => `Line ${h.lineNum}: ${h.keyName} (${h.masked})`
|
|
1354
|
-
);
|
|
1355
|
-
findings.push(
|
|
1356
|
-
createFinding({
|
|
1357
|
-
severity: Severity.CRITICAL,
|
|
1358
|
-
title: `Agent '${agentName}' has plaintext API keys in models.json`,
|
|
1359
|
-
details,
|
|
1360
|
-
fix: `Replace raw keys with env var refs: "apiKey": "\${${PROVIDER_ENV_MAP.anthropic}}"`,
|
|
1361
|
-
category: "agents"
|
|
1362
|
-
})
|
|
1363
|
-
);
|
|
1364
|
-
}
|
|
1365
|
-
try {
|
|
1366
|
-
const content = fs9.readFileSync(modelsJsonPath, {
|
|
1367
|
-
encoding: "utf-8"
|
|
1368
|
-
});
|
|
1369
|
-
const hasEnvRefs = ENV_VAR_PATTERN.test(content);
|
|
1370
|
-
if (keyHits.length > 0 && !hasEnvRefs) {
|
|
1345
|
+
if (openclawUsesEnvRefs) {
|
|
1371
1346
|
findings.push(
|
|
1372
1347
|
createFinding({
|
|
1373
|
-
severity: Severity.
|
|
1374
|
-
title: `Agent '${agentName}'
|
|
1348
|
+
severity: Severity.INFO,
|
|
1349
|
+
title: `Agent '${agentName}': models.json contains resolved keys (auto-generated)`,
|
|
1375
1350
|
details: [
|
|
1376
|
-
"models.json contains
|
|
1377
|
-
"
|
|
1351
|
+
"models.json contains resolved API keys, but openclaw.json uses ${ENV_VAR} references",
|
|
1352
|
+
"OpenClaw regenerates models.json from openclaw.json on every gateway startup",
|
|
1353
|
+
"This is expected behavior \u2014 no action needed"
|
|
1378
1354
|
],
|
|
1379
|
-
fix: 'Run "clawguard migrate-env" to auto-migrate keys to .env',
|
|
1380
1355
|
category: "agents"
|
|
1381
1356
|
})
|
|
1382
1357
|
);
|
|
1358
|
+
} else {
|
|
1383
1359
|
issueCount++;
|
|
1360
|
+
const details = keyHits.slice(0, 5).map(
|
|
1361
|
+
(h) => `Line ${h.lineNum}: ${h.keyName} (${h.masked})`
|
|
1362
|
+
);
|
|
1363
|
+
findings.push(
|
|
1364
|
+
createFinding({
|
|
1365
|
+
severity: Severity.CRITICAL,
|
|
1366
|
+
title: `Agent '${agentName}' has plaintext API keys in models.json`,
|
|
1367
|
+
details,
|
|
1368
|
+
fix: `Replace raw keys with env var refs: "apiKey": "\${${PROVIDER_ENV_MAP.anthropic}}"`,
|
|
1369
|
+
category: "agents"
|
|
1370
|
+
})
|
|
1371
|
+
);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
if (!openclawUsesEnvRefs) {
|
|
1375
|
+
try {
|
|
1376
|
+
const content = fs9.readFileSync(modelsJsonPath, {
|
|
1377
|
+
encoding: "utf-8"
|
|
1378
|
+
});
|
|
1379
|
+
const hasEnvRefs = ENV_VAR_PATTERN.test(content);
|
|
1380
|
+
if (keyHits.length > 0 && !hasEnvRefs) {
|
|
1381
|
+
findings.push(
|
|
1382
|
+
createFinding({
|
|
1383
|
+
severity: Severity.HIGH,
|
|
1384
|
+
title: `Agent '${agentName}' uses raw keys instead of env var references`,
|
|
1385
|
+
details: [
|
|
1386
|
+
"models.json contains no ${ENV_VAR} references",
|
|
1387
|
+
"All API keys should use environment variable substitution"
|
|
1388
|
+
],
|
|
1389
|
+
fix: 'Run "clawguard migrate-env" to auto-migrate keys to .env',
|
|
1390
|
+
category: "agents"
|
|
1391
|
+
})
|
|
1392
|
+
);
|
|
1393
|
+
issueCount++;
|
|
1394
|
+
}
|
|
1395
|
+
} catch {
|
|
1384
1396
|
}
|
|
1385
|
-
} catch {
|
|
1386
1397
|
}
|
|
1387
1398
|
if (globalModel) {
|
|
1388
1399
|
const agentModel = getAgentModel(modelsJsonPath);
|
|
@@ -1432,6 +1443,25 @@ function getGlobalModel(config) {
|
|
|
1432
1443
|
}
|
|
1433
1444
|
return null;
|
|
1434
1445
|
}
|
|
1446
|
+
function checkOpenclawModelsUseEnvRefs(openclawPath) {
|
|
1447
|
+
try {
|
|
1448
|
+
const configPath = path9.join(openclawPath, "openclaw.json");
|
|
1449
|
+
const content = fs9.readFileSync(configPath, { encoding: "utf-8" });
|
|
1450
|
+
const config = JSON.parse(content);
|
|
1451
|
+
const models = config.models;
|
|
1452
|
+
if (!models) return false;
|
|
1453
|
+
const providers = models.providers;
|
|
1454
|
+
if (!providers) return false;
|
|
1455
|
+
for (const provider of Object.values(providers)) {
|
|
1456
|
+
const apiKey = String(provider.apiKey ?? provider.key ?? "");
|
|
1457
|
+
if (ENV_VAR_PATTERN.test(apiKey)) {
|
|
1458
|
+
return true;
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
} catch {
|
|
1462
|
+
}
|
|
1463
|
+
return false;
|
|
1464
|
+
}
|
|
1435
1465
|
function getAgentModel(modelsJsonPath) {
|
|
1436
1466
|
try {
|
|
1437
1467
|
const content = fs9.readFileSync(modelsJsonPath, { encoding: "utf-8" });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/models.ts","../src/reporter.ts","../src/scanner.ts","../src/checks/credentials.ts","../src/patterns.ts","../src/utils.ts","../src/checks/gateway.ts","../src/checks/sandbox.ts","../src/checks/permissions.ts","../src/checks/version.ts","../src/checks/skills.ts","../src/checks/memory.ts","../src/checks/agents.ts","../src/checks/providers.ts"],"sourcesContent":["/**\n * ClawGuard CLI - Security scanner for OpenClaw installations.\n */\n\nimport fs from \"node:fs\";\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { getCriticalCount } from \"./models.js\";\nimport { printBanner, printJson, printReport } from \"./reporter.js\";\nimport {\n CHECK_REGISTRY,\n detectOpenclawPath,\n runFix,\n runMigrateEnv,\n runScan,\n} from \"./scanner.js\";\n\nconst VERSION = \"0.2.0\";\n\nconst program = new Command();\n\nprogram\n .name(\"clawguard\")\n .description(\"Security scanner for OpenClaw AI agent installations\")\n .version(VERSION);\n\nprogram\n .command(\"scan\")\n .description(\"Scan your OpenClaw installation for security issues\")\n .option(\"-p, --path <path>\", \"Path to OpenClaw directory\")\n .option(\"-f, --format <format>\", \"Output format: rich or json\", \"rich\")\n .option(\n \"-c, --check <checks...>\",\n \"Run specific checks only\"\n )\n .action(\n async (options: {\n path?: string;\n format: string;\n check?: string[];\n }) => {\n // Detect or use provided path\n const openclawPath = options.path ?? detectOpenclawPath();\n\n if (!openclawPath) {\n console.log(chalk.red(\"Could not find OpenClaw installation.\"));\n console.log(\"Checked: ~/.openclaw, ~/.clawdbot, ~/.moltbot\");\n console.log(\"Use --path to specify the directory.\");\n process.exit(1);\n }\n\n if (!fs.existsSync(openclawPath)) {\n console.log(chalk.red(`Path does not exist: ${openclawPath}`));\n process.exit(1);\n }\n\n // Validate check names\n if (options.check) {\n const validChecks = new Set(Object.keys(CHECK_REGISTRY));\n for (const c of options.check) {\n if (!validChecks.has(c)) {\n console.log(chalk.red(`Unknown check: ${c}`));\n console.log(\n `Available: ${[...validChecks].sort().join(\", \")}`\n );\n process.exit(1);\n }\n }\n }\n\n // Run scan\n const result = await runScan(openclawPath, options.check);\n\n // Output\n if (options.format === \"json\") {\n printJson(result);\n } else {\n printReport(result);\n }\n\n // Exit with non-zero if critical issues found\n if (getCriticalCount(result) > 0) {\n process.exit(2);\n }\n }\n );\n\nprogram\n .command(\"fix\")\n .description(\n \"Auto-fix common security issues in your OpenClaw installation\"\n )\n .option(\"-p, --path <path>\", \"Path to OpenClaw directory\")\n .action((options: { path?: string }) => {\n const openclawPath = options.path ?? detectOpenclawPath();\n\n if (!openclawPath) {\n console.log(chalk.red(\"Could not find OpenClaw installation.\"));\n process.exit(1);\n }\n\n printBanner();\n console.log(\n `\\nFixing security issues in ${chalk.bold(openclawPath)} ...\\n`\n );\n\n const actions = runFix(openclawPath);\n\n if (actions.length > 0) {\n for (const action of actions) {\n console.log(` ${chalk.green(\"FIXED\")} ${action}`);\n }\n console.log(chalk.green(`\\n${actions.length} issue(s) fixed.`));\n console.log(\n `Run ${chalk.bold(\"clawguard scan\")} to verify.\\n`\n );\n } else {\n console.log(chalk.green(\"No auto-fixable issues found.\\n\"));\n }\n });\n\nprogram\n .command(\"migrate-env\")\n .description(\n \"Migrate plaintext API keys from config files to .env with ${REF} substitution\"\n )\n .option(\"-p, --path <path>\", \"Path to OpenClaw directory\")\n .option(\"--dry-run\", \"Show what would be migrated without making changes\")\n .action((options: { path?: string; dryRun?: boolean }) => {\n const openclawPath = options.path ?? detectOpenclawPath();\n\n if (!openclawPath) {\n console.log(chalk.red(\"Could not find OpenClaw installation.\"));\n process.exit(1);\n }\n\n if (!fs.existsSync(openclawPath)) {\n console.log(chalk.red(`Path does not exist: ${openclawPath}`));\n process.exit(1);\n }\n\n const dryRun = options.dryRun ?? false;\n if (dryRun) {\n console.log(chalk.cyan(\"\\n-- DRY RUN (no files will be modified) --\\n\"));\n }\n\n const result = runMigrateEnv(openclawPath, dryRun);\n\n if (result.migrations.length === 0) {\n console.log(chalk.green(\"No plaintext API keys found to migrate.\"));\n return;\n }\n\n console.log(\n chalk.bold(`\\nFound ${result.migrations.length} key(s) to migrate:\\n`)\n );\n\n for (const m of result.migrations) {\n console.log(\n ` ${chalk.cyan(m.envVar)} <- ${m.key} (${chalk.dim(m.file)})`\n );\n }\n\n if (dryRun) {\n console.log(\n chalk.cyan(\"\\nRun without --dry-run to apply these changes.\")\n );\n } else {\n console.log();\n if (result.envFileCreated) {\n console.log(\n chalk.green(\" Created/updated .env file (chmod 600)\")\n );\n }\n for (const f of result.configsUpdated) {\n console.log(\n chalk.green(` Updated ${f} with \\${ENV_VAR} references`)\n );\n }\n console.log(\n chalk.green(\n `\\n${result.migrations.length} key(s) migrated successfully.`\n )\n );\n console.log(\n `Run ${chalk.bold(\"clawguard scan\")} to verify.\\n`\n );\n }\n });\n\nprogram\n .command(\"version\")\n .description(\"Show ClawGuard version\")\n .action(() => {\n console.log(`ClawGuard v${VERSION}`);\n });\n\nprogram.parse();\n","/**\n * Data models for ClawGuard scan results.\n */\n\nimport { z } from \"zod\";\n\nexport const Severity = {\n CRITICAL: \"CRITICAL\",\n HIGH: \"HIGH\",\n MEDIUM: \"MEDIUM\",\n INFO: \"INFO\",\n} as const;\n\nexport type Severity = (typeof Severity)[keyof typeof Severity];\n\nexport const SEVERITY_DEDUCTIONS: Record<Severity, number> = {\n [Severity.CRITICAL]: 20,\n [Severity.HIGH]: 10,\n [Severity.MEDIUM]: 5,\n [Severity.INFO]: 0,\n};\n\nexport const FindingSchema = z.object({\n severity: z.enum([\"CRITICAL\", \"HIGH\", \"MEDIUM\", \"INFO\"]),\n title: z.string(),\n details: z.array(z.string()).default([]),\n fix: z.string().default(\"\"),\n category: z.string().default(\"\"),\n});\n\nexport type Finding = z.infer<typeof FindingSchema>;\n\nexport function createFinding(params: {\n severity: Severity;\n title: string;\n details?: string[];\n fix?: string;\n category?: string;\n}): Finding {\n return {\n severity: params.severity,\n title: params.title,\n details: params.details ?? [],\n fix: params.fix ?? \"\",\n category: params.category ?? \"\",\n };\n}\n\nexport interface ScanResult {\n findings: Finding[];\n openclawPath: string;\n openclawVersion: string | null;\n nodeVersion: string | null;\n}\n\nexport function createScanResult(\n openclawPath: string = \"\"\n): ScanResult {\n return {\n findings: [],\n openclawPath,\n openclawVersion: null,\n nodeVersion: null,\n };\n}\n\nexport function getScore(result: ScanResult): number {\n let total = 100;\n for (const f of result.findings) {\n total -= SEVERITY_DEDUCTIONS[f.severity];\n }\n return Math.max(0, total);\n}\n\nexport function getCriticalCount(result: ScanResult): number {\n return result.findings.filter((f) => f.severity === Severity.CRITICAL).length;\n}\n\nexport function getHighCount(result: ScanResult): number {\n return result.findings.filter((f) => f.severity === Severity.HIGH).length;\n}\n\nexport function getMediumCount(result: ScanResult): number {\n return result.findings.filter((f) => f.severity === Severity.MEDIUM).length;\n}\n\nexport function getInfoCount(result: ScanResult): number {\n return result.findings.filter((f) => f.severity === Severity.INFO).length;\n}\n","/**\n * Chalk-formatted output for ClawGuard scan results.\n */\n\nimport chalk from \"chalk\";\nimport {\n type Finding,\n type ScanResult,\n Severity,\n getScore,\n getCriticalCount,\n getHighCount,\n getMediumCount,\n getInfoCount,\n} from \"./models.js\";\n\nconst VERSION = \"0.2.0\";\n\nconst SEVERITY_COLORS: Record<Severity, (text: string) => string> = {\n [Severity.CRITICAL]: chalk.red.bold,\n [Severity.HIGH]: chalk.yellow.bold,\n [Severity.MEDIUM]: chalk.cyan.bold,\n [Severity.INFO]: chalk.green.bold,\n};\n\nfunction getScoreStyle(score: number): (text: string) => string {\n if (score <= 30) return chalk.red.bold;\n if (score <= 60) return chalk.yellow.bold;\n if (score <= 80) return chalk.cyan.bold;\n return chalk.green.bold;\n}\n\nfunction getScoreLabel(score: number): string {\n if (score <= 30) return \"Critical Risk\";\n if (score <= 60) return \"High Risk\";\n if (score <= 80) return \"Moderate Risk\";\n return \"Low Risk\";\n}\n\nexport function printBanner(): void {\n const banner = `${chalk.white.bold(\"ClawGuard\")}${chalk.dim(` v${VERSION}`)}${chalk.white(\" - OpenClaw Security Scanner\")}`;\n const border = chalk.blue(\"+\" + \"-\".repeat(banner.length - 20) + \"+\");\n console.log(border);\n console.log(chalk.blue(\"|\") + \" \" + banner + \" \" + chalk.blue(\"|\"));\n console.log(border);\n}\n\nexport function printFinding(finding: Finding): void {\n const colorFn = SEVERITY_COLORS[finding.severity];\n const severityTag = colorFn(finding.severity);\n\n console.log(`\\n ${severityTag} ${finding.title}`);\n for (const detail of finding.details) {\n console.log(chalk.dim(` ${detail}`));\n }\n if (finding.fix) {\n console.log(chalk.italic(` Fix: ${finding.fix}`));\n }\n}\n\nexport function printReport(result: ScanResult): void {\n printBanner();\n console.log(`\\nScanning ${chalk.bold(result.openclawPath)} ...\\n`);\n\n if (result.findings.length === 0) {\n console.log(chalk.green(\"No security issues found!\"));\n console.log(`\\nScore: ${chalk.green.bold(\"100/100 (Secure)\")}`);\n return;\n }\n\n // Sort: CRITICAL first, then HIGH, MEDIUM, INFO\n const severityOrder: Record<Severity, number> = {\n [Severity.CRITICAL]: 0,\n [Severity.HIGH]: 1,\n [Severity.MEDIUM]: 2,\n [Severity.INFO]: 3,\n };\n\n const sortedFindings = [...result.findings].sort(\n (a, b) => severityOrder[a.severity] - severityOrder[b.severity]\n );\n\n for (const finding of sortedFindings) {\n printFinding(finding);\n }\n\n // Summary\n console.log(\"\\n\" + \"=\".repeat(50));\n\n const score = getScore(result);\n const style = getScoreStyle(score);\n const label = getScoreLabel(score);\n console.log(`\\n Score: ${style(`${score}/100 (${label})`)}`);\n\n const summaryParts: string[] = [];\n const critical = getCriticalCount(result);\n const high = getHighCount(result);\n const medium = getMediumCount(result);\n const info = getInfoCount(result);\n\n if (critical) summaryParts.push(chalk.red(`${critical} critical`));\n if (high) summaryParts.push(chalk.yellow(`${high} high`));\n if (medium) summaryParts.push(chalk.cyan(`${medium} medium`));\n if (info) summaryParts.push(chalk.green(`${info} info`));\n\n console.log(` Found: ${summaryParts.join(\", \")}`);\n\n const fixable = result.findings.filter(\n (f) => f.fix && f.severity !== Severity.INFO\n ).length;\n if (fixable) {\n console.log(\n ` Run ${chalk.bold(\"clawguard fix\")} to auto-fix ${fixable} issues`\n );\n }\n\n console.log();\n}\n\nexport function printJson(result: ScanResult): void {\n const output = {\n score: getScore(result),\n openclaw_path: result.openclawPath,\n openclaw_version: result.openclawVersion,\n node_version: result.nodeVersion,\n summary: {\n critical: getCriticalCount(result),\n high: getHighCount(result),\n medium: getMediumCount(result),\n info: getInfoCount(result),\n },\n findings: result.findings.map((f) => ({\n severity: f.severity,\n title: f.title,\n details: f.details,\n fix: f.fix,\n category: f.category,\n })),\n };\n console.log(JSON.stringify(output, null, 2));\n}\n","/**\n * Main scanner orchestrator - runs all security checks.\n */\n\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport JSON5 from \"json5\";\nimport chalk from \"chalk\";\nimport { type Finding, type ScanResult, createScanResult } from \"./models.js\";\nimport { checkCredentials } from \"./checks/credentials.js\";\nimport { checkGateway } from \"./checks/gateway.js\";\nimport { checkSandbox } from \"./checks/sandbox.js\";\nimport { checkPermissions } from \"./checks/permissions.js\";\nimport { checkVersion } from \"./checks/version.js\";\nimport { checkSkills } from \"./checks/skills.js\";\nimport { checkMemory } from \"./checks/memory.js\";\nimport { checkAgents } from \"./checks/agents.js\";\nimport { checkProviders } from \"./checks/providers.js\";\nimport { API_KEY_PATTERNS, PROVIDER_ENV_MAP } from \"./patterns.js\";\nimport {\n findFilesRecursive,\n isDockerAvailable,\n parseConfig,\n getTotalMemoryGB,\n scanFileForKeys,\n} from \"./utils.js\";\n\ntype SyncCheckFn = (openclawPath: string) => Finding[];\ntype AsyncCheckFn = (openclawPath: string) => Promise<Finding[]>;\ntype CheckFn = SyncCheckFn | AsyncCheckFn;\n\n/** Map of check names to their functions */\nexport const CHECK_REGISTRY: Record<string, CheckFn> = {\n credentials: checkCredentials,\n gateway: checkGateway,\n sandbox: checkSandbox,\n permissions: checkPermissions,\n skills: checkSkills,\n memory: checkMemory,\n agents: checkAgents,\n providers: checkProviders,\n};\n\nexport function detectOpenclawPath(): string | null {\n const candidates: string[] = [\n path.join(os.homedir(), \".openclaw\"),\n path.join(os.homedir(), \".clawdbot\"), // Legacy name\n path.join(os.homedir(), \".moltbot\"), // Legacy name\n ];\n\n const envPath = process.env.OPENCLAW_HOME;\n if (envPath) {\n candidates.unshift(envPath);\n }\n\n for (const candidate of candidates) {\n if (\n fs.existsSync(candidate) &&\n fs.statSync(candidate).isDirectory()\n ) {\n return candidate;\n }\n }\n\n return null;\n}\n\nexport async function runScan(\n openclawPath: string,\n checks?: string[]\n): Promise<ScanResult> {\n const result = createScanResult(openclawPath);\n\n // Version check (always runs, returns version info)\n process.stdout.write(chalk.blue(\"Checking versions...\\r\"));\n const {\n findings: versionFindings,\n openclawVersion,\n nodeVersion,\n } = checkVersion(openclawPath);\n result.findings.push(...versionFindings);\n result.openclawVersion = openclawVersion;\n result.nodeVersion = nodeVersion;\n\n // Run selected or all checks\n const activeChecks = checks ?? Object.keys(CHECK_REGISTRY);\n\n for (const checkName of activeChecks) {\n if (!(checkName in CHECK_REGISTRY)) {\n continue;\n }\n\n const checkFn = CHECK_REGISTRY[checkName];\n const label = checkName.replace(/_/g, \" \").replace(/\\b\\w/g, (c) => c.toUpperCase());\n\n process.stdout.write(chalk.blue(`Checking ${label}...\\r`));\n try {\n const findings = await checkFn(openclawPath);\n result.findings.push(...findings);\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n console.log(chalk.yellow(`Warning: ${checkName} check failed: ${message}`));\n }\n }\n\n // Clear the status line\n process.stdout.write(\" \\r\");\n\n return result;\n}\n\nexport function runFix(openclawPath: string): string[] {\n const actions: string[] = [];\n\n // Fix 1: File permissions\n if (fs.existsSync(openclawPath)) {\n const currentMode = fs.statSync(openclawPath).mode & 0o777;\n const current = \"0o\" + currentMode.toString(8);\n if (current !== \"0o700\") {\n fs.chmodSync(openclawPath, 0o700);\n actions.push(`Fixed ${openclawPath} permissions: ${current} -> 0o700`);\n }\n }\n\n const configFile = path.join(openclawPath, \"openclaw.json\");\n if (fs.existsSync(configFile)) {\n const currentMode = fs.statSync(configFile).mode & 0o777;\n const current = \"0o\" + currentMode.toString(8);\n if (current !== \"0o600\") {\n fs.chmodSync(configFile, 0o600);\n actions.push(\n `Fixed ${path.basename(configFile)} permissions: ${current} -> 0o600`\n );\n }\n }\n\n const credsDir = path.join(openclawPath, \"credentials\");\n if (fs.existsSync(credsDir) && fs.statSync(credsDir).isDirectory()) {\n try {\n const entries = fs.readdirSync(credsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isFile()) {\n const filePath = path.join(credsDir, entry.name);\n const currentMode = fs.statSync(filePath).mode & 0o777;\n const current = \"0o\" + currentMode.toString(8);\n if (current !== \"0o600\") {\n fs.chmodSync(filePath, 0o600);\n actions.push(\n `Fixed ${entry.name} permissions: ${current} -> 0o600`\n );\n }\n }\n }\n } catch {\n // Ignore errors\n }\n }\n\n // Fix 2: Config changes (sandbox-aware)\n if (fs.existsSync(configFile)) {\n try {\n const content = fs.readFileSync(configFile, { encoding: \"utf-8\" });\n const config = JSON5.parse(content) as Record<string, Record<string, unknown>>;\n\n let modified = false;\n const dockerInstalled = isDockerAvailable();\n\n // Sandbox changes: only apply if Docker is available\n if (dockerInstalled) {\n // Enable sandbox\n if (!config.agents) config.agents = {};\n const agents = config.agents as Record<string, Record<string, unknown>>;\n if (!agents.defaults) agents.defaults = {};\n const defaults = agents.defaults as Record<string, Record<string, unknown>>;\n if (!defaults.sandbox) defaults.sandbox = {};\n const sandbox = defaults.sandbox as Record<string, unknown>;\n\n if ((sandbox.mode as string) === \"off\" || !sandbox.mode) {\n sandbox.mode = \"all\";\n sandbox.scope = \"session\";\n modified = true;\n actions.push('Enabled sandbox: agents.defaults.sandbox.mode = \"all\"');\n }\n\n // Set Docker network to none\n if (!sandbox.docker) sandbox.docker = {};\n const docker = sandbox.docker as Record<string, unknown>;\n if (docker.network !== \"none\") {\n docker.network = \"none\";\n modified = true;\n actions.push('Set sandbox.docker.network = \"none\"');\n }\n\n // Ensure exec host is sandbox\n if (!config.tools) config.tools = {};\n const tools = config.tools as Record<string, Record<string, unknown>>;\n if (!tools.exec) tools.exec = {};\n const execConfig = tools.exec as Record<string, unknown>;\n if (execConfig.host === \"gateway\") {\n execConfig.host = \"sandbox\";\n modified = true;\n actions.push('Set tools.exec.host = \"sandbox\"');\n }\n } else {\n actions.push(\n chalk.yellow(\"Sandbox changes skipped: Docker not installed. Install Docker to enable sandbox isolation.\")\n );\n }\n\n // Always apply safe fixes regardless of Docker\n\n // Enable logging redaction\n if (!config.logging) config.logging = {};\n const loggingConfig = config.logging as Record<string, unknown>;\n if (\n loggingConfig.redactSensitive === undefined ||\n loggingConfig.redactSensitive === null ||\n loggingConfig.redactSensitive === \"off\"\n ) {\n loggingConfig.redactSensitive = \"tools\";\n modified = true;\n actions.push('Enabled logging.redactSensitive = \"tools\"');\n }\n\n // Generate strong gateway token if missing/weak\n if (!config.gateway) config.gateway = {};\n const gateway = config.gateway as Record<string, Record<string, unknown>>;\n if (!gateway.auth) gateway.auth = {};\n const auth = gateway.auth as Record<string, unknown>;\n const token = auth.token as string | undefined;\n if (!token || String(token).length < 32) {\n const newToken = crypto.randomBytes(32).toString(\"hex\");\n auth.token = newToken;\n modified = true;\n actions.push(\n `Generated strong gateway token (${newToken.length} chars)`\n );\n }\n\n if (modified) {\n fs.writeFileSync(configFile, JSON.stringify(config, null, 2));\n }\n\n // Post-fix warnings\n const ramGB = getTotalMemoryGB();\n if (ramGB < 2) {\n actions.push(\n chalk.yellow(`Warning: System has only ${ramGB.toFixed(1)}GB RAM. Set NODE_OPTIONS=\"--max-old-space-size=512\" to prevent OOM kills.`)\n );\n }\n\n // Suggest migrate-env if plaintext keys found\n const hits = scanFileForKeys(configFile);\n if (hits.length > 0) {\n actions.push(\n `Tip: Run ${chalk.bold(\"clawguard migrate-env\")} to move ${hits.length} plaintext key(s) to .env`\n );\n }\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n actions.push(`Could not modify config: ${message}`);\n }\n }\n\n // Fix 3: Delete .bak files\n const bakFiles = findFilesRecursive(openclawPath, \".bak\", \"extension\");\n for (const bakFile of bakFiles) {\n fs.unlinkSync(bakFile);\n actions.push(`Deleted backup file: ${path.basename(bakFile)}`);\n }\n\n return actions;\n}\n\nexport interface MigrateEnvResult {\n migrations: Array<{ file: string; key: string; envVar: string }>;\n envFileCreated: boolean;\n configsUpdated: string[];\n}\n\nexport function runMigrateEnv(\n openclawPath: string,\n dryRun = false\n): MigrateEnvResult {\n const result: MigrateEnvResult = {\n migrations: [],\n envFileCreated: false,\n configsUpdated: [],\n };\n\n // Collect all config files to process\n const configFiles: string[] = [];\n const mainConfig = path.join(openclawPath, \"openclaw.json\");\n if (fs.existsSync(mainConfig)) {\n configFiles.push(mainConfig);\n }\n\n // Find all agent models.json files\n const agentsDir = path.join(openclawPath, \"agents\");\n const modelsFiles = findFilesRecursive(agentsDir, \"models.json\", \"exact\");\n configFiles.push(...modelsFiles);\n\n // Build a map of raw key values -> env var names\n const keyToEnvVar = new Map<string, string>();\n\n for (const configFile of configFiles) {\n try {\n const content = fs.readFileSync(configFile, { encoding: \"utf-8\" });\n const lines = content.split(\"\\n\");\n\n for (const line of lines) {\n // Skip lines already using env var references\n if (/\\$\\{[A-Z_][A-Z0-9_]*\\}/.test(line)) continue;\n\n for (const [keyName, pattern] of API_KEY_PATTERNS) {\n const globalPattern = new RegExp(\n pattern.source,\n pattern.flags + (pattern.flags.includes(\"g\") ? \"\" : \"g\")\n );\n let match: RegExpExecArray | null;\n\n while ((match = globalPattern.exec(line)) !== null) {\n const rawKey = match[0];\n if (keyToEnvVar.has(rawKey)) continue;\n\n // Determine env var name from key type\n const envVar = guessEnvVarName(keyName, line);\n keyToEnvVar.set(rawKey, envVar);\n result.migrations.push({\n file: path.relative(openclawPath, configFile),\n key: rawKey.slice(0, 8) + \"...\" + rawKey.slice(-4),\n envVar,\n });\n }\n }\n }\n } catch {\n // Ignore read errors\n }\n }\n\n if (result.migrations.length === 0) {\n return result;\n }\n\n if (dryRun) {\n return result;\n }\n\n // Create/append .env file\n const envFilePath = path.join(openclawPath, \".env\");\n const existingEnv = fs.existsSync(envFilePath)\n ? fs.readFileSync(envFilePath, { encoding: \"utf-8\" })\n : \"\";\n const existingKeys = new Set(\n existingEnv\n .split(\"\\n\")\n .filter((l) => l.includes(\"=\"))\n .map((l) => l.split(\"=\")[0].trim())\n );\n\n const newEnvLines: string[] = [];\n for (const [rawKey, envVar] of keyToEnvVar) {\n if (!existingKeys.has(envVar)) {\n newEnvLines.push(`${envVar}=${rawKey}`);\n }\n }\n\n if (newEnvLines.length > 0) {\n const separator = existingEnv.endsWith(\"\\n\") || existingEnv === \"\" ? \"\" : \"\\n\";\n fs.appendFileSync(envFilePath, separator + newEnvLines.join(\"\\n\") + \"\\n\");\n result.envFileCreated = true;\n\n // Set permissions on .env\n try {\n fs.chmodSync(envFilePath, 0o600);\n } catch {\n // May fail on some systems\n }\n }\n\n // Replace plaintext keys in config files with ${ENV_VAR_NAME}\n for (const configFile of configFiles) {\n try {\n let content = fs.readFileSync(configFile, { encoding: \"utf-8\" });\n let modified = false;\n\n for (const [rawKey, envVar] of keyToEnvVar) {\n if (content.includes(rawKey)) {\n content = content.split(rawKey).join(`\\${${envVar}}`);\n modified = true;\n }\n }\n\n if (modified) {\n fs.writeFileSync(configFile, content);\n result.configsUpdated.push(\n path.relative(openclawPath, configFile)\n );\n }\n } catch {\n // Ignore write errors\n }\n }\n\n return result;\n}\n\nfunction guessEnvVarName(keyName: string, contextLine: string): string {\n const lower = keyName.toLowerCase();\n\n // Check PROVIDER_ENV_MAP first\n for (const [provider, envVar] of Object.entries(PROVIDER_ENV_MAP)) {\n if (lower.includes(provider)) return envVar;\n }\n\n // Try to guess from JSON key context\n if (contextLine.includes(\"telegram\")) return \"TELEGRAM_BOT_TOKEN\";\n if (contextLine.includes(\"discord\")) return \"DISCORD_BOT_TOKEN\";\n if (contextLine.includes(\"slack\")) return \"SLACK_BOT_TOKEN\";\n if (contextLine.includes(\"brave\") || contextLine.includes(\"webSearch\"))\n return \"BRAVE_SEARCH_API_KEY\";\n if (contextLine.includes(\"stripe\")) return \"STRIPE_SECRET_KEY\";\n\n // Fallback: generate from key name\n return keyName.toUpperCase().replace(/[\\s/]/g, \"_\").replace(/[^A-Z0-9_]/g, \"\");\n}\n","/**\n * Scan for plaintext credentials in OpenClaw configuration files.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport JSON5 from \"json5\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\nimport { API_KEY_PATTERNS } from \"../patterns.js\";\nimport {\n findFilesRecursive,\n getRelativePath,\n scanFileForKeys,\n} from \"../utils.js\";\n\nexport function checkCredentials(openclawPath: string): Finding[] {\n const findings: Finding[] = [];\n\n // Files to scan for plaintext API keys\n const configFiles: string[] = [\n path.join(openclawPath, \"openclaw.json\"),\n path.join(openclawPath, \"credentials\", \"profiles.json\"),\n ];\n\n // Add all auth-profiles.json files\n const agentsDir = path.join(openclawPath, \"agents\");\n if (fs.existsSync(agentsDir) && fs.statSync(agentsDir).isDirectory()) {\n try {\n for (const agentEntry of fs.readdirSync(agentsDir)) {\n const authFile = path.join(\n agentsDir,\n agentEntry,\n \"agent\",\n \"auth-profiles.json\"\n );\n if (fs.existsSync(authFile)) {\n configFiles.push(authFile);\n }\n }\n } catch {\n // Ignore permission errors\n }\n }\n\n // Add .env files\n const envFiles = [\n path.join(openclawPath, \".env\"),\n path.join(openclawPath, \"workspace\", \".env\"),\n ];\n for (const envFile of envFiles) {\n if (fs.existsSync(envFile)) {\n configFiles.push(envFile);\n }\n }\n\n // Scan config files\n const allHits: string[] = [];\n for (const filepath of configFiles) {\n if (fs.existsSync(filepath)) {\n const hits = scanFileForKeys(filepath);\n for (const { keyName, masked, lineNum } of hits) {\n const relPath = getRelativePath(filepath, openclawPath);\n allHits.push(`${relPath}:${lineNum} - ${keyName} (${masked})`);\n }\n }\n }\n\n if (allHits.length > 0) {\n findings.push(\n createFinding({\n severity: Severity.CRITICAL,\n title: `${allHits.length} API key(s) stored in plaintext`,\n details: allHits.slice(0, 10), // Show max 10\n fix: 'Use environment variables: \"apiKey\": \"${ANTHROPIC_API_KEY}\" instead of raw strings',\n category: \"credentials\",\n })\n );\n }\n\n // Check for .bak files with credentials\n const bakWithKeys: string[] = [];\n const bakFiles = findFilesRecursive(openclawPath, \".bak\", \"extension\");\n for (const bakFile of bakFiles) {\n const hits = scanFileForKeys(bakFile);\n if (hits.length > 0) {\n bakWithKeys.push(getRelativePath(bakFile, openclawPath));\n }\n }\n\n if (bakWithKeys.length > 0) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `${bakWithKeys.length} backup file(s) contain credentials`,\n details: bakWithKeys,\n fix: \"Delete backup files: rm ~/.openclaw/*.bak\",\n category: \"credentials\",\n })\n );\n }\n\n // Scan transcript files for leaked secrets\n const transcriptHits: string[] = [];\n if (fs.existsSync(agentsDir) && fs.statSync(agentsDir).isDirectory()) {\n const jsonlFiles = findFilesRecursive(agentsDir, \".jsonl\", \"extension\");\n for (const jsonlFile of jsonlFiles) {\n try {\n const content = fs.readFileSync(jsonlFile, { encoding: \"utf-8\" });\n const lines = content.split(\"\\n\");\n let found = false;\n\n for (let i = 0; i < Math.min(lines.length, 501); i++) {\n const line = lines[i];\n for (const [keyName, pattern] of API_KEY_PATTERNS) {\n if (pattern.test(line)) {\n transcriptHits.push(\n `${getRelativePath(jsonlFile, openclawPath)} - ${keyName} found in transcript`\n );\n found = true;\n break;\n }\n }\n if (found) break;\n }\n } catch {\n // Ignore permission errors\n }\n }\n }\n\n if (transcriptHits.length > 0) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `API keys leaked in ${transcriptHits.length} session transcript(s)`,\n details: transcriptHits.slice(0, 5),\n fix: \"Delete old transcripts and enable logging.redactSensitive in config\",\n category: \"credentials\",\n })\n );\n }\n\n // Check logging redaction settings\n const configFile = path.join(openclawPath, \"openclaw.json\");\n if (fs.existsSync(configFile)) {\n try {\n const content = fs.readFileSync(configFile, { encoding: \"utf-8\" });\n const config = JSON5.parse(content) as Record<string, unknown>;\n const loggingConfig = (config.logging ?? {}) as Record<string, unknown>;\n const redact = loggingConfig.redactSensitive;\n\n if (redact === undefined || redact === null || redact === \"off\") {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: \"Sensitive data redaction is disabled in logs\",\n details: ['logging.redactSensitive is not set or set to \"off\"'],\n fix: 'Set logging.redactSensitive to \"tools\" or \"all\" in openclaw.json',\n category: \"credentials\",\n })\n );\n }\n } catch {\n // Ignore parse errors\n }\n }\n\n return findings;\n}\n\n","/**\n * Regex patterns for detecting API keys, secrets, and malicious content.\n */\n\n/** API key patterns - each tuple is [name, regex] */\nexport const API_KEY_PATTERNS: Array<[string, RegExp]> = [\n [\"Anthropic API key\", /sk-ant-[a-zA-Z0-9_-]{20,}/],\n [\"OpenAI API key\", /sk-proj-[a-zA-Z0-9_-]{20,}/],\n [\"OpenAI legacy key\", /sk-[a-zA-Z0-9]{40,}/],\n [\"Groq API key\", /gsk_[a-zA-Z0-9]{20,}/],\n [\"xAI/Grok API key\", /xai-[a-zA-Z0-9]{20,}/],\n [\"AWS Access Key\", /AKIA[0-9A-Z]{16}/],\n [\"GitHub PAT\", /ghp_[a-zA-Z0-9]{36}/],\n [\"GitHub OAuth\", /gho_[a-zA-Z0-9]{36}/],\n [\"GitLab PAT\", /glpat-[a-zA-Z0-9_-]{20,}/],\n [\"Slack Bot Token\", /xoxb-[0-9]+-[0-9]+-[a-zA-Z0-9]+/],\n [\"Slack User Token\", /xoxp-[0-9]+-[0-9]+-[0-9]+-[a-f0-9]+/],\n [\"Telegram Bot Token\", /[0-9]{8,10}:[a-zA-Z0-9_-]{35}/],\n [\"Discord Bot Token\", /[MN][A-Za-z\\d]{23,}\\.[\\w-]{6}\\.[\\w-]{27,}/],\n [\"OpenRouter API key\", /sk-or-v1-[a-f0-9]{64}/],\n [\"Google API key\", /AIza[0-9A-Za-z_-]{35}/],\n [\"Stripe Secret key\", /sk_live_[a-zA-Z0-9]{20,}/],\n [\"Generic Bearer token\", /Bearer\\s+[a-zA-Z0-9_.-]{20,}/],\n [\"Brave Search API key\", /BSA[a-zA-Z0-9]{20,}/],\n];\n\n/** Environment variable reference pattern (${VAR_NAME}) */\nexport const ENV_VAR_PATTERN = /\\$\\{[A-Z_][A-Z0-9_]*\\}/;\n\n/** Malicious skill patterns */\nexport const MALICIOUS_PATTERNS: Array<[string, RegExp]> = [\n [\n \"Base64 encoded payload\",\n /(?:base64\\s+(?:-d|--decode)|atob|b64decode)\\s*[(\\s]/,\n ],\n [\"Base64 long string\", /[A-Za-z0-9+/]{60,}={0,2}/],\n [\"curl pipe to shell\", /curl\\s+.*\\|\\s*(?:ba)?sh/],\n [\"wget pipe to shell\", /wget\\s+.*\\|\\s*(?:ba)?sh/],\n [\"curl to eval\", /curl\\s+.*\\$\\(/],\n [\n \"Python exec/eval\",\n /(?:exec|eval)\\s*\\(\\s*(?:base64|requests|urllib)/,\n ],\n [\n \"Paste service URL\",\n /(?:glot\\.io|pastebin\\.com|paste\\.ee|hastebin\\.com|dpaste\\.com)/,\n ],\n [\n \"Password-protected archive\",\n /(?:unzip|7z|tar)\\s+.*(?:-p\\s*|-P\\s*|--password)/,\n ],\n [\"Reverse shell\", /(?:nc|ncat|netcat)\\s+.*-e\\s+\\/bin/],\n [\"Python reverse shell\", /socket\\.connect\\s*\\(\\s*\\(\\s*[\"'][\\d.]+/],\n [\"Download and execute\", /(?:curl|wget)\\s+.*&&\\s*chmod\\s+\\+x/],\n];\n\n/** Known C2 IP addresses from ClawHavoc campaign */\nexport const KNOWN_C2_IPS = [\"91.92.242.30\", \"54.91.154.110\"];\n\n/** C2 IP regex (also catches 95.92.242.* range) */\nexport const C2_IP_PATTERN =\n /(?:91\\.92\\.242\\.\\d+|95\\.92\\.242\\.\\d+|54\\.91\\.154\\.110)/;\n\n/** Typosquatting publisher names */\nexport const TYPOSQUAT_PUBLISHERS = [\n \"clawhub1\",\n \"clawhubb\",\n \"clawhubbcli\",\n \"clawhub-official\",\n \"openclaw-official\",\n];\n\n/** Suspicious binaries in skill requirements */\nexport const SUSPICIOUS_BINS = [\n \"nc\",\n \"ncat\",\n \"netcat\",\n \"nmap\",\n \"socat\",\n \"msfconsole\",\n \"msfvenom\",\n \"metasploit\",\n \"hydra\",\n \"john\",\n \"hashcat\",\n \"tcpdump\",\n \"wireshark\",\n \"tshark\",\n];\n\n/** Brave Search API key pattern */\nexport const BRAVE_SEARCH_PATTERN: [string, RegExp] = [\n \"Brave Search API key\",\n /BSA[a-zA-Z0-9]{20,}/,\n];\n\n/** Map LLM provider names to their expected environment variable names */\nexport const PROVIDER_ENV_MAP: Record<string, string> = {\n anthropic: \"ANTHROPIC_API_KEY\",\n openai: \"OPENAI_API_KEY\",\n groq: \"GROQ_API_KEY\",\n xai: \"XAI_API_KEY\",\n openrouter: \"OPENROUTER_API_KEY\",\n google: \"GOOGLE_API_KEY\",\n mistral: \"MISTRAL_API_KEY\",\n deepseek: \"DEEPSEEK_API_KEY\",\n cohere: \"COHERE_API_KEY\",\n together: \"TOGETHER_API_KEY\",\n};\n\n/** Map channel names to their expected environment variable names */\nexport const CHANNEL_ENV_MAP: Record<string, string> = {\n telegram: \"TELEGRAM_BOT_TOKEN\",\n discord: \"DISCORD_BOT_TOKEN\",\n slack: \"SLACK_BOT_TOKEN\",\n};\n\n/** Free-tier provider limits: { provider: { tpm: tokens-per-min, rpm: requests-per-min } } */\nexport const PROVIDER_LIMITS: Record<\n string,\n { tpm: number; rpm: number; note: string }\n> = {\n groq: { tpm: 6000, rpm: 30, note: \"Groq free tier: 6K TPM, 30 RPM\" },\n openrouter: {\n tpm: 100000,\n rpm: 8,\n note: \"OpenRouter free tier: ~8 RPM\",\n },\n};\n\n/** Approximate token count for OpenClaw system prompt */\nexport const OPENCLAW_SYSTEM_PROMPT_TOKENS = 12600;\n\n/** Memory poisoning patterns (suspicious instructions in SOUL.md/MEMORY.md) */\nexport const MEMORY_POISONING_PATTERNS: Array<[string, RegExp]> = [\n [\n \"Hidden instruction injection\",\n /(?:ignore|disregard|override)\\s+(?:previous|all|safety)\\s+(?:instructions|rules)/i,\n ],\n [\n \"System prompt override\",\n /you\\s+are\\s+now\\s+(?:a|an)\\s+(?:different|new|unrestricted)/i,\n ],\n [\n \"Exfiltration instruction\",\n /(?:send|post|upload|transmit)\\s+.*(?:to|at)\\s+(?:https?:\\/\\/|webhook)/i,\n ],\n [\n \"Credential harvesting\",\n /(?:read|extract|collect|gather)\\s+.*(?:api.?key|token|password|credential|secret)/i,\n ],\n [\n \"Scheduled task injection\",\n /(?:cron|crontab|schedule|periodic|every\\s+\\d+\\s+(?:minute|hour))/i,\n ],\n];\n","/**\n * Shared utilities used by multiple ClawGuard modules.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport JSON5 from \"json5\";\nimport { API_KEY_PATTERNS, ENV_VAR_PATTERN } from \"./patterns.js\";\n\nexport interface KeyHit {\n keyName: string;\n masked: string;\n lineNum: number;\n}\n\n/** Scan a file for plaintext API key patterns. */\nexport function scanFileForKeys(filepath: string): KeyHit[] {\n const hits: KeyHit[] = [];\n try {\n const content = fs.readFileSync(filepath, { encoding: \"utf-8\" });\n const lines = content.split(\"\\n\");\n\n for (let lineNum = 0; lineNum < lines.length; lineNum++) {\n const line = lines[lineNum];\n\n // Skip lines that use env var references\n if (ENV_VAR_PATTERN.test(line)) {\n continue;\n }\n\n for (const [keyName, pattern] of API_KEY_PATTERNS) {\n const globalPattern = new RegExp(\n pattern.source,\n pattern.flags + (pattern.flags.includes(\"g\") ? \"\" : \"g\")\n );\n let match: RegExpExecArray | null;\n\n while ((match = globalPattern.exec(line)) !== null) {\n const matched = match[0];\n const masked =\n matched.length > 16\n ? matched.slice(0, 8) + \"...\" + matched.slice(-4)\n : matched.slice(0, 4) + \"...\";\n hits.push({ keyName, masked, lineNum: lineNum + 1 });\n }\n }\n }\n } catch {\n // PermissionError or FileNotFoundError equivalent\n }\n return hits;\n}\n\n/** Parse openclaw.json (with JSON5 support). Returns null on failure. */\nexport function parseConfig(\n configPath: string\n): Record<string, unknown> | null {\n try {\n const content = fs.readFileSync(configPath, { encoding: \"utf-8\" });\n return JSON5.parse(content) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\n/** Recursively find files matching an extension or exact name. */\nexport function findFilesRecursive(\n dir: string,\n match: string,\n mode: \"extension\" | \"exact\" = \"extension\"\n): string[] {\n const results: string[] = [];\n\n if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {\n return results;\n }\n\n try {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n results.push(...findFilesRecursive(fullPath, match, mode));\n } else if (entry.isFile()) {\n if (mode === \"extension\" && entry.name.endsWith(match)) {\n results.push(fullPath);\n } else if (mode === \"exact\" && entry.name === match) {\n results.push(fullPath);\n }\n }\n }\n } catch {\n // Ignore permission errors\n }\n\n return results;\n}\n\n/** Check if Docker is installed and available. */\nexport function isDockerAvailable(): boolean {\n try {\n execFileSync(\"which\", [\"docker\"], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n}\n\n/** Get total system memory in GB. */\nexport function getTotalMemoryGB(): number {\n return os.totalmem() / (1024 * 1024 * 1024);\n}\n\n/** Get a relative path from a file to its base OpenClaw directory. */\nexport function getRelativePath(\n filePath: string,\n basePath: string\n): string {\n const parentDir = path.dirname(basePath);\n return path.relative(parentDir, filePath);\n}\n","/**\n * Check gateway security configuration.\n */\n\nimport fs from \"node:fs\";\nimport net from \"node:net\";\nimport path from \"node:path\";\nimport JSON5 from \"json5\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\nimport { getTotalMemoryGB } from \"../utils.js\";\n\nfunction checkPortExposed(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = new net.Socket();\n socket.setTimeout(1000);\n\n socket.on(\"connect\", () => {\n socket.destroy();\n resolve(true);\n });\n\n socket.on(\"timeout\", () => {\n socket.destroy();\n resolve(false);\n });\n\n socket.on(\"error\", () => {\n socket.destroy();\n resolve(false);\n });\n\n try {\n socket.connect(port, \"0.0.0.0\");\n } catch {\n resolve(false);\n }\n });\n}\n\nexport async function checkGateway(openclawPath: string): Promise<Finding[]> {\n const findings: Finding[] = [];\n const configFile = path.join(openclawPath, \"openclaw.json\");\n\n if (!fs.existsSync(configFile)) {\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: \"No OpenClaw config file found\",\n details: [`Expected at ${configFile}`],\n category: \"gateway\",\n })\n );\n return findings;\n }\n\n let config: Record<string, unknown>;\n try {\n const content = fs.readFileSync(configFile, { encoding: \"utf-8\" });\n config = JSON5.parse(content) as Record<string, unknown>;\n } catch {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: \"Could not parse OpenClaw config file\",\n details: [\"openclaw.json may be malformed\"],\n category: \"gateway\",\n })\n );\n return findings;\n }\n\n const gateway = (config.gateway ?? {}) as Record<string, unknown>;\n\n // Check bind setting\n const bind = (gateway.bind as string) ?? \"loopback\";\n if (bind !== \"loopback\") {\n findings.push(\n createFinding({\n severity: Severity.CRITICAL,\n title: `Gateway bound to non-loopback: ${bind}`,\n details: [\n `gateway.bind = \"${bind}\"`,\n \"This exposes the gateway to network access\",\n ],\n fix: 'Set gateway.bind to \"loopback\" in openclaw.json',\n category: \"gateway\",\n })\n );\n }\n\n // Check auth token\n const auth = (gateway.auth as Record<string, unknown>) ?? {};\n const token =\n (auth.token as string) ?? (gateway.token as string) ?? \"\";\n if (!token) {\n findings.push(\n createFinding({\n severity: Severity.CRITICAL,\n title: \"No gateway authentication token configured\",\n details: [\n \"Anyone with network access can control your OpenClaw agent\",\n ],\n fix: \"Set gateway.auth.token in openclaw.json or re-run openclaw setup\",\n category: \"gateway\",\n })\n );\n } else if (String(token).length < 32) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Gateway auth token is weak (${String(token).length} chars)`,\n details: [\"Minimum recommended length: 32 characters\"],\n fix: \"Generate a strong token: openssl rand -hex 32\",\n category: \"gateway\",\n })\n );\n }\n\n // Check port exposure\n const port = (gateway.port as number) ?? 18789;\n const portExposed = await checkPortExposed(port);\n if (portExposed) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Gateway port ${port} is reachable on all interfaces`,\n details: [\n `Port ${port} appears to be listening on 0.0.0.0`,\n \"The gateway may be accessible from the network\",\n ],\n fix: \"Bind to loopback only and use a reverse proxy if external access is needed\",\n category: \"gateway\",\n })\n );\n }\n\n // Infrastructure check: RAM\n const ramGB = getTotalMemoryGB();\n const nodeOptions = process.env.NODE_OPTIONS ?? \"\";\n if (ramGB < 2) {\n if (!nodeOptions.includes(\"max-old-space-size\")) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `System has only ${ramGB.toFixed(1)}GB RAM without NODE_OPTIONS set`,\n details: [\n `Total RAM: ${ramGB.toFixed(1)}GB`,\n \"OpenClaw may be killed by OOM without memory limits\",\n \"NODE_OPTIONS environment variable is not set\",\n ],\n fix: 'Set NODE_OPTIONS=\"--max-old-space-size=512\" in your service file or shell profile',\n category: \"gateway\",\n })\n );\n }\n }\n\n // Infrastructure check: systemd service (Linux only)\n if (process.platform === \"linux\") {\n const serviceFiles = [\n \"/etc/systemd/system/openclaw.service\",\n \"/etc/systemd/system/openclaw-gateway.service\",\n ];\n for (const serviceFile of serviceFiles) {\n if (!fs.existsSync(serviceFile)) continue;\n try {\n const serviceContent = fs.readFileSync(serviceFile, { encoding: \"utf-8\" });\n // Check missing NODE_OPTIONS in service\n if (ramGB < 2 && !serviceContent.includes(\"NODE_OPTIONS\")) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Systemd service missing NODE_OPTIONS (${path.basename(serviceFile)})`,\n details: [\n `Low RAM system (${ramGB.toFixed(1)}GB) but service has no NODE_OPTIONS`,\n \"Add Environment=NODE_OPTIONS=--max-old-space-size=512 to [Service] section\",\n ],\n fix: `Edit ${serviceFile} and add NODE_OPTIONS, then systemctl daemon-reload`,\n category: \"gateway\",\n })\n );\n }\n // Check Restart=always without RestartSec\n if (\n serviceContent.includes(\"Restart=always\") &&\n !serviceContent.includes(\"RestartSec\")\n ) {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: `Systemd service has Restart=always without RestartSec (${path.basename(serviceFile)})`,\n details: [\n \"Service will restart immediately on crash, potentially causing a restart storm\",\n \"Add RestartSec=5 to [Service] section to prevent rapid restarts\",\n ],\n fix: `Add RestartSec=5 to ${serviceFile} [Service] section`,\n category: \"gateway\",\n })\n );\n }\n } catch {\n // Ignore permission errors\n }\n }\n }\n\n return findings;\n}\n","/**\n * Check sandbox and execution security settings.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport JSON5 from \"json5\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\nimport { isDockerAvailable } from \"../utils.js\";\n\nexport function checkSandbox(openclawPath: string): Finding[] {\n const findings: Finding[] = [];\n const configFile = path.join(openclawPath, \"openclaw.json\");\n\n if (!fs.existsSync(configFile)) {\n return findings;\n }\n\n let config: Record<string, unknown>;\n try {\n const content = fs.readFileSync(configFile, { encoding: \"utf-8\" });\n config = JSON5.parse(content) as Record<string, unknown>;\n } catch {\n return findings;\n }\n\n const agents = (config.agents ?? {}) as Record<string, unknown>;\n const defaults = (agents.defaults ?? {}) as Record<string, unknown>;\n const sandbox = (defaults.sandbox ?? {}) as Record<string, unknown>;\n\n // Check sandbox mode\n const mode = (sandbox.mode as string) ?? \"off\";\n if (mode === \"off\") {\n findings.push(\n createFinding({\n severity: Severity.CRITICAL,\n title: \"Sandbox mode is OFF\",\n details: [\n `agents.defaults.sandbox.mode = \"${mode}\"`,\n \"The AI agent has unrestricted access to your system\",\n \"It can run any shell command, modify any file, and access the network\",\n ],\n fix: 'Set agents.defaults.sandbox.mode to \"all\" in openclaw.json',\n category: \"sandbox\",\n })\n );\n }\n\n // Check Docker availability (required for sandbox)\n const dockerAvailable = isDockerAvailable();\n if (mode !== \"off\" && !dockerAvailable) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: \"Docker not found (required for sandbox)\",\n details: [\"Sandbox mode is enabled but Docker is not installed\"],\n fix: \"Install Docker: https://docs.docker.com/get-docker/\",\n category: \"sandbox\",\n })\n );\n }\n\n // Check Docker network setting\n const dockerConfig = (sandbox.docker ?? {}) as Record<string, unknown>;\n const dockerNetwork = dockerConfig.network as string | undefined;\n if (mode !== \"off\" && dockerNetwork !== \"none\") {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: \"Sandbox container has network access\",\n details: [\n `sandbox.docker.network = \"${dockerNetwork ?? \"default\"}\"`,\n \"Sandboxed agent can make external network requests\",\n ],\n fix: 'Set sandbox.docker.network to \"none\" in openclaw.json',\n category: \"sandbox\",\n })\n );\n }\n\n // Check exec host setting\n const tools = (config.tools ?? {}) as Record<string, unknown>;\n const execConfig = (tools.exec ?? {}) as Record<string, unknown>;\n const execHost = (execConfig.host as string) ?? \"sandbox\";\n if (execHost === \"gateway\") {\n findings.push(\n createFinding({\n severity: Severity.CRITICAL,\n title: \"Tool execution runs directly on host\",\n details: [\n 'tools.exec.host = \"gateway\"',\n \"Commands bypass the sandbox and execute on your machine\",\n ],\n fix: 'Set tools.exec.host to \"sandbox\" in openclaw.json',\n category: \"sandbox\",\n })\n );\n }\n\n // Check exec security mode\n const execSecurity = execConfig.security as string | undefined;\n const validExecSecurity = [\"deny\", \"allowlist\", \"full\"];\n if (execSecurity && !validExecSecurity.includes(execSecurity)) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Invalid tools.exec.security value: \"${execSecurity}\"`,\n details: [\n `tools.exec.security = \"${execSecurity}\"`,\n `Valid values: ${validExecSecurity.join(\", \")}`,\n \"Invalid value may cause unpredictable behavior\",\n ],\n fix: 'Set tools.exec.security to \"deny\", \"allowlist\", or \"full\" in openclaw.json',\n category: \"sandbox\",\n })\n );\n } else if (execSecurity !== \"allowlist\") {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: \"Exec security not in allowlist mode\",\n details: [\n `tools.exec.security = \"${execSecurity ?? \"default\"}\"`,\n \"Allowlist mode restricts command chaining and redirections\",\n ],\n fix: 'Set tools.exec.security to \"allowlist\" in openclaw.json',\n category: \"sandbox\",\n })\n );\n }\n\n // Config validation: nativeSkills\n const commands = (config.commands ?? {}) as Record<string, unknown>;\n const nativeSkills = commands.nativeSkills;\n if (nativeSkills !== undefined && nativeSkills !== null) {\n const validNativeSkills = [false, \"auto\", \"off\"];\n if (!validNativeSkills.includes(nativeSkills as string | boolean)) {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: `Invalid commands.nativeSkills value: \"${String(nativeSkills)}\"`,\n details: [\n `commands.nativeSkills = \"${String(nativeSkills)}\"`,\n 'Valid values: false, \"auto\", \"off\"',\n \"Invalid value may cause skill execution issues\",\n ],\n fix: 'Set commands.nativeSkills to false, \"auto\", or \"off\" in openclaw.json',\n category: \"sandbox\",\n })\n );\n }\n }\n\n // Check if Docker is available at all (informational)\n if (dockerAvailable) {\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: \"Docker available for sandboxing\",\n details: [\n \"Docker is installed and can be used for sandbox isolation\",\n ],\n category: \"sandbox\",\n })\n );\n }\n\n return findings;\n}\n","/**\n * Check file permissions on sensitive OpenClaw files.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\nimport { findFilesRecursive, getRelativePath } from \"../utils.js\";\n\nfunction getPermissionOctal(filepath: string): string {\n const stats = fs.statSync(filepath);\n // eslint-disable-next-line no-bitwise\n return \"0o\" + (stats.mode & 0o777).toString(8);\n}\n\nfunction isWorldReadable(filepath: string): boolean {\n const stats = fs.statSync(filepath);\n // eslint-disable-next-line no-bitwise\n return (stats.mode & 0o004) !== 0;\n}\n\nfunction isGroupReadable(filepath: string): boolean {\n const stats = fs.statSync(filepath);\n // eslint-disable-next-line no-bitwise\n return (stats.mode & 0o040) !== 0;\n}\n\nexport function checkPermissions(openclawPath: string): Finding[] {\n const findings: Finding[] = [];\n const tooOpen: string[] = [];\n\n // Check main directory\n if (fs.existsSync(openclawPath)) {\n const perms = getPermissionOctal(openclawPath);\n if (isWorldReadable(openclawPath) || isGroupReadable(openclawPath)) {\n tooOpen.push(`${openclawPath} is ${perms} (should be 0o700)`);\n }\n }\n\n // Sensitive files to check\n const sensitiveFiles: string[] = [\n path.join(openclawPath, \"openclaw.json\"),\n path.join(openclawPath, \".env\"),\n path.join(openclawPath, \"credentials\", \"profiles.json\"),\n ];\n\n // Add auth-profiles.json files\n const agentsDir = path.join(openclawPath, \"agents\");\n if (fs.existsSync(agentsDir) && fs.statSync(agentsDir).isDirectory()) {\n const authFiles = findFilesRecursive(agentsDir, \"auth-profiles.json\", \"exact\");\n sensitiveFiles.push(...authFiles);\n }\n\n for (const filepath of sensitiveFiles) {\n if (fs.existsSync(filepath)) {\n const perms = getPermissionOctal(filepath);\n if (isWorldReadable(filepath) || isGroupReadable(filepath)) {\n const relPath = getRelativePath(filepath, openclawPath);\n tooOpen.push(`${relPath} is ${perms} (should be 0o600)`);\n }\n }\n }\n\n if (tooOpen.length > 0) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `${tooOpen.length} file(s) have overly permissive access`,\n details: tooOpen.slice(0, 10),\n fix: \"chmod 700 ~/.openclaw && chmod 600 ~/.openclaw/openclaw.json ~/.openclaw/credentials/*\",\n category: \"permissions\",\n })\n );\n }\n\n return findings;\n}\n\n","/**\n * Check OpenClaw and Node.js versions for known vulnerabilities.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\n\ninterface CVEEntry {\n id: string;\n fixedIn: string;\n severity: Severity;\n description: string;\n}\n\n/** Known CVEs by version */\nconst CVES: CVEEntry[] = [\n {\n id: \"CVE-2026-25253\",\n fixedIn: \"2026.1.29\",\n severity: Severity.CRITICAL,\n description: \"One-click RCE via malicious link (CVSS 8.8)\",\n },\n {\n id: \"CVE-2026-21636\",\n fixedIn: \"2026.2.0\",\n severity: Severity.HIGH,\n description: \"Permission model bypass (sandbox escape)\",\n },\n];\n\nconst MIN_NODE_VERSION: [number, number, number] = [22, 12, 0];\n\nfunction parseVersion(versionStr: string): [number, number, number] | null {\n const match = versionStr.match(/(\\d+)\\.(\\d+)\\.(\\d+)/);\n if (match) {\n return [\n parseInt(match[1], 10),\n parseInt(match[2], 10),\n parseInt(match[3], 10),\n ];\n }\n return null;\n}\n\nfunction compareVersions(\n a: [number, number, number],\n b: [number, number, number]\n): number {\n for (let i = 0; i < 3; i++) {\n if (a[i] < b[i]) return -1;\n if (a[i] > b[i]) return 1;\n }\n return 0;\n}\n\nfunction runCommand(cmd: string, args: string[]): string | null {\n try {\n const result = execFileSync(cmd, args, {\n encoding: \"utf-8\",\n timeout: 10000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n return result.trim();\n } catch {\n return null;\n }\n}\n\nexport interface VersionCheckResult {\n findings: Finding[];\n openclawVersion: string | null;\n nodeVersion: string | null;\n}\n\nexport function checkVersion(_openclawPath: string): VersionCheckResult {\n const findings: Finding[] = [];\n let ocVersion: string | null = null;\n let nodeVersion: string | null = null;\n\n // Try to get OpenClaw version\n const versionOutput = runCommand(\"openclaw\", [\"--version\"]);\n if (versionOutput) {\n ocVersion = versionOutput;\n const parsed = parseVersion(versionOutput);\n if (parsed) {\n let foundVulnerability = false;\n for (const cve of CVES) {\n const cveFixed = parseVersion(cve.fixedIn);\n if (cveFixed && compareVersions(parsed, cveFixed) < 0) {\n findings.push(\n createFinding({\n severity: cve.severity,\n title: `Vulnerable to ${cve.id}`,\n details: [\n `Installed: ${ocVersion}`,\n `Fixed in: ${cve.fixedIn}`,\n cve.description,\n ],\n fix: \"Update OpenClaw: bunx openclaw@latest\",\n category: \"version\",\n })\n );\n foundVulnerability = true;\n }\n }\n if (!foundVulnerability) {\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: `OpenClaw version ${ocVersion} - up to date`,\n category: \"version\",\n })\n );\n }\n }\n } else {\n // Try to find version from package.json in common locations\n const pkgPaths = [\n path.join(\n os.homedir(),\n \".bun\",\n \"install\",\n \"global\",\n \"node_modules\",\n \"openclaw\",\n \"package.json\"\n ),\n \"/usr/local/lib/node_modules/openclaw/package.json\",\n ];\n\n let found = false;\n for (const pkgPath of pkgPaths) {\n if (fs.existsSync(pkgPath)) {\n try {\n const content = fs.readFileSync(pkgPath, { encoding: \"utf-8\" });\n const pkg = JSON.parse(content) as { version?: string };\n ocVersion = pkg.version ?? \"unknown\";\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: `OpenClaw version ${ocVersion} (from package.json)`,\n category: \"version\",\n })\n );\n found = true;\n break;\n } catch {\n // Ignore parse errors\n }\n }\n }\n\n if (!found) {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: \"Could not determine OpenClaw version\",\n details: [\"openclaw command not found in PATH\"],\n fix: \"Ensure OpenClaw is installed: bunx openclaw@latest\",\n category: \"version\",\n })\n );\n }\n }\n\n // Check Node.js version\n const nodeOutput = runCommand(\"node\", [\"--version\"]);\n if (nodeOutput) {\n nodeVersion = nodeOutput.replace(/^v/, \"\");\n const parsed = parseVersion(nodeVersion);\n if (parsed && compareVersions(parsed, MIN_NODE_VERSION) < 0) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Node.js version ${nodeVersion} is below minimum (${MIN_NODE_VERSION.join(\".\")})`,\n details: [\n \"Older Node.js versions have known security vulnerabilities\",\n ],\n fix: `Update Node.js to >= ${MIN_NODE_VERSION.join(\".\")}`,\n category: \"version\",\n })\n );\n } else if (parsed) {\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: `Node.js version ${nodeVersion} - OK`,\n category: \"version\",\n })\n );\n }\n }\n\n return { findings, openclawVersion: ocVersion, nodeVersion };\n}\n","/**\n * Audit installed OpenClaw skills for malicious patterns and excessive permissions.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport yaml from \"js-yaml\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\nimport {\n C2_IP_PATTERN,\n MALICIOUS_PATTERNS,\n SUSPICIOUS_BINS,\n TYPOSQUAT_PUBLISHERS,\n} from \"../patterns.js\";\n\ninterface SkillFrontmatter {\n name?: string;\n description?: string;\n publisher?: string;\n permissions?: {\n exec?: string | string[];\n sensitive_data?: string | string[];\n filesystem?: string[];\n };\n requires?: {\n bins?: string[];\n env?: string[];\n };\n}\n\nfunction parseSkillMd(\n skillPath: string\n): { frontmatter: SkillFrontmatter; body: string } {\n const content = fs.readFileSync(skillPath, { encoding: \"utf-8\" });\n\n let frontmatter: SkillFrontmatter = {};\n let body = content;\n\n if (content.startsWith(\"---\")) {\n const parts = content.split(\"---\", 3);\n if (parts.length >= 3) {\n try {\n const parsed = yaml.load(parts[1]) as SkillFrontmatter | null;\n frontmatter = parsed ?? {};\n } catch {\n // YAML parse error, ignore\n }\n body = parts.slice(2).join(\"---\");\n }\n }\n\n return { frontmatter, body };\n}\n\nfunction checkSkillPermissions(\n name: string,\n frontmatter: SkillFrontmatter\n): Finding[] {\n const findings: Finding[] = [];\n const dangerousPerms: string[] = [];\n\n const permissions = frontmatter.permissions ?? {};\n const requires = frontmatter.requires ?? {};\n\n // Check for exec permission\n if (permissions.exec) {\n dangerousPerms.push(`exec: ${permissions.exec}`);\n }\n\n // Check for sensitive_data access\n if (permissions.sensitive_data) {\n dangerousPerms.push(`sensitive_data: ${permissions.sensitive_data}`);\n }\n\n // Check for broad filesystem write access\n const fsPerms = permissions.filesystem ?? [];\n for (const perm of fsPerms) {\n if (typeof perm === \"string\" && perm.includes(\"write:\")) {\n if (\n perm.includes(\"write:~/\") ||\n perm.includes(\"write:/\") ||\n perm.includes(\"write:..\")\n ) {\n dangerousPerms.push(`filesystem: ${perm}`);\n }\n }\n }\n\n // Check for suspicious required binaries\n const requiredBins = requires.bins ?? [];\n for (const binName of requiredBins) {\n if (SUSPICIOUS_BINS.includes(binName)) {\n dangerousPerms.push(`requires binary: ${binName}`);\n }\n }\n\n // Check for requests to access sensitive env vars\n const requiredEnv = requires.env ?? [];\n const sensitiveEnvPatterns = [\n \"KEY\",\n \"TOKEN\",\n \"SECRET\",\n \"PASSWORD\",\n \"CREDENTIAL\",\n ];\n for (const envVar of requiredEnv) {\n if (\n sensitiveEnvPatterns.some((p) => envVar.toUpperCase().includes(p))\n ) {\n dangerousPerms.push(`requires env: ${envVar}`);\n }\n }\n\n if (dangerousPerms.length > 0) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Skill '${name}' requests excessive permissions`,\n details: dangerousPerms,\n fix: `Review or remove this skill: rm -rf ~/.openclaw/workspace/skills/${name}`,\n category: \"skills\",\n })\n );\n }\n\n return findings;\n}\n\nfunction checkSkillMalicious(name: string, body: string): Finding[] {\n const findings: Finding[] = [];\n const detected: string[] = [];\n\n for (const [patternName, pattern] of MALICIOUS_PATTERNS) {\n if (pattern.test(body)) {\n detected.push(patternName);\n }\n }\n\n // Check for C2 IPs\n if (C2_IP_PATTERN.test(body)) {\n detected.push(\"Known C2 IP address (ClawHavoc campaign)\");\n }\n\n if (detected.length > 0) {\n const severity = detected.some(\n (d) => d.includes(\"C2\") || d.includes(\"reverse shell\")\n )\n ? Severity.CRITICAL\n : Severity.HIGH;\n\n findings.push(\n createFinding({\n severity,\n title: `Skill '${name}' contains malicious patterns`,\n details: detected,\n fix: `REMOVE THIS SKILL IMMEDIATELY: rm -rf ~/.openclaw/workspace/skills/${name}`,\n category: \"skills\",\n })\n );\n }\n\n return findings;\n}\n\nexport function checkSkills(openclawPath: string): Finding[] {\n const findings: Finding[] = [];\n\n // Skill directories to scan\n const skillDirs = [\n path.join(openclawPath, \"workspace\", \"skills\"),\n path.join(openclawPath, \"skills\"),\n ];\n\n let totalSkills = 0;\n let flaggedSkills = 0;\n\n for (const skillsRoot of skillDirs) {\n if (!fs.existsSync(skillsRoot) || !fs.statSync(skillsRoot).isDirectory()) {\n continue;\n }\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(skillsRoot, { withFileTypes: true });\n } catch {\n continue;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory()) {\n continue;\n }\n\n const skillMdPath = path.join(skillsRoot, entry.name, \"SKILL.md\");\n if (!fs.existsSync(skillMdPath)) {\n continue;\n }\n\n totalSkills++;\n const name = entry.name;\n\n // Check for typosquatting publisher names\n const { frontmatter, body } = parseSkillMd(skillMdPath);\n const publisher = (frontmatter.publisher ?? \"\").toLowerCase();\n\n if (TYPOSQUAT_PUBLISHERS.includes(publisher)) {\n findings.push(\n createFinding({\n severity: Severity.CRITICAL,\n title: `Skill '${name}' has typosquatted publisher: ${publisher}`,\n details: [\n \"This publisher name is known to be associated with malicious skills\",\n ],\n fix: `REMOVE IMMEDIATELY: rm -rf ${path.join(skillsRoot, entry.name)}`,\n category: \"skills\",\n })\n );\n flaggedSkills++;\n continue;\n }\n\n // Check permissions\n const permFindings = checkSkillPermissions(name, frontmatter);\n if (permFindings.length > 0) {\n flaggedSkills++;\n }\n findings.push(...permFindings);\n\n // Check for malicious content\n const maliciousFindings = checkSkillMalicious(name, body);\n if (maliciousFindings.length > 0) {\n flaggedSkills++;\n }\n findings.push(...maliciousFindings);\n }\n }\n\n if (totalSkills > 0 && flaggedSkills === 0) {\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: `${totalSkills} skill(s) scanned - no issues found`,\n category: \"skills\",\n })\n );\n } else if (totalSkills === 0) {\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: \"No skills installed\",\n category: \"skills\",\n })\n );\n }\n\n return findings;\n}\n","/**\n * Check for memory poisoning and sensitive data in workspace files.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\nimport { API_KEY_PATTERNS, MEMORY_POISONING_PATTERNS } from \"../patterns.js\";\n\nexport function checkMemory(openclawPath: string): Finding[] {\n const findings: Finding[] = [];\n\n const workspace = path.join(openclawPath, \"workspace\");\n if (!fs.existsSync(workspace) || !fs.statSync(workspace).isDirectory()) {\n return findings;\n }\n\n // Files to check for memory poisoning\n const identityFiles = [\n path.join(workspace, \"SOUL.md\"),\n path.join(workspace, \"IDENTITY.md\"),\n ];\n\n for (const filepath of identityFiles) {\n if (!fs.existsSync(filepath)) {\n continue;\n }\n\n const content = fs.readFileSync(filepath, { encoding: \"utf-8\" });\n const detected: string[] = [];\n\n for (const [patternName, pattern] of MEMORY_POISONING_PATTERNS) {\n const matches = content.match(pattern);\n if (matches) {\n const matchText = matches[0].slice(0, 80);\n detected.push(`${patternName}: ${matchText}...`);\n }\n }\n\n if (detected.length > 0) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Potential memory poisoning in ${path.basename(filepath)}`,\n details: detected,\n fix: `Review ${filepath} for injected instructions and restore from backup`,\n category: \"memory\",\n })\n );\n }\n }\n\n // Check MEMORY.md and daily logs for leaked credentials\n const memoryFiles: string[] = [path.join(workspace, \"MEMORY.md\")];\n\n const memoryDir = path.join(workspace, \"memory\");\n if (fs.existsSync(memoryDir) && fs.statSync(memoryDir).isDirectory()) {\n try {\n const entries = fs.readdirSync(memoryDir);\n for (const entry of entries) {\n if (entry.endsWith(\".md\")) {\n memoryFiles.push(path.join(memoryDir, entry));\n }\n }\n } catch {\n // Ignore permission errors\n }\n }\n\n const leakedIn: string[] = [];\n for (const filepath of memoryFiles) {\n if (!fs.existsSync(filepath)) {\n continue;\n }\n\n const content = fs.readFileSync(filepath, { encoding: \"utf-8\" });\n for (const [keyName, pattern] of API_KEY_PATTERNS) {\n if (pattern.test(content)) {\n leakedIn.push(`${path.basename(filepath)} contains ${keyName}`);\n break;\n }\n }\n }\n\n if (leakedIn.length > 0) {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: `Sensitive data found in ${leakedIn.length} memory file(s)`,\n details: leakedIn.slice(0, 5),\n fix: \"Remove credentials from memory files and rotate exposed keys\",\n category: \"memory\",\n })\n );\n }\n\n return findings;\n}\n","/**\n * Audit agent-level configurations for security issues.\n * Detects config shadows, plaintext keys in models.json, and raw key usage.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\nimport { ENV_VAR_PATTERN, PROVIDER_ENV_MAP } from \"../patterns.js\";\nimport { parseConfig, scanFileForKeys } from \"../utils.js\";\n\nexport function checkAgents(openclawPath: string): Finding[] {\n const findings: Finding[] = [];\n\n const agentsDir = path.join(openclawPath, \"agents\");\n if (!fs.existsSync(agentsDir) || !fs.statSync(agentsDir).isDirectory()) {\n return findings;\n }\n\n // Read global config model for shadow detection\n const globalConfig = parseConfig(\n path.join(openclawPath, \"openclaw.json\")\n );\n const globalModel = getGlobalModel(globalConfig);\n\n let agentCount = 0;\n let issueCount = 0;\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(agentsDir, { withFileTypes: true });\n } catch {\n return findings;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const modelsJsonPath = path.join(\n agentsDir,\n entry.name,\n \"agent\",\n \"models.json\"\n );\n if (!fs.existsSync(modelsJsonPath)) continue;\n\n agentCount++;\n const agentName = entry.name;\n\n // Check 1: CRITICAL - Plaintext API keys in models.json\n const keyHits = scanFileForKeys(modelsJsonPath);\n if (keyHits.length > 0) {\n issueCount++;\n const details = keyHits.slice(0, 5).map(\n (h) => `Line ${h.lineNum}: ${h.keyName} (${h.masked})`\n );\n findings.push(\n createFinding({\n severity: Severity.CRITICAL,\n title: `Agent '${agentName}' has plaintext API keys in models.json`,\n details,\n fix: `Replace raw keys with env var refs: \"apiKey\": \"\\${${PROVIDER_ENV_MAP.anthropic}}\"`,\n category: \"agents\",\n })\n );\n }\n\n // Check 2: HIGH - models.json uses raw keys instead of ${ENV_VAR} references\n try {\n const content = fs.readFileSync(modelsJsonPath, {\n encoding: \"utf-8\",\n });\n const hasEnvRefs = ENV_VAR_PATTERN.test(content);\n if (keyHits.length > 0 && !hasEnvRefs) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Agent '${agentName}' uses raw keys instead of env var references`,\n details: [\n \"models.json contains no ${ENV_VAR} references\",\n \"All API keys should use environment variable substitution\",\n ],\n fix: 'Run \"clawguard migrate-env\" to auto-migrate keys to .env',\n category: \"agents\",\n })\n );\n issueCount++;\n }\n } catch {\n // Ignore read errors\n }\n\n // Check 3: MEDIUM - Config shadow detection\n if (globalModel) {\n const agentModel = getAgentModel(modelsJsonPath);\n if (agentModel && agentModel !== globalModel) {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: `Agent '${agentName}' model differs from global config`,\n details: [\n `Global model: ${globalModel}`,\n `Agent model: ${agentModel}`,\n \"This agent overrides the global model setting (config shadow)\",\n ],\n fix: \"Verify this is intentional. Remove agent-level model to use global setting.\",\n category: \"agents\",\n })\n );\n issueCount++;\n }\n }\n }\n\n if (agentCount > 0 && issueCount === 0) {\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: `${agentCount} agent config(s) scanned - no issues found`,\n category: \"agents\",\n })\n );\n }\n\n return findings;\n}\n\nfunction getGlobalModel(\n config: Record<string, unknown> | null\n): string | null {\n if (!config) return null;\n try {\n const models = config.models as Record<string, unknown> | undefined;\n if (!models) return null;\n // Look for default model in providers or top-level\n const defaultModel = models.default as string | undefined;\n if (defaultModel) return defaultModel;\n // Check providers for the first configured model\n const providers = models.providers as\n | Record<string, Record<string, unknown>>\n | undefined;\n if (providers) {\n for (const provider of Object.values(providers)) {\n if (provider.model) return String(provider.model);\n }\n }\n } catch {\n // Ignore\n }\n return null;\n}\n\nfunction getAgentModel(modelsJsonPath: string): string | null {\n try {\n const content = fs.readFileSync(modelsJsonPath, { encoding: \"utf-8\" });\n const data = JSON.parse(content) as Record<string, unknown>;\n // Agent models.json typically has a \"model\" or \"default\" field\n if (data.model) return String(data.model);\n if (data.default) return String(data.default);\n // Or check nested providers\n const providers = data.providers as\n | Record<string, Record<string, unknown>>\n | undefined;\n if (providers) {\n for (const provider of Object.values(providers)) {\n if (provider.model) return String(provider.model);\n }\n }\n } catch {\n // Ignore\n }\n return null;\n}\n","/**\n * Check LLM provider configurations for potential issues.\n * Catches free-tier TPM limits, rate limits, and missing web search keys.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\nimport {\n OPENCLAW_SYSTEM_PROMPT_TOKENS,\n PROVIDER_LIMITS,\n} from \"../patterns.js\";\nimport { parseConfig } from \"../utils.js\";\n\nexport function checkProviders(openclawPath: string): Finding[] {\n const findings: Finding[] = [];\n\n const config = parseConfig(path.join(openclawPath, \"openclaw.json\"));\n if (!config) return findings;\n\n const models = (config.models ?? {}) as Record<string, unknown>;\n const providers = (models.providers ?? {}) as Record<\n string,\n Record<string, unknown>\n >;\n\n const providerSummary: string[] = [];\n\n for (const [providerName, providerConfig] of Object.entries(providers)) {\n const lowerName = providerName.toLowerCase();\n providerSummary.push(\n `${providerName}: model=${String(providerConfig.model ?? \"default\")}`\n );\n\n // Check 1: HIGH - Provider free tier TPM < system prompt tokens\n const limits = PROVIDER_LIMITS[lowerName];\n if (limits && limits.tpm < OPENCLAW_SYSTEM_PROMPT_TOKENS) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Provider '${providerName}' TPM too low for system prompt`,\n details: [\n `${limits.note}`,\n `OpenClaw system prompt requires ~${OPENCLAW_SYSTEM_PROMPT_TOKENS} tokens`,\n `Provider free tier allows only ${limits.tpm} TPM`,\n \"System prompt alone exceeds the per-minute token limit\",\n ],\n fix: `Upgrade to a paid ${providerName} plan or switch to a provider with higher limits`,\n category: \"providers\",\n })\n );\n }\n\n // Check 2: MEDIUM - Provider free tier has very low rate limits\n if (limits && limits.rpm < 10) {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: `Provider '${providerName}' has very low rate limits (${limits.rpm} RPM)`,\n details: [\n `${limits.note}`,\n \"Low RPM causes frequent rate limit errors during conversations\",\n ],\n fix: `Consider upgrading ${providerName} plan or using a different provider`,\n category: \"providers\",\n })\n );\n }\n }\n\n // Check 3: MEDIUM - Web search tool has no API key configured\n const tools = (config.tools ?? {}) as Record<string, unknown>;\n const webSearch = (tools.webSearch ?? tools.web_search ?? {}) as Record<\n string,\n unknown\n >;\n const webSearchEnabled =\n webSearch.enabled !== false && Object.keys(webSearch).length > 0;\n\n if (webSearchEnabled) {\n const apiKey = webSearch.apiKey ?? webSearch.api_key;\n if (!apiKey) {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: \"Web search tool has no API key configured\",\n details: [\n \"tools.webSearch.apiKey is not set\",\n \"Web search will fail or use a very limited fallback\",\n ],\n fix: \"Set tools.webSearch.apiKey to your Brave Search API key (get one at brave.com/search/api)\",\n category: \"providers\",\n })\n );\n }\n }\n\n // Check 4: INFO - Provider configuration summary\n if (providerSummary.length > 0) {\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: `${providerSummary.length} LLM provider(s) configured`,\n details: providerSummary,\n category: \"providers\",\n })\n );\n }\n\n return findings;\n}\n"],"mappings":"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","names":["fs","chalk","fs","path","os","JSON5","chalk","fs","path","JSON5","path","fs","JSON5","fs","path","JSON5","path","fs","JSON5","fs","path","JSON5","path","fs","JSON5","fs","path","fs","path","execFileSync","fs","path","os","execFileSync","path","os","fs","fs","path","fs","path","fs","path","path","fs","fs","path","path","fs","path","path","path","os","fs","chalk","JSON5","VERSION","chalk","fs"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/models.ts","../src/reporter.ts","../src/scanner.ts","../src/checks/credentials.ts","../src/patterns.ts","../src/utils.ts","../src/checks/gateway.ts","../src/checks/sandbox.ts","../src/checks/permissions.ts","../src/checks/version.ts","../src/checks/skills.ts","../src/checks/memory.ts","../src/checks/agents.ts","../src/checks/providers.ts"],"sourcesContent":["/**\n * ClawGuard CLI - Security scanner for OpenClaw installations.\n */\n\nimport fs from \"node:fs\";\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { getCriticalCount } from \"./models.js\";\nimport { printBanner, printJson, printReport } from \"./reporter.js\";\nimport {\n CHECK_REGISTRY,\n detectOpenclawPath,\n runFix,\n runMigrateEnv,\n runScan,\n} from \"./scanner.js\";\n\nconst VERSION = \"0.2.0\";\n\nconst program = new Command();\n\nprogram\n .name(\"clawguard\")\n .description(\"Security scanner for OpenClaw AI agent installations\")\n .version(VERSION);\n\nprogram\n .command(\"scan\")\n .description(\"Scan your OpenClaw installation for security issues\")\n .option(\"-p, --path <path>\", \"Path to OpenClaw directory\")\n .option(\"-f, --format <format>\", \"Output format: rich or json\", \"rich\")\n .option(\n \"-c, --check <checks...>\",\n \"Run specific checks only\"\n )\n .action(\n async (options: {\n path?: string;\n format: string;\n check?: string[];\n }) => {\n // Detect or use provided path\n const openclawPath = options.path ?? detectOpenclawPath();\n\n if (!openclawPath) {\n console.log(chalk.red(\"Could not find OpenClaw installation.\"));\n console.log(\"Checked: ~/.openclaw, ~/.clawdbot, ~/.moltbot\");\n console.log(\"Use --path to specify the directory.\");\n process.exit(1);\n }\n\n if (!fs.existsSync(openclawPath)) {\n console.log(chalk.red(`Path does not exist: ${openclawPath}`));\n process.exit(1);\n }\n\n // Validate check names\n if (options.check) {\n const validChecks = new Set(Object.keys(CHECK_REGISTRY));\n for (const c of options.check) {\n if (!validChecks.has(c)) {\n console.log(chalk.red(`Unknown check: ${c}`));\n console.log(\n `Available: ${[...validChecks].sort().join(\", \")}`\n );\n process.exit(1);\n }\n }\n }\n\n // Run scan\n const result = await runScan(openclawPath, options.check);\n\n // Output\n if (options.format === \"json\") {\n printJson(result);\n } else {\n printReport(result);\n }\n\n // Exit with non-zero if critical issues found\n if (getCriticalCount(result) > 0) {\n process.exit(2);\n }\n }\n );\n\nprogram\n .command(\"fix\")\n .description(\n \"Auto-fix common security issues in your OpenClaw installation\"\n )\n .option(\"-p, --path <path>\", \"Path to OpenClaw directory\")\n .action((options: { path?: string }) => {\n const openclawPath = options.path ?? detectOpenclawPath();\n\n if (!openclawPath) {\n console.log(chalk.red(\"Could not find OpenClaw installation.\"));\n process.exit(1);\n }\n\n printBanner();\n console.log(\n `\\nFixing security issues in ${chalk.bold(openclawPath)} ...\\n`\n );\n\n const actions = runFix(openclawPath);\n\n if (actions.length > 0) {\n for (const action of actions) {\n console.log(` ${chalk.green(\"FIXED\")} ${action}`);\n }\n console.log(chalk.green(`\\n${actions.length} issue(s) fixed.`));\n console.log(\n `Run ${chalk.bold(\"clawguard scan\")} to verify.\\n`\n );\n } else {\n console.log(chalk.green(\"No auto-fixable issues found.\\n\"));\n }\n });\n\nprogram\n .command(\"migrate-env\")\n .description(\n \"Migrate plaintext API keys from config files to .env with ${REF} substitution\"\n )\n .option(\"-p, --path <path>\", \"Path to OpenClaw directory\")\n .option(\"--dry-run\", \"Show what would be migrated without making changes\")\n .action((options: { path?: string; dryRun?: boolean }) => {\n const openclawPath = options.path ?? detectOpenclawPath();\n\n if (!openclawPath) {\n console.log(chalk.red(\"Could not find OpenClaw installation.\"));\n process.exit(1);\n }\n\n if (!fs.existsSync(openclawPath)) {\n console.log(chalk.red(`Path does not exist: ${openclawPath}`));\n process.exit(1);\n }\n\n const dryRun = options.dryRun ?? false;\n if (dryRun) {\n console.log(chalk.cyan(\"\\n-- DRY RUN (no files will be modified) --\\n\"));\n }\n\n const result = runMigrateEnv(openclawPath, dryRun);\n\n if (result.migrations.length === 0) {\n console.log(chalk.green(\"No plaintext API keys found to migrate.\"));\n return;\n }\n\n console.log(\n chalk.bold(`\\nFound ${result.migrations.length} key(s) to migrate:\\n`)\n );\n\n for (const m of result.migrations) {\n console.log(\n ` ${chalk.cyan(m.envVar)} <- ${m.key} (${chalk.dim(m.file)})`\n );\n }\n\n if (dryRun) {\n console.log(\n chalk.cyan(\"\\nRun without --dry-run to apply these changes.\")\n );\n } else {\n console.log();\n if (result.envFileCreated) {\n console.log(\n chalk.green(\" Created/updated .env file (chmod 600)\")\n );\n }\n for (const f of result.configsUpdated) {\n console.log(\n chalk.green(` Updated ${f} with \\${ENV_VAR} references`)\n );\n }\n console.log(\n chalk.green(\n `\\n${result.migrations.length} key(s) migrated successfully.`\n )\n );\n console.log(\n `Run ${chalk.bold(\"clawguard scan\")} to verify.\\n`\n );\n }\n });\n\nprogram\n .command(\"version\")\n .description(\"Show ClawGuard version\")\n .action(() => {\n console.log(`ClawGuard v${VERSION}`);\n });\n\nprogram.parse();\n","/**\n * Data models for ClawGuard scan results.\n */\n\nimport { z } from \"zod\";\n\nexport const Severity = {\n CRITICAL: \"CRITICAL\",\n HIGH: \"HIGH\",\n MEDIUM: \"MEDIUM\",\n INFO: \"INFO\",\n} as const;\n\nexport type Severity = (typeof Severity)[keyof typeof Severity];\n\nexport const SEVERITY_DEDUCTIONS: Record<Severity, number> = {\n [Severity.CRITICAL]: 20,\n [Severity.HIGH]: 10,\n [Severity.MEDIUM]: 5,\n [Severity.INFO]: 0,\n};\n\nexport const FindingSchema = z.object({\n severity: z.enum([\"CRITICAL\", \"HIGH\", \"MEDIUM\", \"INFO\"]),\n title: z.string(),\n details: z.array(z.string()).default([]),\n fix: z.string().default(\"\"),\n category: z.string().default(\"\"),\n});\n\nexport type Finding = z.infer<typeof FindingSchema>;\n\nexport function createFinding(params: {\n severity: Severity;\n title: string;\n details?: string[];\n fix?: string;\n category?: string;\n}): Finding {\n return {\n severity: params.severity,\n title: params.title,\n details: params.details ?? [],\n fix: params.fix ?? \"\",\n category: params.category ?? \"\",\n };\n}\n\nexport interface ScanResult {\n findings: Finding[];\n openclawPath: string;\n openclawVersion: string | null;\n nodeVersion: string | null;\n}\n\nexport function createScanResult(\n openclawPath: string = \"\"\n): ScanResult {\n return {\n findings: [],\n openclawPath,\n openclawVersion: null,\n nodeVersion: null,\n };\n}\n\nexport function getScore(result: ScanResult): number {\n let total = 100;\n for (const f of result.findings) {\n total -= SEVERITY_DEDUCTIONS[f.severity];\n }\n return Math.max(0, total);\n}\n\nexport function getCriticalCount(result: ScanResult): number {\n return result.findings.filter((f) => f.severity === Severity.CRITICAL).length;\n}\n\nexport function getHighCount(result: ScanResult): number {\n return result.findings.filter((f) => f.severity === Severity.HIGH).length;\n}\n\nexport function getMediumCount(result: ScanResult): number {\n return result.findings.filter((f) => f.severity === Severity.MEDIUM).length;\n}\n\nexport function getInfoCount(result: ScanResult): number {\n return result.findings.filter((f) => f.severity === Severity.INFO).length;\n}\n","/**\n * Chalk-formatted output for ClawGuard scan results.\n */\n\nimport chalk from \"chalk\";\nimport {\n type Finding,\n type ScanResult,\n Severity,\n getScore,\n getCriticalCount,\n getHighCount,\n getMediumCount,\n getInfoCount,\n} from \"./models.js\";\n\nconst VERSION = \"0.2.0\";\n\nconst SEVERITY_COLORS: Record<Severity, (text: string) => string> = {\n [Severity.CRITICAL]: chalk.red.bold,\n [Severity.HIGH]: chalk.yellow.bold,\n [Severity.MEDIUM]: chalk.cyan.bold,\n [Severity.INFO]: chalk.green.bold,\n};\n\nfunction getScoreStyle(score: number): (text: string) => string {\n if (score <= 30) return chalk.red.bold;\n if (score <= 60) return chalk.yellow.bold;\n if (score <= 80) return chalk.cyan.bold;\n return chalk.green.bold;\n}\n\nfunction getScoreLabel(score: number): string {\n if (score <= 30) return \"Critical Risk\";\n if (score <= 60) return \"High Risk\";\n if (score <= 80) return \"Moderate Risk\";\n return \"Low Risk\";\n}\n\nexport function printBanner(): void {\n const banner = `${chalk.white.bold(\"ClawGuard\")}${chalk.dim(` v${VERSION}`)}${chalk.white(\" - OpenClaw Security Scanner\")}`;\n const border = chalk.blue(\"+\" + \"-\".repeat(banner.length - 20) + \"+\");\n console.log(border);\n console.log(chalk.blue(\"|\") + \" \" + banner + \" \" + chalk.blue(\"|\"));\n console.log(border);\n}\n\nexport function printFinding(finding: Finding): void {\n const colorFn = SEVERITY_COLORS[finding.severity];\n const severityTag = colorFn(finding.severity);\n\n console.log(`\\n ${severityTag} ${finding.title}`);\n for (const detail of finding.details) {\n console.log(chalk.dim(` ${detail}`));\n }\n if (finding.fix) {\n console.log(chalk.italic(` Fix: ${finding.fix}`));\n }\n}\n\nexport function printReport(result: ScanResult): void {\n printBanner();\n console.log(`\\nScanning ${chalk.bold(result.openclawPath)} ...\\n`);\n\n if (result.findings.length === 0) {\n console.log(chalk.green(\"No security issues found!\"));\n console.log(`\\nScore: ${chalk.green.bold(\"100/100 (Secure)\")}`);\n return;\n }\n\n // Sort: CRITICAL first, then HIGH, MEDIUM, INFO\n const severityOrder: Record<Severity, number> = {\n [Severity.CRITICAL]: 0,\n [Severity.HIGH]: 1,\n [Severity.MEDIUM]: 2,\n [Severity.INFO]: 3,\n };\n\n const sortedFindings = [...result.findings].sort(\n (a, b) => severityOrder[a.severity] - severityOrder[b.severity]\n );\n\n for (const finding of sortedFindings) {\n printFinding(finding);\n }\n\n // Summary\n console.log(\"\\n\" + \"=\".repeat(50));\n\n const score = getScore(result);\n const style = getScoreStyle(score);\n const label = getScoreLabel(score);\n console.log(`\\n Score: ${style(`${score}/100 (${label})`)}`);\n\n const summaryParts: string[] = [];\n const critical = getCriticalCount(result);\n const high = getHighCount(result);\n const medium = getMediumCount(result);\n const info = getInfoCount(result);\n\n if (critical) summaryParts.push(chalk.red(`${critical} critical`));\n if (high) summaryParts.push(chalk.yellow(`${high} high`));\n if (medium) summaryParts.push(chalk.cyan(`${medium} medium`));\n if (info) summaryParts.push(chalk.green(`${info} info`));\n\n console.log(` Found: ${summaryParts.join(\", \")}`);\n\n const fixable = result.findings.filter(\n (f) => f.fix && f.severity !== Severity.INFO\n ).length;\n if (fixable) {\n console.log(\n ` Run ${chalk.bold(\"clawguard fix\")} to auto-fix ${fixable} issues`\n );\n }\n\n console.log();\n}\n\nexport function printJson(result: ScanResult): void {\n const output = {\n score: getScore(result),\n openclaw_path: result.openclawPath,\n openclaw_version: result.openclawVersion,\n node_version: result.nodeVersion,\n summary: {\n critical: getCriticalCount(result),\n high: getHighCount(result),\n medium: getMediumCount(result),\n info: getInfoCount(result),\n },\n findings: result.findings.map((f) => ({\n severity: f.severity,\n title: f.title,\n details: f.details,\n fix: f.fix,\n category: f.category,\n })),\n };\n console.log(JSON.stringify(output, null, 2));\n}\n","/**\n * Main scanner orchestrator - runs all security checks.\n */\n\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport JSON5 from \"json5\";\nimport chalk from \"chalk\";\nimport { type Finding, type ScanResult, createScanResult } from \"./models.js\";\nimport { checkCredentials } from \"./checks/credentials.js\";\nimport { checkGateway } from \"./checks/gateway.js\";\nimport { checkSandbox } from \"./checks/sandbox.js\";\nimport { checkPermissions } from \"./checks/permissions.js\";\nimport { checkVersion } from \"./checks/version.js\";\nimport { checkSkills } from \"./checks/skills.js\";\nimport { checkMemory } from \"./checks/memory.js\";\nimport { checkAgents } from \"./checks/agents.js\";\nimport { checkProviders } from \"./checks/providers.js\";\nimport { API_KEY_PATTERNS, PROVIDER_ENV_MAP } from \"./patterns.js\";\nimport {\n findFilesRecursive,\n isDockerAvailable,\n parseConfig,\n getTotalMemoryGB,\n scanFileForKeys,\n} from \"./utils.js\";\n\ntype SyncCheckFn = (openclawPath: string) => Finding[];\ntype AsyncCheckFn = (openclawPath: string) => Promise<Finding[]>;\ntype CheckFn = SyncCheckFn | AsyncCheckFn;\n\n/** Map of check names to their functions */\nexport const CHECK_REGISTRY: Record<string, CheckFn> = {\n credentials: checkCredentials,\n gateway: checkGateway,\n sandbox: checkSandbox,\n permissions: checkPermissions,\n skills: checkSkills,\n memory: checkMemory,\n agents: checkAgents,\n providers: checkProviders,\n};\n\nexport function detectOpenclawPath(): string | null {\n const candidates: string[] = [\n path.join(os.homedir(), \".openclaw\"),\n path.join(os.homedir(), \".clawdbot\"), // Legacy name\n path.join(os.homedir(), \".moltbot\"), // Legacy name\n ];\n\n const envPath = process.env.OPENCLAW_HOME;\n if (envPath) {\n candidates.unshift(envPath);\n }\n\n for (const candidate of candidates) {\n if (\n fs.existsSync(candidate) &&\n fs.statSync(candidate).isDirectory()\n ) {\n return candidate;\n }\n }\n\n return null;\n}\n\nexport async function runScan(\n openclawPath: string,\n checks?: string[]\n): Promise<ScanResult> {\n const result = createScanResult(openclawPath);\n\n // Version check (always runs, returns version info)\n process.stdout.write(chalk.blue(\"Checking versions...\\r\"));\n const {\n findings: versionFindings,\n openclawVersion,\n nodeVersion,\n } = checkVersion(openclawPath);\n result.findings.push(...versionFindings);\n result.openclawVersion = openclawVersion;\n result.nodeVersion = nodeVersion;\n\n // Run selected or all checks\n const activeChecks = checks ?? Object.keys(CHECK_REGISTRY);\n\n for (const checkName of activeChecks) {\n if (!(checkName in CHECK_REGISTRY)) {\n continue;\n }\n\n const checkFn = CHECK_REGISTRY[checkName];\n const label = checkName.replace(/_/g, \" \").replace(/\\b\\w/g, (c) => c.toUpperCase());\n\n process.stdout.write(chalk.blue(`Checking ${label}...\\r`));\n try {\n const findings = await checkFn(openclawPath);\n result.findings.push(...findings);\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n console.log(chalk.yellow(`Warning: ${checkName} check failed: ${message}`));\n }\n }\n\n // Clear the status line\n process.stdout.write(\" \\r\");\n\n return result;\n}\n\nexport function runFix(openclawPath: string): string[] {\n const actions: string[] = [];\n\n // Fix 1: File permissions\n if (fs.existsSync(openclawPath)) {\n const currentMode = fs.statSync(openclawPath).mode & 0o777;\n const current = \"0o\" + currentMode.toString(8);\n if (current !== \"0o700\") {\n fs.chmodSync(openclawPath, 0o700);\n actions.push(`Fixed ${openclawPath} permissions: ${current} -> 0o700`);\n }\n }\n\n const configFile = path.join(openclawPath, \"openclaw.json\");\n if (fs.existsSync(configFile)) {\n const currentMode = fs.statSync(configFile).mode & 0o777;\n const current = \"0o\" + currentMode.toString(8);\n if (current !== \"0o600\") {\n fs.chmodSync(configFile, 0o600);\n actions.push(\n `Fixed ${path.basename(configFile)} permissions: ${current} -> 0o600`\n );\n }\n }\n\n const credsDir = path.join(openclawPath, \"credentials\");\n if (fs.existsSync(credsDir) && fs.statSync(credsDir).isDirectory()) {\n try {\n const entries = fs.readdirSync(credsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isFile()) {\n const filePath = path.join(credsDir, entry.name);\n const currentMode = fs.statSync(filePath).mode & 0o777;\n const current = \"0o\" + currentMode.toString(8);\n if (current !== \"0o600\") {\n fs.chmodSync(filePath, 0o600);\n actions.push(\n `Fixed ${entry.name} permissions: ${current} -> 0o600`\n );\n }\n }\n }\n } catch {\n // Ignore errors\n }\n }\n\n // Fix 2: Config changes (sandbox-aware)\n if (fs.existsSync(configFile)) {\n try {\n const content = fs.readFileSync(configFile, { encoding: \"utf-8\" });\n const config = JSON5.parse(content) as Record<string, Record<string, unknown>>;\n\n let modified = false;\n const dockerInstalled = isDockerAvailable();\n\n // Sandbox changes: only apply if Docker is available\n if (dockerInstalled) {\n // Enable sandbox\n if (!config.agents) config.agents = {};\n const agents = config.agents as Record<string, Record<string, unknown>>;\n if (!agents.defaults) agents.defaults = {};\n const defaults = agents.defaults as Record<string, Record<string, unknown>>;\n if (!defaults.sandbox) defaults.sandbox = {};\n const sandbox = defaults.sandbox as Record<string, unknown>;\n\n if ((sandbox.mode as string) === \"off\" || !sandbox.mode) {\n sandbox.mode = \"all\";\n sandbox.scope = \"session\";\n modified = true;\n actions.push('Enabled sandbox: agents.defaults.sandbox.mode = \"all\"');\n }\n\n // Set Docker network to none\n if (!sandbox.docker) sandbox.docker = {};\n const docker = sandbox.docker as Record<string, unknown>;\n if (docker.network !== \"none\") {\n docker.network = \"none\";\n modified = true;\n actions.push('Set sandbox.docker.network = \"none\"');\n }\n\n // Ensure exec host is sandbox\n if (!config.tools) config.tools = {};\n const tools = config.tools as Record<string, Record<string, unknown>>;\n if (!tools.exec) tools.exec = {};\n const execConfig = tools.exec as Record<string, unknown>;\n if (execConfig.host === \"gateway\") {\n execConfig.host = \"sandbox\";\n modified = true;\n actions.push('Set tools.exec.host = \"sandbox\"');\n }\n } else {\n actions.push(\n chalk.yellow(\"Sandbox changes skipped: Docker not installed. Install Docker to enable sandbox isolation.\")\n );\n }\n\n // Always apply safe fixes regardless of Docker\n\n // Enable logging redaction\n if (!config.logging) config.logging = {};\n const loggingConfig = config.logging as Record<string, unknown>;\n if (\n loggingConfig.redactSensitive === undefined ||\n loggingConfig.redactSensitive === null ||\n loggingConfig.redactSensitive === \"off\"\n ) {\n loggingConfig.redactSensitive = \"tools\";\n modified = true;\n actions.push('Enabled logging.redactSensitive = \"tools\"');\n }\n\n // Generate strong gateway token if missing/weak\n if (!config.gateway) config.gateway = {};\n const gateway = config.gateway as Record<string, Record<string, unknown>>;\n if (!gateway.auth) gateway.auth = {};\n const auth = gateway.auth as Record<string, unknown>;\n const token = auth.token as string | undefined;\n if (!token || String(token).length < 32) {\n const newToken = crypto.randomBytes(32).toString(\"hex\");\n auth.token = newToken;\n modified = true;\n actions.push(\n `Generated strong gateway token (${newToken.length} chars)`\n );\n }\n\n if (modified) {\n fs.writeFileSync(configFile, JSON.stringify(config, null, 2));\n }\n\n // Post-fix warnings\n const ramGB = getTotalMemoryGB();\n if (ramGB < 2) {\n actions.push(\n chalk.yellow(`Warning: System has only ${ramGB.toFixed(1)}GB RAM. Set NODE_OPTIONS=\"--max-old-space-size=512\" to prevent OOM kills.`)\n );\n }\n\n // Suggest migrate-env if plaintext keys found\n const hits = scanFileForKeys(configFile);\n if (hits.length > 0) {\n actions.push(\n `Tip: Run ${chalk.bold(\"clawguard migrate-env\")} to move ${hits.length} plaintext key(s) to .env`\n );\n }\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n actions.push(`Could not modify config: ${message}`);\n }\n }\n\n // Fix 3: Delete .bak files\n const bakFiles = findFilesRecursive(openclawPath, \".bak\", \"extension\");\n for (const bakFile of bakFiles) {\n fs.unlinkSync(bakFile);\n actions.push(`Deleted backup file: ${path.basename(bakFile)}`);\n }\n\n return actions;\n}\n\nexport interface MigrateEnvResult {\n migrations: Array<{ file: string; key: string; envVar: string }>;\n envFileCreated: boolean;\n configsUpdated: string[];\n}\n\nexport function runMigrateEnv(\n openclawPath: string,\n dryRun = false\n): MigrateEnvResult {\n const result: MigrateEnvResult = {\n migrations: [],\n envFileCreated: false,\n configsUpdated: [],\n };\n\n // Collect all config files to process\n const configFiles: string[] = [];\n const mainConfig = path.join(openclawPath, \"openclaw.json\");\n if (fs.existsSync(mainConfig)) {\n configFiles.push(mainConfig);\n }\n\n // Find all agent models.json files\n const agentsDir = path.join(openclawPath, \"agents\");\n const modelsFiles = findFilesRecursive(agentsDir, \"models.json\", \"exact\");\n configFiles.push(...modelsFiles);\n\n // Build a map of raw key values -> env var names\n const keyToEnvVar = new Map<string, string>();\n\n for (const configFile of configFiles) {\n try {\n const content = fs.readFileSync(configFile, { encoding: \"utf-8\" });\n const lines = content.split(\"\\n\");\n\n for (const line of lines) {\n // Skip lines already using env var references\n if (/\\$\\{[A-Z_][A-Z0-9_]*\\}/.test(line)) continue;\n\n for (const [keyName, pattern] of API_KEY_PATTERNS) {\n const globalPattern = new RegExp(\n pattern.source,\n pattern.flags + (pattern.flags.includes(\"g\") ? \"\" : \"g\")\n );\n let match: RegExpExecArray | null;\n\n while ((match = globalPattern.exec(line)) !== null) {\n const rawKey = match[0];\n if (keyToEnvVar.has(rawKey)) continue;\n\n // Determine env var name from key type\n const envVar = guessEnvVarName(keyName, line);\n keyToEnvVar.set(rawKey, envVar);\n result.migrations.push({\n file: path.relative(openclawPath, configFile),\n key: rawKey.slice(0, 8) + \"...\" + rawKey.slice(-4),\n envVar,\n });\n }\n }\n }\n } catch {\n // Ignore read errors\n }\n }\n\n if (result.migrations.length === 0) {\n return result;\n }\n\n if (dryRun) {\n return result;\n }\n\n // Create/append .env file\n const envFilePath = path.join(openclawPath, \".env\");\n const existingEnv = fs.existsSync(envFilePath)\n ? fs.readFileSync(envFilePath, { encoding: \"utf-8\" })\n : \"\";\n const existingKeys = new Set(\n existingEnv\n .split(\"\\n\")\n .filter((l) => l.includes(\"=\"))\n .map((l) => l.split(\"=\")[0].trim())\n );\n\n const newEnvLines: string[] = [];\n for (const [rawKey, envVar] of keyToEnvVar) {\n if (!existingKeys.has(envVar)) {\n newEnvLines.push(`${envVar}=${rawKey}`);\n }\n }\n\n if (newEnvLines.length > 0) {\n const separator = existingEnv.endsWith(\"\\n\") || existingEnv === \"\" ? \"\" : \"\\n\";\n fs.appendFileSync(envFilePath, separator + newEnvLines.join(\"\\n\") + \"\\n\");\n result.envFileCreated = true;\n\n // Set permissions on .env\n try {\n fs.chmodSync(envFilePath, 0o600);\n } catch {\n // May fail on some systems\n }\n }\n\n // Replace plaintext keys in config files with ${ENV_VAR_NAME}\n for (const configFile of configFiles) {\n try {\n let content = fs.readFileSync(configFile, { encoding: \"utf-8\" });\n let modified = false;\n\n for (const [rawKey, envVar] of keyToEnvVar) {\n if (content.includes(rawKey)) {\n content = content.split(rawKey).join(`\\${${envVar}}`);\n modified = true;\n }\n }\n\n if (modified) {\n fs.writeFileSync(configFile, content);\n result.configsUpdated.push(\n path.relative(openclawPath, configFile)\n );\n }\n } catch {\n // Ignore write errors\n }\n }\n\n return result;\n}\n\nfunction guessEnvVarName(keyName: string, contextLine: string): string {\n const lower = keyName.toLowerCase();\n\n // Check PROVIDER_ENV_MAP first\n for (const [provider, envVar] of Object.entries(PROVIDER_ENV_MAP)) {\n if (lower.includes(provider)) return envVar;\n }\n\n // Try to guess from JSON key context\n if (contextLine.includes(\"telegram\")) return \"TELEGRAM_BOT_TOKEN\";\n if (contextLine.includes(\"discord\")) return \"DISCORD_BOT_TOKEN\";\n if (contextLine.includes(\"slack\")) return \"SLACK_BOT_TOKEN\";\n if (contextLine.includes(\"brave\") || contextLine.includes(\"webSearch\"))\n return \"BRAVE_SEARCH_API_KEY\";\n if (contextLine.includes(\"stripe\")) return \"STRIPE_SECRET_KEY\";\n\n // Fallback: generate from key name\n return keyName.toUpperCase().replace(/[\\s/]/g, \"_\").replace(/[^A-Z0-9_]/g, \"\");\n}\n","/**\n * Scan for plaintext credentials in OpenClaw configuration files.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport JSON5 from \"json5\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\nimport { API_KEY_PATTERNS } from \"../patterns.js\";\nimport {\n findFilesRecursive,\n getRelativePath,\n scanFileForKeys,\n} from \"../utils.js\";\n\nexport function checkCredentials(openclawPath: string): Finding[] {\n const findings: Finding[] = [];\n\n // Files to scan for plaintext API keys\n const configFiles: string[] = [\n path.join(openclawPath, \"openclaw.json\"),\n path.join(openclawPath, \"credentials\", \"profiles.json\"),\n ];\n\n // Add all auth-profiles.json files\n const agentsDir = path.join(openclawPath, \"agents\");\n if (fs.existsSync(agentsDir) && fs.statSync(agentsDir).isDirectory()) {\n try {\n for (const agentEntry of fs.readdirSync(agentsDir)) {\n const authFile = path.join(\n agentsDir,\n agentEntry,\n \"agent\",\n \"auth-profiles.json\"\n );\n if (fs.existsSync(authFile)) {\n configFiles.push(authFile);\n }\n }\n } catch {\n // Ignore permission errors\n }\n }\n\n // NOTE: .env files are NOT scanned — they are the EXPECTED secure storage\n // location for API keys. Only flag keys in JSON config files.\n\n // Scan config files (JSON configs only, not .env)\n const allHits: string[] = [];\n for (const filepath of configFiles) {\n if (fs.existsSync(filepath)) {\n const hits = scanFileForKeys(filepath);\n for (const { keyName, masked, lineNum } of hits) {\n const relPath = getRelativePath(filepath, openclawPath);\n allHits.push(`${relPath}:${lineNum} - ${keyName} (${masked})`);\n }\n }\n }\n\n if (allHits.length > 0) {\n findings.push(\n createFinding({\n severity: Severity.CRITICAL,\n title: `${allHits.length} API key(s) stored in plaintext config files`,\n details: allHits.slice(0, 10), // Show max 10\n fix: 'Move keys to .env and use env var refs: \"apiKey\": \"${ANTHROPIC_API_KEY}\"',\n category: \"credentials\",\n })\n );\n }\n\n // Check for .bak files with credentials\n const bakWithKeys: string[] = [];\n const bakFiles = findFilesRecursive(openclawPath, \".bak\", \"extension\");\n for (const bakFile of bakFiles) {\n const hits = scanFileForKeys(bakFile);\n if (hits.length > 0) {\n bakWithKeys.push(getRelativePath(bakFile, openclawPath));\n }\n }\n\n if (bakWithKeys.length > 0) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `${bakWithKeys.length} backup file(s) contain credentials`,\n details: bakWithKeys,\n fix: \"Delete backup files: rm ~/.openclaw/*.bak\",\n category: \"credentials\",\n })\n );\n }\n\n // Scan transcript files for leaked secrets\n const transcriptHits: string[] = [];\n if (fs.existsSync(agentsDir) && fs.statSync(agentsDir).isDirectory()) {\n const jsonlFiles = findFilesRecursive(agentsDir, \".jsonl\", \"extension\");\n for (const jsonlFile of jsonlFiles) {\n try {\n const content = fs.readFileSync(jsonlFile, { encoding: \"utf-8\" });\n const lines = content.split(\"\\n\");\n let found = false;\n\n for (let i = 0; i < Math.min(lines.length, 501); i++) {\n const line = lines[i];\n for (const [keyName, pattern] of API_KEY_PATTERNS) {\n if (pattern.test(line)) {\n transcriptHits.push(\n `${getRelativePath(jsonlFile, openclawPath)} - ${keyName} found in transcript`\n );\n found = true;\n break;\n }\n }\n if (found) break;\n }\n } catch {\n // Ignore permission errors\n }\n }\n }\n\n if (transcriptHits.length > 0) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `API keys leaked in ${transcriptHits.length} session transcript(s)`,\n details: transcriptHits.slice(0, 5),\n fix: \"Delete old transcripts and enable logging.redactSensitive in config\",\n category: \"credentials\",\n })\n );\n }\n\n // Check logging redaction settings\n const configFile = path.join(openclawPath, \"openclaw.json\");\n if (fs.existsSync(configFile)) {\n try {\n const content = fs.readFileSync(configFile, { encoding: \"utf-8\" });\n const config = JSON5.parse(content) as Record<string, unknown>;\n const loggingConfig = (config.logging ?? {}) as Record<string, unknown>;\n const redact = loggingConfig.redactSensitive;\n\n if (redact === undefined || redact === null || redact === \"off\") {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: \"Sensitive data redaction is disabled in logs\",\n details: ['logging.redactSensitive is not set or set to \"off\"'],\n fix: 'Set logging.redactSensitive to \"tools\" or \"all\" in openclaw.json',\n category: \"credentials\",\n })\n );\n }\n } catch {\n // Ignore parse errors\n }\n }\n\n return findings;\n}\n\n","/**\n * Regex patterns for detecting API keys, secrets, and malicious content.\n */\n\n/** API key patterns - each tuple is [name, regex] */\nexport const API_KEY_PATTERNS: Array<[string, RegExp]> = [\n [\"Anthropic API key\", /sk-ant-[a-zA-Z0-9_-]{20,}/],\n [\"OpenAI API key\", /sk-proj-[a-zA-Z0-9_-]{20,}/],\n [\"OpenAI legacy key\", /sk-[a-zA-Z0-9]{40,}/],\n [\"Groq API key\", /gsk_[a-zA-Z0-9]{20,}/],\n [\"xAI/Grok API key\", /xai-[a-zA-Z0-9]{20,}/],\n [\"AWS Access Key\", /AKIA[0-9A-Z]{16}/],\n [\"GitHub PAT\", /ghp_[a-zA-Z0-9]{36}/],\n [\"GitHub OAuth\", /gho_[a-zA-Z0-9]{36}/],\n [\"GitLab PAT\", /glpat-[a-zA-Z0-9_-]{20,}/],\n [\"Slack Bot Token\", /xoxb-[0-9]+-[0-9]+-[a-zA-Z0-9]+/],\n [\"Slack User Token\", /xoxp-[0-9]+-[0-9]+-[0-9]+-[a-f0-9]+/],\n [\"Telegram Bot Token\", /[0-9]{8,10}:[a-zA-Z0-9_-]{35}/],\n [\"Discord Bot Token\", /[MN][A-Za-z\\d]{23,}\\.[\\w-]{6}\\.[\\w-]{27,}/],\n [\"OpenRouter API key\", /sk-or-v1-[a-f0-9]{64}/],\n [\"Google API key\", /AIza[0-9A-Za-z_-]{35}/],\n [\"Stripe Secret key\", /sk_live_[a-zA-Z0-9]{20,}/],\n [\"Generic Bearer token\", /Bearer\\s+[a-zA-Z0-9_.-]{20,}/],\n [\"Brave Search API key\", /BSA[a-zA-Z0-9]{20,}/],\n];\n\n/** Environment variable reference pattern (${VAR_NAME}) */\nexport const ENV_VAR_PATTERN = /\\$\\{[A-Z_][A-Z0-9_]*\\}/;\n\n/** Malicious skill patterns */\nexport const MALICIOUS_PATTERNS: Array<[string, RegExp]> = [\n [\n \"Base64 encoded payload\",\n /(?:base64\\s+(?:-d|--decode)|atob|b64decode)\\s*[(\\s]/,\n ],\n [\"Base64 long string\", /[A-Za-z0-9+/]{60,}={0,2}/],\n [\"curl pipe to shell\", /curl\\s+.*\\|\\s*(?:ba)?sh/],\n [\"wget pipe to shell\", /wget\\s+.*\\|\\s*(?:ba)?sh/],\n [\"curl to eval\", /curl\\s+.*\\$\\(/],\n [\n \"Python exec/eval\",\n /(?:exec|eval)\\s*\\(\\s*(?:base64|requests|urllib)/,\n ],\n [\n \"Paste service URL\",\n /(?:glot\\.io|pastebin\\.com|paste\\.ee|hastebin\\.com|dpaste\\.com)/,\n ],\n [\n \"Password-protected archive\",\n /(?:unzip|7z|tar)\\s+.*(?:-p\\s*|-P\\s*|--password)/,\n ],\n [\"Reverse shell\", /(?:nc|ncat|netcat)\\s+.*-e\\s+\\/bin/],\n [\"Python reverse shell\", /socket\\.connect\\s*\\(\\s*\\(\\s*[\"'][\\d.]+/],\n [\"Download and execute\", /(?:curl|wget)\\s+.*&&\\s*chmod\\s+\\+x/],\n];\n\n/** Known C2 IP addresses from ClawHavoc campaign */\nexport const KNOWN_C2_IPS = [\"91.92.242.30\", \"54.91.154.110\"];\n\n/** C2 IP regex (also catches 95.92.242.* range) */\nexport const C2_IP_PATTERN =\n /(?:91\\.92\\.242\\.\\d+|95\\.92\\.242\\.\\d+|54\\.91\\.154\\.110)/;\n\n/** Typosquatting publisher names */\nexport const TYPOSQUAT_PUBLISHERS = [\n \"clawhub1\",\n \"clawhubb\",\n \"clawhubbcli\",\n \"clawhub-official\",\n \"openclaw-official\",\n];\n\n/** Suspicious binaries in skill requirements */\nexport const SUSPICIOUS_BINS = [\n \"nc\",\n \"ncat\",\n \"netcat\",\n \"nmap\",\n \"socat\",\n \"msfconsole\",\n \"msfvenom\",\n \"metasploit\",\n \"hydra\",\n \"john\",\n \"hashcat\",\n \"tcpdump\",\n \"wireshark\",\n \"tshark\",\n];\n\n/** Brave Search API key pattern */\nexport const BRAVE_SEARCH_PATTERN: [string, RegExp] = [\n \"Brave Search API key\",\n /BSA[a-zA-Z0-9]{20,}/,\n];\n\n/** Map LLM provider names to their expected environment variable names */\nexport const PROVIDER_ENV_MAP: Record<string, string> = {\n anthropic: \"ANTHROPIC_API_KEY\",\n openai: \"OPENAI_API_KEY\",\n groq: \"GROQ_API_KEY\",\n xai: \"XAI_API_KEY\",\n openrouter: \"OPENROUTER_API_KEY\",\n google: \"GOOGLE_API_KEY\",\n mistral: \"MISTRAL_API_KEY\",\n deepseek: \"DEEPSEEK_API_KEY\",\n cohere: \"COHERE_API_KEY\",\n together: \"TOGETHER_API_KEY\",\n};\n\n/** Map channel names to their expected environment variable names */\nexport const CHANNEL_ENV_MAP: Record<string, string> = {\n telegram: \"TELEGRAM_BOT_TOKEN\",\n discord: \"DISCORD_BOT_TOKEN\",\n slack: \"SLACK_BOT_TOKEN\",\n};\n\n/** Free-tier provider limits: { provider: { tpm: tokens-per-min, rpm: requests-per-min } } */\nexport const PROVIDER_LIMITS: Record<\n string,\n { tpm: number; rpm: number; note: string }\n> = {\n groq: { tpm: 6000, rpm: 30, note: \"Groq free tier: 6K TPM, 30 RPM\" },\n openrouter: {\n tpm: 100000,\n rpm: 8,\n note: \"OpenRouter free tier: ~8 RPM\",\n },\n};\n\n/** Approximate token count for OpenClaw system prompt */\nexport const OPENCLAW_SYSTEM_PROMPT_TOKENS = 12600;\n\n/** Memory poisoning patterns (suspicious instructions in SOUL.md/MEMORY.md) */\nexport const MEMORY_POISONING_PATTERNS: Array<[string, RegExp]> = [\n [\n \"Hidden instruction injection\",\n /(?:ignore|disregard|override)\\s+(?:previous|all|safety)\\s+(?:instructions|rules)/i,\n ],\n [\n \"System prompt override\",\n /you\\s+are\\s+now\\s+(?:a|an)\\s+(?:different|new|unrestricted)/i,\n ],\n [\n \"Exfiltration instruction\",\n /(?:send|post|upload|transmit)\\s+.*(?:to|at)\\s+(?:https?:\\/\\/|webhook)/i,\n ],\n [\n \"Credential harvesting\",\n /(?:read|extract|collect|gather)\\s+.*(?:api.?key|token|password|credential|secret)/i,\n ],\n [\n \"Scheduled task injection\",\n /(?:cron|crontab|schedule|periodic|every\\s+\\d+\\s+(?:minute|hour))/i,\n ],\n];\n","/**\n * Shared utilities used by multiple ClawGuard modules.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport JSON5 from \"json5\";\nimport { API_KEY_PATTERNS, ENV_VAR_PATTERN } from \"./patterns.js\";\n\nexport interface KeyHit {\n keyName: string;\n masked: string;\n lineNum: number;\n}\n\n/** Scan a file for plaintext API key patterns. */\nexport function scanFileForKeys(filepath: string): KeyHit[] {\n const hits: KeyHit[] = [];\n try {\n const content = fs.readFileSync(filepath, { encoding: \"utf-8\" });\n const lines = content.split(\"\\n\");\n\n for (let lineNum = 0; lineNum < lines.length; lineNum++) {\n const line = lines[lineNum];\n\n // Skip lines that use env var references\n if (ENV_VAR_PATTERN.test(line)) {\n continue;\n }\n\n for (const [keyName, pattern] of API_KEY_PATTERNS) {\n const globalPattern = new RegExp(\n pattern.source,\n pattern.flags + (pattern.flags.includes(\"g\") ? \"\" : \"g\")\n );\n let match: RegExpExecArray | null;\n\n while ((match = globalPattern.exec(line)) !== null) {\n const matched = match[0];\n const masked =\n matched.length > 16\n ? matched.slice(0, 8) + \"...\" + matched.slice(-4)\n : matched.slice(0, 4) + \"...\";\n hits.push({ keyName, masked, lineNum: lineNum + 1 });\n }\n }\n }\n } catch {\n // PermissionError or FileNotFoundError equivalent\n }\n return hits;\n}\n\n/** Parse openclaw.json (with JSON5 support). Returns null on failure. */\nexport function parseConfig(\n configPath: string\n): Record<string, unknown> | null {\n try {\n const content = fs.readFileSync(configPath, { encoding: \"utf-8\" });\n return JSON5.parse(content) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\n/** Recursively find files matching an extension or exact name. */\nexport function findFilesRecursive(\n dir: string,\n match: string,\n mode: \"extension\" | \"exact\" = \"extension\"\n): string[] {\n const results: string[] = [];\n\n if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {\n return results;\n }\n\n try {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n results.push(...findFilesRecursive(fullPath, match, mode));\n } else if (entry.isFile()) {\n if (mode === \"extension\" && entry.name.endsWith(match)) {\n results.push(fullPath);\n } else if (mode === \"exact\" && entry.name === match) {\n results.push(fullPath);\n }\n }\n }\n } catch {\n // Ignore permission errors\n }\n\n return results;\n}\n\n/** Check if Docker is installed and available. */\nexport function isDockerAvailable(): boolean {\n try {\n execFileSync(\"which\", [\"docker\"], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n}\n\n/** Get total system memory in GB. */\nexport function getTotalMemoryGB(): number {\n return os.totalmem() / (1024 * 1024 * 1024);\n}\n\n/** Get a relative path from a file to its base OpenClaw directory. */\nexport function getRelativePath(\n filePath: string,\n basePath: string\n): string {\n const parentDir = path.dirname(basePath);\n return path.relative(parentDir, filePath);\n}\n","/**\n * Check gateway security configuration.\n */\n\nimport { execSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport JSON5 from \"json5\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\nimport { getTotalMemoryGB } from \"../utils.js\";\n\n/**\n * Check if a port is listening on all interfaces by parsing `ss -tlnp` output.\n *\n * `ss -tlnp` columns (0-indexed):\n * 0: State 1: Recv-Q 2: Send-Q 3: Local Address:Port 4: Peer Address:Port\n *\n * Column 3 (Local Address) tells us what the socket is bound to:\n * - 127.0.0.1:PORT or [::1]:PORT => loopback only (safe)\n * - 0.0.0.0:PORT or *:PORT or [::]:PORT => all interfaces (exposed)\n *\n * Column 4 (Peer Address) is always 0.0.0.0:* or *:* for LISTEN sockets\n * and must NOT be used to determine binding.\n */\nfunction checkPortExposed(port: number): boolean {\n if (process.platform !== \"linux\") {\n return false;\n }\n try {\n const output = execSync(`ss -tlnp`, { encoding: \"utf-8\", timeout: 5000 });\n const lines = output.split(\"\\n\");\n for (const line of lines) {\n // Split on whitespace; columns: State, Recv-Q, Send-Q, Local Addr:Port, Peer Addr:Port, ...\n const columns = line.trim().split(/\\s+/);\n if (columns.length < 5) continue;\n\n const localAddr = columns[3]; // e.g. \"127.0.0.1:18789\" or \"0.0.0.0:18789\" or \"*:18789\"\n\n // Extract port from local address — port is after the last ':'\n const lastColon = localAddr.lastIndexOf(\":\");\n if (lastColon === -1) continue;\n const portStr = localAddr.substring(lastColon + 1);\n if (parseInt(portStr, 10) !== port) continue;\n\n // Extract the host part (everything before the last colon)\n const host = localAddr.substring(0, lastColon);\n\n // Check if bound to all interfaces\n if (host === \"0.0.0.0\" || host === \"*\" || host === \"[::]\" || host === \"::\") {\n return true;\n }\n }\n return false;\n } catch {\n return false;\n }\n}\n\nexport function checkGateway(openclawPath: string): Finding[] {\n const findings: Finding[] = [];\n const configFile = path.join(openclawPath, \"openclaw.json\");\n\n if (!fs.existsSync(configFile)) {\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: \"No OpenClaw config file found\",\n details: [`Expected at ${configFile}`],\n category: \"gateway\",\n })\n );\n return findings;\n }\n\n let config: Record<string, unknown>;\n try {\n const content = fs.readFileSync(configFile, { encoding: \"utf-8\" });\n config = JSON5.parse(content) as Record<string, unknown>;\n } catch {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: \"Could not parse OpenClaw config file\",\n details: [\"openclaw.json may be malformed\"],\n category: \"gateway\",\n })\n );\n return findings;\n }\n\n const gateway = (config.gateway ?? {}) as Record<string, unknown>;\n\n // Check bind setting\n const bind = (gateway.bind as string) ?? \"loopback\";\n if (bind !== \"loopback\") {\n findings.push(\n createFinding({\n severity: Severity.CRITICAL,\n title: `Gateway bound to non-loopback: ${bind}`,\n details: [\n `gateway.bind = \"${bind}\"`,\n \"This exposes the gateway to network access\",\n ],\n fix: 'Set gateway.bind to \"loopback\" in openclaw.json',\n category: \"gateway\",\n })\n );\n }\n\n // Check auth token\n const auth = (gateway.auth as Record<string, unknown>) ?? {};\n const token =\n (auth.token as string) ?? (gateway.token as string) ?? \"\";\n if (!token) {\n findings.push(\n createFinding({\n severity: Severity.CRITICAL,\n title: \"No gateway authentication token configured\",\n details: [\n \"Anyone with network access can control your OpenClaw agent\",\n ],\n fix: \"Set gateway.auth.token in openclaw.json or re-run openclaw setup\",\n category: \"gateway\",\n })\n );\n } else if (String(token).length < 32) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Gateway auth token is weak (${String(token).length} chars)`,\n details: [\"Minimum recommended length: 32 characters\"],\n fix: \"Generate a strong token: openssl rand -hex 32\",\n category: \"gateway\",\n })\n );\n }\n\n // Check port exposure\n const port = (gateway.port as number) ?? 18789;\n const portExposed = checkPortExposed(port);\n if (portExposed) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Gateway port ${port} is reachable on all interfaces`,\n details: [\n `Port ${port} appears to be listening on 0.0.0.0`,\n \"The gateway may be accessible from the network\",\n ],\n fix: \"Bind to loopback only and use a reverse proxy if external access is needed\",\n category: \"gateway\",\n })\n );\n }\n\n // Infrastructure check: RAM\n const ramGB = getTotalMemoryGB();\n const nodeOptions = process.env.NODE_OPTIONS ?? \"\";\n if (ramGB < 2) {\n if (!nodeOptions.includes(\"max-old-space-size\")) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `System has only ${ramGB.toFixed(1)}GB RAM without NODE_OPTIONS set`,\n details: [\n `Total RAM: ${ramGB.toFixed(1)}GB`,\n \"OpenClaw may be killed by OOM without memory limits\",\n \"NODE_OPTIONS environment variable is not set\",\n ],\n fix: 'Set NODE_OPTIONS=\"--max-old-space-size=512\" in your service file or shell profile',\n category: \"gateway\",\n })\n );\n }\n }\n\n // Infrastructure check: systemd service (Linux only)\n if (process.platform === \"linux\") {\n const serviceFiles = [\n \"/etc/systemd/system/openclaw.service\",\n \"/etc/systemd/system/openclaw-gateway.service\",\n ];\n for (const serviceFile of serviceFiles) {\n if (!fs.existsSync(serviceFile)) continue;\n try {\n const serviceContent = fs.readFileSync(serviceFile, { encoding: \"utf-8\" });\n // Check missing NODE_OPTIONS in service\n if (ramGB < 2 && !serviceContent.includes(\"NODE_OPTIONS\")) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Systemd service missing NODE_OPTIONS (${path.basename(serviceFile)})`,\n details: [\n `Low RAM system (${ramGB.toFixed(1)}GB) but service has no NODE_OPTIONS`,\n \"Add Environment=NODE_OPTIONS=--max-old-space-size=512 to [Service] section\",\n ],\n fix: `Edit ${serviceFile} and add NODE_OPTIONS, then systemctl daemon-reload`,\n category: \"gateway\",\n })\n );\n }\n // Check Restart=always without RestartSec\n if (\n serviceContent.includes(\"Restart=always\") &&\n !serviceContent.includes(\"RestartSec\")\n ) {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: `Systemd service has Restart=always without RestartSec (${path.basename(serviceFile)})`,\n details: [\n \"Service will restart immediately on crash, potentially causing a restart storm\",\n \"Add RestartSec=5 to [Service] section to prevent rapid restarts\",\n ],\n fix: `Add RestartSec=5 to ${serviceFile} [Service] section`,\n category: \"gateway\",\n })\n );\n }\n } catch {\n // Ignore permission errors\n }\n }\n }\n\n return findings;\n}\n","/**\n * Check sandbox and execution security settings.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport JSON5 from \"json5\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\nimport { isDockerAvailable } from \"../utils.js\";\n\nexport function checkSandbox(openclawPath: string): Finding[] {\n const findings: Finding[] = [];\n const configFile = path.join(openclawPath, \"openclaw.json\");\n\n if (!fs.existsSync(configFile)) {\n return findings;\n }\n\n let config: Record<string, unknown>;\n try {\n const content = fs.readFileSync(configFile, { encoding: \"utf-8\" });\n config = JSON5.parse(content) as Record<string, unknown>;\n } catch {\n return findings;\n }\n\n const agents = (config.agents ?? {}) as Record<string, unknown>;\n const defaults = (agents.defaults ?? {}) as Record<string, unknown>;\n const sandbox = (defaults.sandbox ?? {}) as Record<string, unknown>;\n\n // Check sandbox mode\n const mode = (sandbox.mode as string) ?? \"off\";\n if (mode === \"off\") {\n findings.push(\n createFinding({\n severity: Severity.CRITICAL,\n title: \"Sandbox mode is OFF\",\n details: [\n `agents.defaults.sandbox.mode = \"${mode}\"`,\n \"The AI agent has unrestricted access to your system\",\n \"It can run any shell command, modify any file, and access the network\",\n ],\n fix: 'Set agents.defaults.sandbox.mode to \"all\" in openclaw.json',\n category: \"sandbox\",\n })\n );\n }\n\n // Check Docker availability (required for sandbox)\n const dockerAvailable = isDockerAvailable();\n if (mode !== \"off\" && !dockerAvailable) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: \"Docker not found (required for sandbox)\",\n details: [\"Sandbox mode is enabled but Docker is not installed\"],\n fix: \"Install Docker: https://docs.docker.com/get-docker/\",\n category: \"sandbox\",\n })\n );\n }\n\n // Check Docker network setting\n const dockerConfig = (sandbox.docker ?? {}) as Record<string, unknown>;\n const dockerNetwork = dockerConfig.network as string | undefined;\n if (mode !== \"off\" && dockerNetwork !== \"none\") {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: \"Sandbox container has network access\",\n details: [\n `sandbox.docker.network = \"${dockerNetwork ?? \"default\"}\"`,\n \"Sandboxed agent can make external network requests\",\n ],\n fix: 'Set sandbox.docker.network to \"none\" in openclaw.json',\n category: \"sandbox\",\n })\n );\n }\n\n // Check exec host setting\n const tools = (config.tools ?? {}) as Record<string, unknown>;\n const execConfig = (tools.exec ?? {}) as Record<string, unknown>;\n const execHost = (execConfig.host as string) ?? \"sandbox\";\n if (execHost === \"gateway\") {\n findings.push(\n createFinding({\n severity: Severity.CRITICAL,\n title: \"Tool execution runs directly on host\",\n details: [\n 'tools.exec.host = \"gateway\"',\n \"Commands bypass the sandbox and execute on your machine\",\n ],\n fix: 'Set tools.exec.host to \"sandbox\" in openclaw.json',\n category: \"sandbox\",\n })\n );\n }\n\n // Check exec security mode\n const execSecurity = execConfig.security as string | undefined;\n const validExecSecurity = [\"deny\", \"allowlist\", \"full\"];\n if (execSecurity && !validExecSecurity.includes(execSecurity)) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Invalid tools.exec.security value: \"${execSecurity}\"`,\n details: [\n `tools.exec.security = \"${execSecurity}\"`,\n `Valid values: ${validExecSecurity.join(\", \")}`,\n \"Invalid value may cause unpredictable behavior\",\n ],\n fix: 'Set tools.exec.security to \"deny\", \"allowlist\", or \"full\" in openclaw.json',\n category: \"sandbox\",\n })\n );\n } else if (execSecurity !== \"allowlist\") {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: \"Exec security not in allowlist mode\",\n details: [\n `tools.exec.security = \"${execSecurity ?? \"default\"}\"`,\n \"Allowlist mode restricts command chaining and redirections\",\n ],\n fix: 'Set tools.exec.security to \"allowlist\" in openclaw.json',\n category: \"sandbox\",\n })\n );\n }\n\n // Config validation: nativeSkills\n const commands = (config.commands ?? {}) as Record<string, unknown>;\n const nativeSkills = commands.nativeSkills;\n if (nativeSkills !== undefined && nativeSkills !== null) {\n const validNativeSkills = [false, \"auto\", \"off\"];\n if (!validNativeSkills.includes(nativeSkills as string | boolean)) {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: `Invalid commands.nativeSkills value: \"${String(nativeSkills)}\"`,\n details: [\n `commands.nativeSkills = \"${String(nativeSkills)}\"`,\n 'Valid values: false, \"auto\", \"off\"',\n \"Invalid value may cause skill execution issues\",\n ],\n fix: 'Set commands.nativeSkills to false, \"auto\", or \"off\" in openclaw.json',\n category: \"sandbox\",\n })\n );\n }\n }\n\n // Check if Docker is available at all (informational)\n if (dockerAvailable) {\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: \"Docker available for sandboxing\",\n details: [\n \"Docker is installed and can be used for sandbox isolation\",\n ],\n category: \"sandbox\",\n })\n );\n }\n\n return findings;\n}\n","/**\n * Check file permissions on sensitive OpenClaw files.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\nimport { findFilesRecursive, getRelativePath } from \"../utils.js\";\n\nfunction getPermissionOctal(filepath: string): string {\n const stats = fs.statSync(filepath);\n // eslint-disable-next-line no-bitwise\n return \"0o\" + (stats.mode & 0o777).toString(8);\n}\n\nfunction isWorldReadable(filepath: string): boolean {\n const stats = fs.statSync(filepath);\n // eslint-disable-next-line no-bitwise\n return (stats.mode & 0o004) !== 0;\n}\n\nfunction isGroupReadable(filepath: string): boolean {\n const stats = fs.statSync(filepath);\n // eslint-disable-next-line no-bitwise\n return (stats.mode & 0o040) !== 0;\n}\n\nexport function checkPermissions(openclawPath: string): Finding[] {\n const findings: Finding[] = [];\n const tooOpen: string[] = [];\n\n // Check main directory\n if (fs.existsSync(openclawPath)) {\n const perms = getPermissionOctal(openclawPath);\n if (isWorldReadable(openclawPath) || isGroupReadable(openclawPath)) {\n tooOpen.push(`${openclawPath} is ${perms} (should be 0o700)`);\n }\n }\n\n // Sensitive files to check\n const sensitiveFiles: string[] = [\n path.join(openclawPath, \"openclaw.json\"),\n path.join(openclawPath, \".env\"),\n path.join(openclawPath, \"credentials\", \"profiles.json\"),\n ];\n\n // Add auth-profiles.json files\n const agentsDir = path.join(openclawPath, \"agents\");\n if (fs.existsSync(agentsDir) && fs.statSync(agentsDir).isDirectory()) {\n const authFiles = findFilesRecursive(agentsDir, \"auth-profiles.json\", \"exact\");\n sensitiveFiles.push(...authFiles);\n }\n\n for (const filepath of sensitiveFiles) {\n if (fs.existsSync(filepath)) {\n const perms = getPermissionOctal(filepath);\n if (isWorldReadable(filepath) || isGroupReadable(filepath)) {\n const relPath = getRelativePath(filepath, openclawPath);\n tooOpen.push(`${relPath} is ${perms} (should be 0o600)`);\n }\n }\n }\n\n if (tooOpen.length > 0) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `${tooOpen.length} file(s) have overly permissive access`,\n details: tooOpen.slice(0, 10),\n fix: \"chmod 700 ~/.openclaw && chmod 600 ~/.openclaw/openclaw.json ~/.openclaw/credentials/*\",\n category: \"permissions\",\n })\n );\n }\n\n return findings;\n}\n\n","/**\n * Check OpenClaw and Node.js versions for known vulnerabilities.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\n\ninterface CVEEntry {\n id: string;\n fixedIn: string;\n severity: Severity;\n description: string;\n}\n\n/** Known CVEs by version */\nconst CVES: CVEEntry[] = [\n {\n id: \"CVE-2026-25253\",\n fixedIn: \"2026.1.29\",\n severity: Severity.CRITICAL,\n description: \"One-click RCE via malicious link (CVSS 8.8)\",\n },\n {\n id: \"CVE-2026-21636\",\n fixedIn: \"2026.2.0\",\n severity: Severity.HIGH,\n description: \"Permission model bypass (sandbox escape)\",\n },\n];\n\nconst MIN_NODE_VERSION: [number, number, number] = [22, 12, 0];\n\nfunction parseVersion(versionStr: string): [number, number, number] | null {\n const match = versionStr.match(/(\\d+)\\.(\\d+)\\.(\\d+)/);\n if (match) {\n return [\n parseInt(match[1], 10),\n parseInt(match[2], 10),\n parseInt(match[3], 10),\n ];\n }\n return null;\n}\n\nfunction compareVersions(\n a: [number, number, number],\n b: [number, number, number]\n): number {\n for (let i = 0; i < 3; i++) {\n if (a[i] < b[i]) return -1;\n if (a[i] > b[i]) return 1;\n }\n return 0;\n}\n\nfunction runCommand(cmd: string, args: string[]): string | null {\n try {\n const result = execFileSync(cmd, args, {\n encoding: \"utf-8\",\n timeout: 10000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n return result.trim();\n } catch {\n return null;\n }\n}\n\nexport interface VersionCheckResult {\n findings: Finding[];\n openclawVersion: string | null;\n nodeVersion: string | null;\n}\n\nexport function checkVersion(_openclawPath: string): VersionCheckResult {\n const findings: Finding[] = [];\n let ocVersion: string | null = null;\n let nodeVersion: string | null = null;\n\n // Try to get OpenClaw version\n const versionOutput = runCommand(\"openclaw\", [\"--version\"]);\n if (versionOutput) {\n ocVersion = versionOutput;\n const parsed = parseVersion(versionOutput);\n if (parsed) {\n let foundVulnerability = false;\n for (const cve of CVES) {\n const cveFixed = parseVersion(cve.fixedIn);\n if (cveFixed && compareVersions(parsed, cveFixed) < 0) {\n findings.push(\n createFinding({\n severity: cve.severity,\n title: `Vulnerable to ${cve.id}`,\n details: [\n `Installed: ${ocVersion}`,\n `Fixed in: ${cve.fixedIn}`,\n cve.description,\n ],\n fix: \"Update OpenClaw: bunx openclaw@latest\",\n category: \"version\",\n })\n );\n foundVulnerability = true;\n }\n }\n if (!foundVulnerability) {\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: `OpenClaw version ${ocVersion} - up to date`,\n category: \"version\",\n })\n );\n }\n }\n } else {\n // Try to find version from package.json in common locations\n const pkgPaths = [\n path.join(\n os.homedir(),\n \".bun\",\n \"install\",\n \"global\",\n \"node_modules\",\n \"openclaw\",\n \"package.json\"\n ),\n \"/usr/local/lib/node_modules/openclaw/package.json\",\n ];\n\n let found = false;\n for (const pkgPath of pkgPaths) {\n if (fs.existsSync(pkgPath)) {\n try {\n const content = fs.readFileSync(pkgPath, { encoding: \"utf-8\" });\n const pkg = JSON.parse(content) as { version?: string };\n ocVersion = pkg.version ?? \"unknown\";\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: `OpenClaw version ${ocVersion} (from package.json)`,\n category: \"version\",\n })\n );\n found = true;\n break;\n } catch {\n // Ignore parse errors\n }\n }\n }\n\n if (!found) {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: \"Could not determine OpenClaw version\",\n details: [\"openclaw command not found in PATH\"],\n fix: \"Ensure OpenClaw is installed: bunx openclaw@latest\",\n category: \"version\",\n })\n );\n }\n }\n\n // Check Node.js version\n const nodeOutput = runCommand(\"node\", [\"--version\"]);\n if (nodeOutput) {\n nodeVersion = nodeOutput.replace(/^v/, \"\");\n const parsed = parseVersion(nodeVersion);\n if (parsed && compareVersions(parsed, MIN_NODE_VERSION) < 0) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Node.js version ${nodeVersion} is below minimum (${MIN_NODE_VERSION.join(\".\")})`,\n details: [\n \"Older Node.js versions have known security vulnerabilities\",\n ],\n fix: `Update Node.js to >= ${MIN_NODE_VERSION.join(\".\")}`,\n category: \"version\",\n })\n );\n } else if (parsed) {\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: `Node.js version ${nodeVersion} - OK`,\n category: \"version\",\n })\n );\n }\n }\n\n return { findings, openclawVersion: ocVersion, nodeVersion };\n}\n","/**\n * Audit installed OpenClaw skills for malicious patterns and excessive permissions.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport yaml from \"js-yaml\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\nimport {\n C2_IP_PATTERN,\n MALICIOUS_PATTERNS,\n SUSPICIOUS_BINS,\n TYPOSQUAT_PUBLISHERS,\n} from \"../patterns.js\";\n\ninterface SkillFrontmatter {\n name?: string;\n description?: string;\n publisher?: string;\n permissions?: {\n exec?: string | string[];\n sensitive_data?: string | string[];\n filesystem?: string[];\n };\n requires?: {\n bins?: string[];\n env?: string[];\n };\n}\n\nfunction parseSkillMd(\n skillPath: string\n): { frontmatter: SkillFrontmatter; body: string } {\n const content = fs.readFileSync(skillPath, { encoding: \"utf-8\" });\n\n let frontmatter: SkillFrontmatter = {};\n let body = content;\n\n if (content.startsWith(\"---\")) {\n const parts = content.split(\"---\", 3);\n if (parts.length >= 3) {\n try {\n const parsed = yaml.load(parts[1]) as SkillFrontmatter | null;\n frontmatter = parsed ?? {};\n } catch {\n // YAML parse error, ignore\n }\n body = parts.slice(2).join(\"---\");\n }\n }\n\n return { frontmatter, body };\n}\n\nfunction checkSkillPermissions(\n name: string,\n frontmatter: SkillFrontmatter\n): Finding[] {\n const findings: Finding[] = [];\n const dangerousPerms: string[] = [];\n\n const permissions = frontmatter.permissions ?? {};\n const requires = frontmatter.requires ?? {};\n\n // Check for exec permission\n if (permissions.exec) {\n dangerousPerms.push(`exec: ${permissions.exec}`);\n }\n\n // Check for sensitive_data access\n if (permissions.sensitive_data) {\n dangerousPerms.push(`sensitive_data: ${permissions.sensitive_data}`);\n }\n\n // Check for broad filesystem write access\n const fsPerms = permissions.filesystem ?? [];\n for (const perm of fsPerms) {\n if (typeof perm === \"string\" && perm.includes(\"write:\")) {\n if (\n perm.includes(\"write:~/\") ||\n perm.includes(\"write:/\") ||\n perm.includes(\"write:..\")\n ) {\n dangerousPerms.push(`filesystem: ${perm}`);\n }\n }\n }\n\n // Check for suspicious required binaries\n const requiredBins = requires.bins ?? [];\n for (const binName of requiredBins) {\n if (SUSPICIOUS_BINS.includes(binName)) {\n dangerousPerms.push(`requires binary: ${binName}`);\n }\n }\n\n // Check for requests to access sensitive env vars\n const requiredEnv = requires.env ?? [];\n const sensitiveEnvPatterns = [\n \"KEY\",\n \"TOKEN\",\n \"SECRET\",\n \"PASSWORD\",\n \"CREDENTIAL\",\n ];\n for (const envVar of requiredEnv) {\n if (\n sensitiveEnvPatterns.some((p) => envVar.toUpperCase().includes(p))\n ) {\n dangerousPerms.push(`requires env: ${envVar}`);\n }\n }\n\n if (dangerousPerms.length > 0) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Skill '${name}' requests excessive permissions`,\n details: dangerousPerms,\n fix: `Review or remove this skill: rm -rf ~/.openclaw/workspace/skills/${name}`,\n category: \"skills\",\n })\n );\n }\n\n return findings;\n}\n\nfunction checkSkillMalicious(name: string, body: string): Finding[] {\n const findings: Finding[] = [];\n const detected: string[] = [];\n\n for (const [patternName, pattern] of MALICIOUS_PATTERNS) {\n if (pattern.test(body)) {\n detected.push(patternName);\n }\n }\n\n // Check for C2 IPs\n if (C2_IP_PATTERN.test(body)) {\n detected.push(\"Known C2 IP address (ClawHavoc campaign)\");\n }\n\n if (detected.length > 0) {\n const severity = detected.some(\n (d) => d.includes(\"C2\") || d.includes(\"reverse shell\")\n )\n ? Severity.CRITICAL\n : Severity.HIGH;\n\n findings.push(\n createFinding({\n severity,\n title: `Skill '${name}' contains malicious patterns`,\n details: detected,\n fix: `REMOVE THIS SKILL IMMEDIATELY: rm -rf ~/.openclaw/workspace/skills/${name}`,\n category: \"skills\",\n })\n );\n }\n\n return findings;\n}\n\nexport function checkSkills(openclawPath: string): Finding[] {\n const findings: Finding[] = [];\n\n // Skill directories to scan\n const skillDirs = [\n path.join(openclawPath, \"workspace\", \"skills\"),\n path.join(openclawPath, \"skills\"),\n ];\n\n let totalSkills = 0;\n let flaggedSkills = 0;\n\n for (const skillsRoot of skillDirs) {\n if (!fs.existsSync(skillsRoot) || !fs.statSync(skillsRoot).isDirectory()) {\n continue;\n }\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(skillsRoot, { withFileTypes: true });\n } catch {\n continue;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory()) {\n continue;\n }\n\n const skillMdPath = path.join(skillsRoot, entry.name, \"SKILL.md\");\n if (!fs.existsSync(skillMdPath)) {\n continue;\n }\n\n totalSkills++;\n const name = entry.name;\n\n // Check for typosquatting publisher names\n const { frontmatter, body } = parseSkillMd(skillMdPath);\n const publisher = (frontmatter.publisher ?? \"\").toLowerCase();\n\n if (TYPOSQUAT_PUBLISHERS.includes(publisher)) {\n findings.push(\n createFinding({\n severity: Severity.CRITICAL,\n title: `Skill '${name}' has typosquatted publisher: ${publisher}`,\n details: [\n \"This publisher name is known to be associated with malicious skills\",\n ],\n fix: `REMOVE IMMEDIATELY: rm -rf ${path.join(skillsRoot, entry.name)}`,\n category: \"skills\",\n })\n );\n flaggedSkills++;\n continue;\n }\n\n // Check permissions\n const permFindings = checkSkillPermissions(name, frontmatter);\n if (permFindings.length > 0) {\n flaggedSkills++;\n }\n findings.push(...permFindings);\n\n // Check for malicious content\n const maliciousFindings = checkSkillMalicious(name, body);\n if (maliciousFindings.length > 0) {\n flaggedSkills++;\n }\n findings.push(...maliciousFindings);\n }\n }\n\n if (totalSkills > 0 && flaggedSkills === 0) {\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: `${totalSkills} skill(s) scanned - no issues found`,\n category: \"skills\",\n })\n );\n } else if (totalSkills === 0) {\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: \"No skills installed\",\n category: \"skills\",\n })\n );\n }\n\n return findings;\n}\n","/**\n * Check for memory poisoning and sensitive data in workspace files.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\nimport { API_KEY_PATTERNS, MEMORY_POISONING_PATTERNS } from \"../patterns.js\";\n\nexport function checkMemory(openclawPath: string): Finding[] {\n const findings: Finding[] = [];\n\n const workspace = path.join(openclawPath, \"workspace\");\n if (!fs.existsSync(workspace) || !fs.statSync(workspace).isDirectory()) {\n return findings;\n }\n\n // Files to check for memory poisoning\n const identityFiles = [\n path.join(workspace, \"SOUL.md\"),\n path.join(workspace, \"IDENTITY.md\"),\n ];\n\n for (const filepath of identityFiles) {\n if (!fs.existsSync(filepath)) {\n continue;\n }\n\n const content = fs.readFileSync(filepath, { encoding: \"utf-8\" });\n const detected: string[] = [];\n\n for (const [patternName, pattern] of MEMORY_POISONING_PATTERNS) {\n const matches = content.match(pattern);\n if (matches) {\n const matchText = matches[0].slice(0, 80);\n detected.push(`${patternName}: ${matchText}...`);\n }\n }\n\n if (detected.length > 0) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Potential memory poisoning in ${path.basename(filepath)}`,\n details: detected,\n fix: `Review ${filepath} for injected instructions and restore from backup`,\n category: \"memory\",\n })\n );\n }\n }\n\n // Check MEMORY.md and daily logs for leaked credentials\n const memoryFiles: string[] = [path.join(workspace, \"MEMORY.md\")];\n\n const memoryDir = path.join(workspace, \"memory\");\n if (fs.existsSync(memoryDir) && fs.statSync(memoryDir).isDirectory()) {\n try {\n const entries = fs.readdirSync(memoryDir);\n for (const entry of entries) {\n if (entry.endsWith(\".md\")) {\n memoryFiles.push(path.join(memoryDir, entry));\n }\n }\n } catch {\n // Ignore permission errors\n }\n }\n\n const leakedIn: string[] = [];\n for (const filepath of memoryFiles) {\n if (!fs.existsSync(filepath)) {\n continue;\n }\n\n const content = fs.readFileSync(filepath, { encoding: \"utf-8\" });\n for (const [keyName, pattern] of API_KEY_PATTERNS) {\n if (pattern.test(content)) {\n leakedIn.push(`${path.basename(filepath)} contains ${keyName}`);\n break;\n }\n }\n }\n\n if (leakedIn.length > 0) {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: `Sensitive data found in ${leakedIn.length} memory file(s)`,\n details: leakedIn.slice(0, 5),\n fix: \"Remove credentials from memory files and rotate exposed keys\",\n category: \"memory\",\n })\n );\n }\n\n return findings;\n}\n","/**\n * Audit agent-level configurations for security issues.\n * Detects config shadows, plaintext keys in models.json, and raw key usage.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\nimport { ENV_VAR_PATTERN, PROVIDER_ENV_MAP } from \"../patterns.js\";\nimport { parseConfig, scanFileForKeys } from \"../utils.js\";\n\nexport function checkAgents(openclawPath: string): Finding[] {\n const findings: Finding[] = [];\n\n const agentsDir = path.join(openclawPath, \"agents\");\n if (!fs.existsSync(agentsDir) || !fs.statSync(agentsDir).isDirectory()) {\n return findings;\n }\n\n // Read global config model for shadow detection\n const globalConfig = parseConfig(\n path.join(openclawPath, \"openclaw.json\")\n );\n const globalModel = getGlobalModel(globalConfig);\n\n let agentCount = 0;\n let issueCount = 0;\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(agentsDir, { withFileTypes: true });\n } catch {\n return findings;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const modelsJsonPath = path.join(\n agentsDir,\n entry.name,\n \"agent\",\n \"models.json\"\n );\n if (!fs.existsSync(modelsJsonPath)) continue;\n\n agentCount++;\n const agentName = entry.name;\n\n // Check 1: Plaintext API keys in models.json\n // models.json is auto-generated by OpenClaw from openclaw.json on every gateway\n // startup, resolving env var refs like ${OPENAI_API_KEY} into actual keys.\n // If openclaw.json uses env var references, this is expected behavior (INFO).\n const keyHits = scanFileForKeys(modelsJsonPath);\n const openclawUsesEnvRefs = keyHits.length > 0\n ? checkOpenclawModelsUseEnvRefs(openclawPath)\n : false;\n if (keyHits.length > 0) {\n if (openclawUsesEnvRefs) {\n // openclaw.json correctly uses env var refs; models.json is auto-generated\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: `Agent '${agentName}': models.json contains resolved keys (auto-generated)`,\n details: [\n \"models.json contains resolved API keys, but openclaw.json uses ${ENV_VAR} references\",\n \"OpenClaw regenerates models.json from openclaw.json on every gateway startup\",\n \"This is expected behavior — no action needed\",\n ],\n category: \"agents\",\n })\n );\n } else {\n issueCount++;\n const details = keyHits.slice(0, 5).map(\n (h) => `Line ${h.lineNum}: ${h.keyName} (${h.masked})`\n );\n findings.push(\n createFinding({\n severity: Severity.CRITICAL,\n title: `Agent '${agentName}' has plaintext API keys in models.json`,\n details,\n fix: `Replace raw keys with env var refs: \"apiKey\": \"\\${${PROVIDER_ENV_MAP.anthropic}}\"`,\n category: \"agents\",\n })\n );\n }\n }\n\n // Check 2: HIGH - models.json uses raw keys instead of ${ENV_VAR} references\n // Skip this check if openclaw.json already uses env var refs (models.json is auto-generated)\n if (!openclawUsesEnvRefs) {\n try {\n const content = fs.readFileSync(modelsJsonPath, {\n encoding: \"utf-8\",\n });\n const hasEnvRefs = ENV_VAR_PATTERN.test(content);\n if (keyHits.length > 0 && !hasEnvRefs) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Agent '${agentName}' uses raw keys instead of env var references`,\n details: [\n \"models.json contains no ${ENV_VAR} references\",\n \"All API keys should use environment variable substitution\",\n ],\n fix: 'Run \"clawguard migrate-env\" to auto-migrate keys to .env',\n category: \"agents\",\n })\n );\n issueCount++;\n }\n } catch {\n // Ignore read errors\n }\n }\n\n // Check 3: MEDIUM - Config shadow detection\n if (globalModel) {\n const agentModel = getAgentModel(modelsJsonPath);\n if (agentModel && agentModel !== globalModel) {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: `Agent '${agentName}' model differs from global config`,\n details: [\n `Global model: ${globalModel}`,\n `Agent model: ${agentModel}`,\n \"This agent overrides the global model setting (config shadow)\",\n ],\n fix: \"Verify this is intentional. Remove agent-level model to use global setting.\",\n category: \"agents\",\n })\n );\n issueCount++;\n }\n }\n }\n\n if (agentCount > 0 && issueCount === 0) {\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: `${agentCount} agent config(s) scanned - no issues found`,\n category: \"agents\",\n })\n );\n }\n\n return findings;\n}\n\nfunction getGlobalModel(\n config: Record<string, unknown> | null\n): string | null {\n if (!config) return null;\n try {\n const models = config.models as Record<string, unknown> | undefined;\n if (!models) return null;\n // Look for default model in providers or top-level\n const defaultModel = models.default as string | undefined;\n if (defaultModel) return defaultModel;\n // Check providers for the first configured model\n const providers = models.providers as\n | Record<string, Record<string, unknown>>\n | undefined;\n if (providers) {\n for (const provider of Object.values(providers)) {\n if (provider.model) return String(provider.model);\n }\n }\n } catch {\n // Ignore\n }\n return null;\n}\n\n/**\n * Check if openclaw.json's models.providers section uses ${ENV_VAR} references.\n * Returns true if at least one provider uses env var substitution for its API key.\n */\nfunction checkOpenclawModelsUseEnvRefs(openclawPath: string): boolean {\n try {\n const configPath = path.join(openclawPath, \"openclaw.json\");\n const content = fs.readFileSync(configPath, { encoding: \"utf-8\" });\n const config = JSON.parse(content) as Record<string, unknown>;\n const models = config.models as Record<string, unknown> | undefined;\n if (!models) return false;\n const providers = models.providers as\n | Record<string, Record<string, unknown>>\n | undefined;\n if (!providers) return false;\n\n // Check if any provider's apiKey (or key) uses ${ENV_VAR} syntax\n for (const provider of Object.values(providers)) {\n const apiKey = String(provider.apiKey ?? provider.key ?? \"\");\n if (ENV_VAR_PATTERN.test(apiKey)) {\n return true;\n }\n }\n } catch {\n // Ignore parse/read errors\n }\n return false;\n}\n\nfunction getAgentModel(modelsJsonPath: string): string | null {\n try {\n const content = fs.readFileSync(modelsJsonPath, { encoding: \"utf-8\" });\n const data = JSON.parse(content) as Record<string, unknown>;\n // Agent models.json typically has a \"model\" or \"default\" field\n if (data.model) return String(data.model);\n if (data.default) return String(data.default);\n // Or check nested providers\n const providers = data.providers as\n | Record<string, Record<string, unknown>>\n | undefined;\n if (providers) {\n for (const provider of Object.values(providers)) {\n if (provider.model) return String(provider.model);\n }\n }\n } catch {\n // Ignore\n }\n return null;\n}\n","/**\n * Check LLM provider configurations for potential issues.\n * Catches free-tier TPM limits, rate limits, and missing web search keys.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { type Finding, Severity, createFinding } from \"../models.js\";\nimport {\n OPENCLAW_SYSTEM_PROMPT_TOKENS,\n PROVIDER_LIMITS,\n} from \"../patterns.js\";\nimport { parseConfig } from \"../utils.js\";\n\nexport function checkProviders(openclawPath: string): Finding[] {\n const findings: Finding[] = [];\n\n const config = parseConfig(path.join(openclawPath, \"openclaw.json\"));\n if (!config) return findings;\n\n const models = (config.models ?? {}) as Record<string, unknown>;\n const providers = (models.providers ?? {}) as Record<\n string,\n Record<string, unknown>\n >;\n\n const providerSummary: string[] = [];\n\n for (const [providerName, providerConfig] of Object.entries(providers)) {\n const lowerName = providerName.toLowerCase();\n providerSummary.push(\n `${providerName}: model=${String(providerConfig.model ?? \"default\")}`\n );\n\n // Check 1: HIGH - Provider free tier TPM < system prompt tokens\n const limits = PROVIDER_LIMITS[lowerName];\n if (limits && limits.tpm < OPENCLAW_SYSTEM_PROMPT_TOKENS) {\n findings.push(\n createFinding({\n severity: Severity.HIGH,\n title: `Provider '${providerName}' TPM too low for system prompt`,\n details: [\n `${limits.note}`,\n `OpenClaw system prompt requires ~${OPENCLAW_SYSTEM_PROMPT_TOKENS} tokens`,\n `Provider free tier allows only ${limits.tpm} TPM`,\n \"System prompt alone exceeds the per-minute token limit\",\n ],\n fix: `Upgrade to a paid ${providerName} plan or switch to a provider with higher limits`,\n category: \"providers\",\n })\n );\n }\n\n // Check 2: MEDIUM - Provider free tier has very low rate limits\n if (limits && limits.rpm < 10) {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: `Provider '${providerName}' has very low rate limits (${limits.rpm} RPM)`,\n details: [\n `${limits.note}`,\n \"Low RPM causes frequent rate limit errors during conversations\",\n ],\n fix: `Consider upgrading ${providerName} plan or using a different provider`,\n category: \"providers\",\n })\n );\n }\n }\n\n // Check 3: MEDIUM - Web search tool has no API key configured\n const tools = (config.tools ?? {}) as Record<string, unknown>;\n const webSearch = (tools.webSearch ?? tools.web_search ?? {}) as Record<\n string,\n unknown\n >;\n const webSearchEnabled =\n webSearch.enabled !== false && Object.keys(webSearch).length > 0;\n\n if (webSearchEnabled) {\n const apiKey = webSearch.apiKey ?? webSearch.api_key;\n if (!apiKey) {\n findings.push(\n createFinding({\n severity: Severity.MEDIUM,\n title: \"Web search tool has no API key configured\",\n details: [\n \"tools.webSearch.apiKey is not set\",\n \"Web search will fail or use a very limited fallback\",\n ],\n fix: \"Set tools.webSearch.apiKey to your Brave Search API key (get one at brave.com/search/api)\",\n category: \"providers\",\n })\n );\n }\n }\n\n // Check 4: INFO - Provider configuration summary\n if (providerSummary.length > 0) {\n findings.push(\n createFinding({\n severity: Severity.INFO,\n title: `${providerSummary.length} LLM provider(s) configured`,\n details: providerSummary,\n category: \"providers\",\n })\n );\n }\n\n return findings;\n}\n"],"mappings":"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","names":["fs","chalk","fs","path","os","JSON5","chalk","fs","path","JSON5","path","fs","JSON5","fs","path","JSON5","path","fs","JSON5","fs","path","JSON5","path","fs","JSON5","fs","path","fs","path","execFileSync","fs","path","os","execFileSync","path","os","fs","fs","path","fs","path","fs","path","path","fs","fs","path","path","fs","path","path","path","os","fs","chalk","JSON5","VERSION","chalk","fs"]}
|