clawguard-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +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/checks/gateway.ts","../src/checks/sandbox.ts","../src/checks/permissions.ts","../src/checks/version.ts","../src/checks/skills.ts","../src/checks/memory.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 runScan,\n} from \"./scanner.js\";\n\nconst VERSION = \"0.1.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(\"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.1.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\";\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};\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: Enable sandbox mode in config\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\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\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 } 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\");\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\n/** Recursively find files with a given extension */\nfunction findFilesRecursive(dir: string, ext: string): 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, ext));\n } else if (entry.isFile() && entry.name.endsWith(ext)) {\n results.push(fullPath);\n }\n }\n } catch {\n // Ignore permission errors\n }\n\n return results;\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, ENV_VAR_PATTERN } from \"../patterns.js\";\n\ninterface KeyHit {\n keyName: string;\n masked: string;\n lineNum: number;\n}\n\nfunction 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 // Create a new regex with global flag for iteration\n const globalPattern = new RegExp(pattern.source, pattern.flags + (pattern.flags.includes(\"g\") ? \"\" : \"g\"));\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\nfunction getRelativePath(filePath: string, basePath: string): string {\n const parentDir = path.dirname(basePath);\n return path.relative(parentDir, filePath);\n}\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\");\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\");\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/** Recursively find files with a given extension */\nfunction findFilesRecursive(dir: string, ext: string): 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, ext));\n } else if (entry.isFile() && entry.name.endsWith(ext)) {\n results.push(fullPath);\n }\n }\n } catch {\n // Ignore permission errors\n }\n\n return results;\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];\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/** 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 * 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\";\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 return findings;\n}\n","/**\n * Check sandbox and execution security settings.\n */\n\nimport { execFileSync } 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\";\n\nfunction isDockerAvailable(): boolean {\n try {\n execFileSync(\"which\", [\"docker\"], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n}\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 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 // 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\";\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\nfunction getRelativePath(filePath: string, basePath: string): string {\n const parentDir = path.dirname(basePath);\n return path.relative(parentDir, filePath);\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\");\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/** Recursively find files with a given exact name */\nfunction findFilesRecursive(dir: string, filename: string): 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, filename));\n } else if (entry.isFile() && entry.name === filename) {\n results.push(fullPath);\n }\n }\n } catch {\n // Ignore permission errors\n }\n\n return results;\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"],"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","fs","getRelativePath","path","findFilesRecursive","execFileSync","fs","path","execFileSync","path","fs","fs","path","fs","path","fs","path","path","fs","path","os","fs","chalk","JSON5","findFilesRecursive","VERSION","chalk","fs"]}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "clawguard-cli",
3
+ "version": "0.1.0",
4
+ "description": "Security scanner for OpenClaw AI agent installations",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "bin": {
8
+ "clawguard": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsup",
15
+ "dev": "tsup --watch",
16
+ "start": "node dist/index.js",
17
+ "typecheck": "tsc --noEmit"
18
+ },
19
+ "keywords": [
20
+ "openclaw",
21
+ "security",
22
+ "scanner",
23
+ "ai-agent",
24
+ "clawdbot",
25
+ "moltbot",
26
+ "vulnerability",
27
+ "audit"
28
+ ],
29
+ "author": "Vishal M",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/vman7250/clawguard"
34
+ },
35
+ "homepage": "https://github.com/vman7250/clawguard",
36
+ "bugs": {
37
+ "url": "https://github.com/vman7250/clawguard/issues"
38
+ },
39
+ "engines": {
40
+ "node": ">=18.0.0"
41
+ },
42
+ "dependencies": {
43
+ "chalk": "^5.3.0",
44
+ "commander": "^12.1.0",
45
+ "json5": "^2.2.3",
46
+ "js-yaml": "^4.1.0",
47
+ "zod": "^3.23.8"
48
+ },
49
+ "devDependencies": {
50
+ "@types/js-yaml": "^4.0.9",
51
+ "@types/node": "^22.10.0",
52
+ "tsup": "^8.3.0",
53
+ "typescript": "^5.7.0"
54
+ }
55
+ }