@posthog/wizard 2.0.1 → 2.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.
- package/dist/bin.js +53 -8
- package/dist/bin.js.map +1 -1
- package/dist/src/__tests__/cli.test.js +50 -3
- package/dist/src/__tests__/cli.test.js.map +1 -1
- package/dist/src/__tests__/package-json.test.d.ts +1 -0
- package/dist/src/__tests__/package-json.test.js +173 -0
- package/dist/src/__tests__/package-json.test.js.map +1 -0
- package/dist/src/frameworks/angular/angular-wizard-agent.js +1 -6
- package/dist/src/frameworks/angular/angular-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/astro/astro-wizard-agent.js +1 -4
- package/dist/src/frameworks/astro/astro-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/nextjs/nextjs-wizard-agent.js +1 -4
- package/dist/src/frameworks/nextjs/nextjs-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/nuxt/nuxt-wizard-agent.js +1 -4
- package/dist/src/frameworks/nuxt/nuxt-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/react-native/react-native-wizard-agent.js +1 -6
- package/dist/src/frameworks/react-native/react-native-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/react-router/react-router-wizard-agent.js +1 -6
- package/dist/src/frameworks/react-router/react-router-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/tanstack-router/tanstack-router-wizard-agent.js +1 -6
- package/dist/src/frameworks/tanstack-router/tanstack-router-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/tanstack-start/tanstack-start-wizard-agent.js +1 -6
- package/dist/src/frameworks/tanstack-start/tanstack-start-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/vue/vue-wizard-agent.js +1 -4
- package/dist/src/frameworks/vue/vue-wizard-agent.js.map +1 -1
- package/dist/src/lib/__tests__/agent-interface.test.js +1 -0
- package/dist/src/lib/__tests__/agent-interface.test.js.map +1 -1
- package/dist/src/lib/__tests__/yara-hooks.test.d.ts +1 -0
- package/dist/src/lib/__tests__/yara-hooks.test.js +432 -0
- package/dist/src/lib/__tests__/yara-hooks.test.js.map +1 -0
- package/dist/src/lib/__tests__/yara-scanner.test.d.ts +1 -0
- package/dist/src/lib/__tests__/yara-scanner.test.js +613 -0
- package/dist/src/lib/__tests__/yara-scanner.test.js.map +1 -0
- package/dist/src/lib/agent-interface.d.ts +4 -2
- package/dist/src/lib/agent-interface.js +40 -26
- package/dist/src/lib/agent-interface.js.map +1 -1
- package/dist/src/lib/agent-runner.js +49 -15
- package/dist/src/lib/agent-runner.js.map +1 -1
- package/dist/src/lib/commandments.js +1 -0
- package/dist/src/lib/commandments.js.map +1 -1
- package/dist/src/lib/constants.d.ts +4 -3
- package/dist/src/lib/constants.js +3 -2
- package/dist/src/lib/constants.js.map +1 -1
- package/dist/src/lib/middleware/benchmark.js +2 -6
- package/dist/src/lib/middleware/benchmark.js.map +1 -1
- package/dist/src/lib/middleware/benchmarks/json-writer.js +1 -2
- package/dist/src/lib/middleware/benchmarks/json-writer.js.map +1 -1
- package/dist/src/lib/middleware/benchmarks/summary.js +6 -10
- package/dist/src/lib/middleware/benchmarks/summary.js.map +1 -1
- package/dist/src/lib/skill-install.d.ts +10 -0
- package/dist/src/lib/skill-install.js +23 -0
- package/dist/src/lib/skill-install.js.map +1 -0
- package/dist/src/lib/version.d.ts +1 -1
- package/dist/src/lib/version.js +1 -1
- package/dist/src/lib/version.js.map +1 -1
- package/dist/src/lib/wizard-session.d.ts +13 -0
- package/dist/src/lib/wizard-session.js +3 -0
- package/dist/src/lib/wizard-session.js.map +1 -1
- package/dist/src/lib/yara-hooks.d.ts +44 -0
- package/dist/src/lib/yara-hooks.js +377 -0
- package/dist/src/lib/yara-hooks.js.map +1 -0
- package/dist/src/lib/yara-scanner.d.ts +61 -0
- package/dist/src/lib/yara-scanner.js +328 -0
- package/dist/src/lib/yara-scanner.js.map +1 -0
- package/dist/src/run.d.ts +3 -0
- package/dist/src/run.js +11 -2
- package/dist/src/run.js.map +1 -1
- package/dist/src/steps/add-mcp-server-to-clients/index.d.ts +2 -1
- package/dist/src/steps/add-mcp-server-to-clients/index.js +1 -1
- package/dist/src/steps/add-mcp-server-to-clients/index.js.map +1 -1
- package/dist/src/steps/add-or-update-environment-variables.js +9 -10
- package/dist/src/steps/add-or-update-environment-variables.js.map +1 -1
- package/dist/src/steps/upload-environment-variables/providers/vercel.js +4 -8
- package/dist/src/steps/upload-environment-variables/providers/vercel.js.map +1 -1
- package/dist/src/ui/logging-ui.d.ts +5 -0
- package/dist/src/ui/logging-ui.js +3 -0
- package/dist/src/ui/logging-ui.js.map +1 -1
- package/dist/src/ui/tui/ink-ui.d.ts +5 -0
- package/dist/src/ui/tui/ink-ui.js +3 -0
- package/dist/src/ui/tui/ink-ui.js.map +1 -1
- package/dist/src/ui/tui/primitives/Divider.d.ts +6 -0
- package/dist/src/ui/tui/primitives/Divider.js +15 -0
- package/dist/src/ui/tui/primitives/Divider.js.map +1 -0
- package/dist/src/ui/tui/primitives/index.d.ts +1 -0
- package/dist/src/ui/tui/primitives/index.js +1 -0
- package/dist/src/ui/tui/primitives/index.js.map +1 -1
- package/dist/src/ui/tui/router.d.ts +2 -1
- package/dist/src/ui/tui/router.js +1 -0
- package/dist/src/ui/tui/router.js.map +1 -1
- package/dist/src/ui/tui/screen-registry.js +2 -0
- package/dist/src/ui/tui/screen-registry.js.map +1 -1
- package/dist/src/ui/tui/screens/IntroScreen.js +18 -2
- package/dist/src/ui/tui/screens/IntroScreen.js.map +1 -1
- package/dist/src/ui/tui/screens/PortConflictScreen.d.ts +11 -0
- package/dist/src/ui/tui/screens/PortConflictScreen.js +30 -0
- package/dist/src/ui/tui/screens/PortConflictScreen.js.map +1 -0
- package/dist/src/ui/tui/store.d.ts +18 -0
- package/dist/src/ui/tui/store.js +25 -0
- package/dist/src/ui/tui/store.js.map +1 -1
- package/dist/src/ui/wizard-ui.d.ts +6 -0
- package/dist/src/ui/wizard-ui.js.map +1 -1
- package/dist/src/utils/debug.js +1 -5
- package/dist/src/utils/debug.js.map +1 -1
- package/dist/src/utils/logging.js +7 -10
- package/dist/src/utils/logging.js.map +1 -1
- package/dist/src/utils/oauth.js +44 -4
- package/dist/src/utils/oauth.js.map +1 -1
- package/dist/src/utils/package-json.d.ts +5 -0
- package/dist/src/utils/package-json.js +20 -0
- package/dist/src/utils/package-json.js.map +1 -1
- package/dist/src/utils/rules/universal.md +12 -0
- package/dist/src/utils/setup-utils.js +12 -14
- package/dist/src/utils/setup-utils.js.map +1 -1
- package/dist/src/utils/types.d.ts +9 -0
- package/dist/src/utils/types.js.map +1 -1
- package/package.json +1 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yara-hooks.js","sourceRoot":"","sources":["../../../src/lib/yara-hooks.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * YARA hook wiring for the Claude Agent SDK.\n *\n * Creates PreToolUse and PostToolUse hook callback arrays that\n * integrate the YARA scanner into the wizard's agent loop. These\n * hooks are registered in the SDK's query() options alongside the\n * existing Stop hook.\n *\n * PreToolUse hooks block dangerous commands before execution.\n * PostToolUse hooks detect violations in written code and prompt\n * injection in read content, and scan context-mill skill downloads.\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport fg from 'fast-glob';\nimport { scan, scanSkillDirectory } from './yara-scanner';\nimport type { YaraMatch, ScanResult } from './yara-scanner';\nimport { logToFile } from '../utils/debug';\nimport { analytics } from '../utils/analytics';\nimport { isSkillInstallCommand } from './skill-install';\n\n// ─── Types ───────────────────────────────────────────────────────\n// Using loose types to avoid tight coupling to SDK version.\n// The SDK hook types are: HookCallbackMatcher[], where each matcher\n// has { matcher?: string, hooks: HookCallback[], timeout?: number }\n\ntype HookInput = Record<string, unknown>;\ntype HookOutput = Record<string, unknown>;\ntype HookCallback = (\n input: HookInput,\n toolUseID: string | undefined,\n options: { signal: AbortSignal },\n) => Promise<HookOutput>;\n\nexport interface HookCallbackMatcher {\n matcher?: string;\n hooks: HookCallback[];\n timeout?: number;\n}\n\n// ─── Scan Report Accumulator ─────────────────────────────────────\n\ntype ScanAction = 'blocked' | 'reverted' | 'warned' | 'aborted';\n\ninterface ScanReportEntry {\n rule: string;\n severity: string;\n action: ScanAction;\n phase: string;\n tool: string;\n}\n\nlet scanCount = 0;\nconst scanViolations: ScanReportEntry[] = [];\n\nfunction recordScan(): void {\n scanCount++;\n}\n\nfunction recordViolation(entry: ScanReportEntry): void {\n scanViolations.push(entry);\n}\n\n/** Reset counters (for testing) */\nexport function resetScanReport(): void {\n scanCount = 0;\n scanViolations.length = 0;\n}\n\n/** Format the scan report summary. Returns null if no scans occurred */\nexport function formatScanReport(): string | null {\n if (scanCount === 0) return null;\n\n const lines: string[] = ['', '— YARA Scanner Summary —'];\n const violationCount = scanViolations.length;\n const cleanCount = scanCount - violationCount;\n\n lines.push(\n `✓ ${scanCount} tool calls scanned, ${violationCount} violation${\n violationCount !== 1 ? 's' : ''\n } detected`,\n );\n\n if (violationCount > 0) {\n lines.push('');\n for (const v of scanViolations) {\n const tag = v.action.toUpperCase();\n lines.push(\n ` [${tag}] ${v.rule} (${v.severity.toUpperCase()}) — ${v.phase}:${\n v.tool\n }`,\n );\n }\n }\n\n if (cleanCount > 0) {\n lines.push('');\n lines.push(\n `No violations: ✓ ${cleanCount} clean scan${cleanCount !== 1 ? 's' : ''}`,\n );\n }\n\n lines.push('');\n return lines.join('\\n');\n}\n\nconst YARA_REPORT_PATH = '/tmp/posthog-wizard-yara-report.json';\n\n/** Write the scan report to a JSON file. Returns the file path, or null if no scans occurred. */\nexport function writeScanReport(): string | null {\n if (scanCount === 0) return null;\n\n const report = {\n summary: {\n totalScans: scanCount,\n violations: scanViolations.length,\n clean: scanCount - scanViolations.length,\n },\n violations: scanViolations,\n };\n\n try {\n fs.writeFileSync(YARA_REPORT_PATH, JSON.stringify(report, null, 2));\n } catch (err) {\n logToFile('[YARA] Failed to write scan report:', err);\n return null;\n }\n return YARA_REPORT_PATH;\n}\n\n// ─── Hook Timeouts (ms) ─────────────────────────────────────────\n\n/** Timeout for synchronous scan hooks (PreToolUse, PostToolUse Write/Edit/Read) */\nconst HOOK_TIMEOUT_MS = 60;\n/** Timeout for skill install hook (involves filesystem I/O) */\nconst SKILL_SCAN_HOOK_TIMEOUT_MS = 120;\n\n// ─── Logging ─────────────────────────────────────────────────────\n\nfunction logYaraMatch(\n phase: string,\n tool: string,\n match: YaraMatch,\n action: ScanAction,\n): void {\n logToFile(\n `[YARA] ${phase}:${tool} [${action.toUpperCase()}] rule \"${\n match.rule.name\n }\" ` +\n `(severity: ${match.rule.severity}, category: ${match.rule.category})\\n` +\n ` Description: ${match.rule.description}\\n` +\n ` Matched text: \"${match.matchedText.substring(0, 200)}\"`,\n );\n analytics.wizardCapture('yara rule matched', {\n rule: match.rule.name,\n severity: match.rule.severity,\n category: match.rule.category,\n action,\n phase,\n tool,\n });\n}\n\n// ─── Severity helpers ────────────────────────────────────────────\n\nconst SEVERITY_RANK: Record<string, number> = {\n critical: 4,\n high: 3,\n medium: 2,\n low: 1,\n};\n\n/** Return the highest-severity match from a list of matches. */\nfunction highestSeverityMatch(matches: YaraMatch[]): YaraMatch {\n return matches.reduce((worst, m) =>\n (SEVERITY_RANK[m.rule.severity] ?? 0) >\n (SEVERITY_RANK[worst.rule.severity] ?? 0)\n ? m\n : worst,\n );\n}\n\n// ─── PreToolUse Hooks ────────────────────────────────────────────\n\n/**\n * Create PreToolUse hook matchers for YARA scanning.\n * Scans Bash commands before execution for exfiltration,\n * destructive operations, and supply chain violations.\n */\nexport function createPreToolUseYaraHooks(): HookCallbackMatcher[] {\n return [\n {\n hooks: [\n (input: HookInput): Promise<HookOutput> => {\n try {\n const toolName = input.tool_name as string;\n if (toolName !== 'Bash') return Promise.resolve({});\n\n const toolInput = input.tool_input as Record<string, unknown>;\n const command =\n typeof toolInput?.command === 'string' ? toolInput.command : '';\n\n if (!command) return Promise.resolve({});\n\n recordScan();\n const result = scan(command, 'PreToolUse', 'Bash');\n if (!result.matched) return Promise.resolve({});\n\n const match = highestSeverityMatch(result.matches);\n logYaraMatch('PreToolUse', 'Bash', match, 'blocked');\n recordViolation({\n rule: match.rule.name,\n severity: match.rule.severity,\n action: 'blocked',\n phase: 'PreToolUse',\n tool: 'Bash',\n });\n\n return Promise.resolve({\n decision: 'block',\n reason: `[YARA] ${match.rule.name}: ${match.rule.description}. Command blocked for security.`,\n });\n } catch (error) {\n logToFile('[YARA] PreToolUse hook error:', error);\n // Fail closed: block the command if scanning fails\n return Promise.resolve({\n decision: 'block',\n reason: '[YARA] Scanner error — command blocked as a precaution.',\n });\n }\n },\n ],\n timeout: HOOK_TIMEOUT_MS,\n },\n ];\n}\n\n// ─── PostToolUse Hooks ───────────────────────────────────────────\n\n/**\n * Create PostToolUse hook matchers for YARA scanning.\n *\n * Three matchers:\n * 1. Write/Edit — scan written content for PII, secrets, config violations\n * 2. Read/Grep — scan read content for prompt injection\n * 3. Bash (skill install) — scan downloaded skill files for poisoned content\n */\nexport function createPostToolUseYaraHooks(): HookCallbackMatcher[] {\n return [\n // ── Write/Edit content scanning ──\n {\n hooks: [\n (input: HookInput): Promise<HookOutput> => {\n try {\n const toolName = input.tool_name as string;\n if (toolName !== 'Write' && toolName !== 'Edit')\n return Promise.resolve({});\n\n const toolInput = input.tool_input as Record<string, unknown>;\n // For Write, scan the content being written\n // For Edit, scan the new_str (replacement text)\n const content =\n toolName === 'Write'\n ? (toolInput?.content as string) ?? ''\n : (toolInput?.new_str as string) ?? '';\n\n if (!content) return Promise.resolve({});\n\n recordScan();\n const tool = toolName;\n const result = scan(content, 'PostToolUse', tool);\n if (!result.matched) return Promise.resolve({});\n\n const match = highestSeverityMatch(result.matches);\n logYaraMatch('PostToolUse', tool, match, 'reverted');\n recordViolation({\n rule: match.rule.name,\n severity: match.rule.severity,\n action: 'reverted',\n phase: 'PostToolUse',\n tool,\n });\n\n return Promise.resolve({\n hookSpecificOutput: {\n hookEventName: 'PostToolUse',\n additionalContext:\n `[YARA VIOLATION] ${match.rule.name}: ${match.rule.description}. ` +\n `You MUST revert this change immediately. The content you just wrote violates security policy.`,\n },\n });\n } catch (error) {\n logToFile('[YARA] PostToolUse Write/Edit hook error:', error);\n // Fail closed: instruct the agent to revert if scanning fails\n return Promise.resolve({\n hookSpecificOutput: {\n hookEventName: 'PostToolUse',\n additionalContext:\n '[YARA] Scanner error — you MUST revert this change as a precaution.',\n },\n });\n }\n },\n ],\n timeout: HOOK_TIMEOUT_MS,\n },\n\n // ── Read/Grep prompt injection scanning ──\n {\n hooks: [\n (input: HookInput): Promise<HookOutput> => {\n try {\n const toolName = input.tool_name as string;\n if (toolName !== 'Read' && toolName !== 'Grep')\n return Promise.resolve({});\n\n const toolResponse = input.tool_response;\n const content =\n typeof toolResponse === 'string'\n ? toolResponse\n : JSON.stringify(toolResponse ?? '');\n\n if (!content) return Promise.resolve({});\n\n recordScan();\n const tool = toolName;\n const result = scan(content, 'PostToolUse', tool);\n if (!result.matched) return Promise.resolve({});\n\n const match = highestSeverityMatch(result.matches);\n\n if (match.rule.severity === 'critical') {\n logYaraMatch('PostToolUse', tool, match, 'aborted');\n recordViolation({\n rule: match.rule.name,\n severity: match.rule.severity,\n action: 'aborted',\n phase: 'PostToolUse',\n tool,\n });\n // Prompt injection: abort the session — context is poisoned\n return Promise.resolve({\n stopReason:\n `[YARA CRITICAL] ${match.rule.name}: Prompt injection detected in file content. ` +\n `Agent context is potentially poisoned. Session terminated for safety.`,\n });\n }\n\n logYaraMatch('PostToolUse', tool, match, 'warned');\n recordViolation({\n rule: match.rule.name,\n severity: match.rule.severity,\n action: 'warned',\n phase: 'PostToolUse',\n tool,\n });\n return Promise.resolve({\n hookSpecificOutput: {\n hookEventName: 'PostToolUse',\n additionalContext: `[YARA WARNING] ${match.rule.name}: ${match.rule.description}`,\n },\n });\n } catch (error) {\n logToFile('[YARA] PostToolUse Read/Grep hook error:', error);\n // Fail closed: terminate session if scanning fails on read content\n return Promise.resolve({\n stopReason:\n '[YARA] Scanner error while scanning read content — session terminated as a precaution.',\n });\n }\n },\n ],\n timeout: HOOK_TIMEOUT_MS,\n },\n\n // ── Context-mill skill install scanning ──\n {\n hooks: [\n async (input: HookInput): Promise<HookOutput> => {\n try {\n const toolName = input.tool_name as string;\n if (toolName !== 'Bash') return {};\n\n const toolInput = input.tool_input as Record<string, unknown>;\n const command =\n typeof toolInput?.command === 'string' ? toolInput.command : '';\n\n // Only scan after skill install commands\n if (!isSkillInstallCommand(command)) return {};\n\n // Extract skill directory from command\n const dirMatch = command.match(\n /mkdir -p (.claude\\/skills\\/[^\\s&]+)/,\n );\n if (!dirMatch) return {};\n\n const skillDir = dirMatch[1];\n const cwd = (input.cwd as string) ?? process.cwd();\n recordScan();\n const result = await scanSkillFiles(cwd, skillDir);\n\n if (!result.matched) return {};\n\n const match = highestSeverityMatch(result.matches);\n logYaraMatch(\n 'PostToolUse',\n 'Bash (skill install)',\n match,\n 'aborted',\n );\n recordViolation({\n rule: match.rule.name,\n severity: match.rule.severity,\n action: 'aborted',\n phase: 'PostToolUse',\n tool: 'Bash (skill)',\n });\n\n return {\n stopReason:\n `[YARA CRITICAL] Poisoned skill detected in ${skillDir}: ${match.rule.name}. ` +\n `The downloaded skill contains potential prompt injection. Session terminated for safety.`,\n };\n } catch (error) {\n logToFile('[YARA] PostToolUse skill install hook error:', error);\n // Fail closed: terminate if skill scanning fails\n return {\n stopReason:\n '[YARA] Scanner error while scanning skill files — session terminated as a precaution.',\n };\n }\n },\n ],\n timeout: SKILL_SCAN_HOOK_TIMEOUT_MS,\n },\n ];\n}\n\n// ─── Skill File Scanner ──────────────────────────────────────────\n\n/**\n * Read and scan all text files in a skill directory for prompt injection.\n */\nasync function scanSkillFiles(\n cwd: string,\n skillDir: string,\n): Promise<ScanResult> {\n const absoluteDir = path.resolve(cwd, skillDir);\n\n if (!fs.existsSync(absoluteDir)) {\n logToFile(`[YARA] Skill directory does not exist: ${absoluteDir}`);\n return { matched: false };\n }\n\n const files = await fg('**/*.{md,txt,yaml,yml,json,js,ts,py,rb,sh}', {\n cwd: absoluteDir,\n absolute: true,\n });\n\n const fileContents: Array<{ path: string; content: string }> = [];\n for (const filePath of files) {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n fileContents.push({ path: filePath, content });\n } catch (err) {\n logToFile(`[YARA] Could not read skill file ${filePath}:`, err);\n }\n }\n\n if (fileContents.length === 0) {\n logToFile(`[YARA] No text files found in skill directory: ${absoluteDir}`);\n return { matched: false };\n }\n\n logToFile(\n `[YARA] Scanning ${fileContents.length} files in skill directory: ${skillDir}`,\n );\n return scanSkillDirectory(fileContents);\n}\n"]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* YARA content scanner for the PostHog wizard.
|
|
3
|
+
*
|
|
4
|
+
* This file is the single source of truth for all wizard YARA rules.
|
|
5
|
+
*
|
|
6
|
+
* Scans tool inputs (pre-execution) and outputs (post-execution) for
|
|
7
|
+
* security violations including PII leakage, hardcoded secrets,
|
|
8
|
+
* prompt injection, and secret exfiltration.
|
|
9
|
+
*
|
|
10
|
+
* We use YARA-style regex rules rather than the real YARA C library to
|
|
11
|
+
* avoid native binary dependencies in an npx-distributed npm package.
|
|
12
|
+
*
|
|
13
|
+
* This is Layer 2 (L2) in the wizard's defense-in-depth model,
|
|
14
|
+
* complementing the prompt-based commandments (L0) and the
|
|
15
|
+
* canUseTool() allowlist (L1).
|
|
16
|
+
*/
|
|
17
|
+
export type YaraSeverity = 'critical' | 'high' | 'medium' | 'low';
|
|
18
|
+
export type YaraCategory = 'posthog_pii' | 'posthog_hardcoded_key' | 'posthog_autocapture' | 'posthog_config' | 'prompt_injection' | 'exfiltration' | 'filesystem_safety' | 'supply_chain';
|
|
19
|
+
export type HookPhase = 'PreToolUse' | 'PostToolUse';
|
|
20
|
+
export type ToolTarget = 'Bash' | 'Write' | 'Edit' | 'Read' | 'Grep';
|
|
21
|
+
export interface YaraRule {
|
|
22
|
+
/** Rule name matching the .yar file (e.g. 'pii_in_capture_call') */
|
|
23
|
+
name: string;
|
|
24
|
+
description: string;
|
|
25
|
+
severity: YaraSeverity;
|
|
26
|
+
category: YaraCategory;
|
|
27
|
+
/** Which hook+tool combinations this rule applies to */
|
|
28
|
+
appliesTo: Array<{
|
|
29
|
+
phase: HookPhase;
|
|
30
|
+
tool: ToolTarget;
|
|
31
|
+
}>;
|
|
32
|
+
/** Compiled regex patterns — any match triggers the rule */
|
|
33
|
+
patterns: RegExp[];
|
|
34
|
+
}
|
|
35
|
+
export interface YaraMatch {
|
|
36
|
+
rule: YaraRule;
|
|
37
|
+
/** The matched substring */
|
|
38
|
+
matchedText: string;
|
|
39
|
+
/** Byte offset in the scanned content */
|
|
40
|
+
offset: number;
|
|
41
|
+
}
|
|
42
|
+
export type ScanResult = {
|
|
43
|
+
matched: false;
|
|
44
|
+
} | {
|
|
45
|
+
matched: true;
|
|
46
|
+
matches: YaraMatch[];
|
|
47
|
+
};
|
|
48
|
+
export declare const RULES: YaraRule[];
|
|
49
|
+
/**
|
|
50
|
+
* Scan content against rules applicable to a given hook phase and tool.
|
|
51
|
+
* Returns all matching rules (one match per rule, first pattern wins).
|
|
52
|
+
*/
|
|
53
|
+
export declare function scan(content: string, phase: HookPhase, tool: ToolTarget): ScanResult;
|
|
54
|
+
/**
|
|
55
|
+
* Scan all files in a skill directory for prompt injection.
|
|
56
|
+
* Used for context-mill scanning after skill installation.
|
|
57
|
+
*/
|
|
58
|
+
export declare function scanSkillDirectory(files: Array<{
|
|
59
|
+
path: string;
|
|
60
|
+
content: string;
|
|
61
|
+
}>): ScanResult;
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* YARA content scanner for the PostHog wizard.
|
|
4
|
+
*
|
|
5
|
+
* This file is the single source of truth for all wizard YARA rules.
|
|
6
|
+
*
|
|
7
|
+
* Scans tool inputs (pre-execution) and outputs (post-execution) for
|
|
8
|
+
* security violations including PII leakage, hardcoded secrets,
|
|
9
|
+
* prompt injection, and secret exfiltration.
|
|
10
|
+
*
|
|
11
|
+
* We use YARA-style regex rules rather than the real YARA C library to
|
|
12
|
+
* avoid native binary dependencies in an npx-distributed npm package.
|
|
13
|
+
*
|
|
14
|
+
* This is Layer 2 (L2) in the wizard's defense-in-depth model,
|
|
15
|
+
* complementing the prompt-based commandments (L0) and the
|
|
16
|
+
* canUseTool() allowlist (L1).
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.RULES = void 0;
|
|
20
|
+
exports.scan = scan;
|
|
21
|
+
exports.scanSkillDirectory = scanSkillDirectory;
|
|
22
|
+
// ─── Rule Definitions ────────────────────────────────────────────
|
|
23
|
+
//
|
|
24
|
+
// Patterns are compiled once at module load time for performance.
|
|
25
|
+
// Design spec: policies/yara/RULES.md
|
|
26
|
+
const POST_WRITE_EDIT = [
|
|
27
|
+
{ phase: 'PostToolUse', tool: 'Write' },
|
|
28
|
+
{ phase: 'PostToolUse', tool: 'Edit' },
|
|
29
|
+
];
|
|
30
|
+
const POST_READ_GREP = [
|
|
31
|
+
{ phase: 'PostToolUse', tool: 'Read' },
|
|
32
|
+
{ phase: 'PostToolUse', tool: 'Grep' },
|
|
33
|
+
];
|
|
34
|
+
const PRE_BASH = [
|
|
35
|
+
{ phase: 'PreToolUse', tool: 'Bash' },
|
|
36
|
+
];
|
|
37
|
+
// ── §1 PostHog API Violations ────────────────────────────────────
|
|
38
|
+
const pii_in_capture_call = {
|
|
39
|
+
name: 'pii_in_capture_call',
|
|
40
|
+
description: "Detects PII fields passed to posthog.capture() — violates 'NEVER send PII in capture()' commandment",
|
|
41
|
+
severity: 'high',
|
|
42
|
+
category: 'posthog_pii',
|
|
43
|
+
appliesTo: POST_WRITE_EDIT,
|
|
44
|
+
patterns: [
|
|
45
|
+
// Direct PII field names in capture properties
|
|
46
|
+
/\.capture\s*\([^)]{0,200}email/i,
|
|
47
|
+
/\.capture\s*\([^)]{0,200}phone/i,
|
|
48
|
+
/\.capture\s*\([^)]{0,200}full[_\s]?name/i,
|
|
49
|
+
/\.capture\s*\([^)]{0,200}first[_\s]?name/i,
|
|
50
|
+
/\.capture\s*\([^)]{0,200}last[_\s]?name/i,
|
|
51
|
+
/\.capture\s*\([^)]{0,200}(street|mailing|home|billing)[_\s]?address/i,
|
|
52
|
+
/\.capture\s*\([^)]{0,200}(ssn|social[_\s]?security)/i,
|
|
53
|
+
/\.capture\s*\([^)]{0,200}(date[_\s]?of[_\s]?birth|dob|birthday)/i,
|
|
54
|
+
/\.capture\s*\([^)]{0,200}\$ip/,
|
|
55
|
+
// identify() allows email/phone/name (standard PostHog user properties),
|
|
56
|
+
// but highly sensitive PII is still blocked in identify().
|
|
57
|
+
/\.identify\s*\([^)]{0,200}(ssn|social[_\s]?security)/i,
|
|
58
|
+
/\.identify\s*\([^)]{0,200}(card[_\s]?number|cvv|credit[_\s]?card)/i,
|
|
59
|
+
/\.identify\s*\([^)]{0,200}(date[_\s]?of[_\s]?birth|dob|birthday)/i,
|
|
60
|
+
/\.identify\s*\([^)]{0,200}(street|mailing|home|billing)[_\s]?address/i,
|
|
61
|
+
// PII in $set properties via capture (bound to same object)
|
|
62
|
+
/\$set[^}]{0,200}email/i,
|
|
63
|
+
/\$set[^}]{0,200}phone/i,
|
|
64
|
+
],
|
|
65
|
+
};
|
|
66
|
+
const hardcoded_posthog_key = {
|
|
67
|
+
name: 'hardcoded_posthog_key',
|
|
68
|
+
description: "Detects hardcoded PostHog API keys in source — violates 'use environment variables' commandment",
|
|
69
|
+
severity: 'high',
|
|
70
|
+
category: 'posthog_hardcoded_key',
|
|
71
|
+
appliesTo: POST_WRITE_EDIT,
|
|
72
|
+
patterns: [
|
|
73
|
+
// PostHog project API key (phc_ prefix, 20+ alphanumeric chars)
|
|
74
|
+
/phc_[a-zA-Z0-9]{20,}/,
|
|
75
|
+
// PostHog personal API key (phx_ prefix)
|
|
76
|
+
/phx_[a-zA-Z0-9]{20,}/,
|
|
77
|
+
// Hardcoded key assignment patterns
|
|
78
|
+
/apiKey\s*[:=]\s*['"][a-zA-Z0-9_]{20,}['"]/,
|
|
79
|
+
/api_key\s*[:=]\s*['"][a-zA-Z0-9_]{20,}['"]/,
|
|
80
|
+
/POSTHOG_KEY\s*[:=]\s*['"][a-zA-Z0-9_]{20,}['"]/,
|
|
81
|
+
],
|
|
82
|
+
};
|
|
83
|
+
const autocapture_disabled = {
|
|
84
|
+
name: 'autocapture_disabled',
|
|
85
|
+
description: "Detects agent disabling autocapture — violates 'don't disable autocapture' commandment",
|
|
86
|
+
severity: 'medium',
|
|
87
|
+
category: 'posthog_autocapture',
|
|
88
|
+
appliesTo: POST_WRITE_EDIT,
|
|
89
|
+
patterns: [
|
|
90
|
+
/autocapture\s*:\s*false/,
|
|
91
|
+
/autocapture\s*:\s*'false'/,
|
|
92
|
+
/autocapture\s*:\s*"false"/,
|
|
93
|
+
/autocapture\s*=\s*False/,
|
|
94
|
+
/disable_autocapture\s*[:=]\s*(true|True|1)/,
|
|
95
|
+
],
|
|
96
|
+
};
|
|
97
|
+
// ── §1b Additional PostHog config rules ──────────────────────────
|
|
98
|
+
const hardcoded_posthog_host = {
|
|
99
|
+
name: 'hardcoded_posthog_host',
|
|
100
|
+
description: 'Detects hardcoded PostHog host URLs in source — should use environment variables',
|
|
101
|
+
severity: 'high',
|
|
102
|
+
category: 'posthog_hardcoded_key',
|
|
103
|
+
appliesTo: POST_WRITE_EDIT,
|
|
104
|
+
patterns: [/['"]https:\/\/(us|eu)\.i\.posthog\.com['"]/],
|
|
105
|
+
};
|
|
106
|
+
const session_recording_disabled = {
|
|
107
|
+
name: 'session_recording_disabled',
|
|
108
|
+
description: 'Detects agent disabling session recording',
|
|
109
|
+
severity: 'medium',
|
|
110
|
+
category: 'posthog_config',
|
|
111
|
+
appliesTo: POST_WRITE_EDIT,
|
|
112
|
+
patterns: [
|
|
113
|
+
/disable_session_recording\s*:\s*true/i,
|
|
114
|
+
/disable_session_recording\s*=\s*True/,
|
|
115
|
+
],
|
|
116
|
+
};
|
|
117
|
+
const opt_out_capturing = {
|
|
118
|
+
name: 'opt_out_capturing',
|
|
119
|
+
description: 'Detects agent opting out of PostHog capturing entirely',
|
|
120
|
+
severity: 'medium',
|
|
121
|
+
category: 'posthog_config',
|
|
122
|
+
appliesTo: POST_WRITE_EDIT,
|
|
123
|
+
patterns: [
|
|
124
|
+
// Match opt_out_capturing as a config property (in init options), not as a method call.
|
|
125
|
+
// posthog.opt_out_capturing() is a legitimate GDPR-required API.
|
|
126
|
+
/opt_out_capturing\s*[:=]\s*(true|True|1)/i,
|
|
127
|
+
/opted_out\s*[:=]\s*(true|True|1)/i,
|
|
128
|
+
],
|
|
129
|
+
};
|
|
130
|
+
// ── §2 Prompt Injection ──────────────────────────────────────────
|
|
131
|
+
const prompt_injection_wizard_override = {
|
|
132
|
+
name: 'prompt_injection_wizard_override',
|
|
133
|
+
description: 'Detects classic prompt injection attempting to override agent instructions',
|
|
134
|
+
severity: 'critical',
|
|
135
|
+
category: 'prompt_injection',
|
|
136
|
+
appliesTo: POST_READ_GREP,
|
|
137
|
+
patterns: [
|
|
138
|
+
// Direct instruction override — classic injection patterns
|
|
139
|
+
/ignore previous instructions/i,
|
|
140
|
+
/disregard all/i,
|
|
141
|
+
/forget your instructions/i,
|
|
142
|
+
/override your rules/i,
|
|
143
|
+
// Role manipulation
|
|
144
|
+
/act as a different/i,
|
|
145
|
+
/new instructions:/i,
|
|
146
|
+
],
|
|
147
|
+
};
|
|
148
|
+
const prompt_injection_wizard_specific = {
|
|
149
|
+
name: 'prompt_injection_wizard_specific',
|
|
150
|
+
description: 'Detects wizard-specific manipulation or tool abuse attempts in project files',
|
|
151
|
+
severity: 'medium',
|
|
152
|
+
category: 'prompt_injection',
|
|
153
|
+
appliesTo: POST_READ_GREP,
|
|
154
|
+
patterns: [
|
|
155
|
+
// Wizard-specific manipulation
|
|
156
|
+
/skip posthog/i,
|
|
157
|
+
/do not install posthog/i,
|
|
158
|
+
/remove posthog/i,
|
|
159
|
+
/uninstall posthog/i,
|
|
160
|
+
/delete the posthog/i,
|
|
161
|
+
// Tool abuse via file content
|
|
162
|
+
/run the following command/i,
|
|
163
|
+
/execute this shell command/i,
|
|
164
|
+
// Role hijacking — require "you are now a" to avoid false positives
|
|
165
|
+
// on legitimate phrases like "you are now ready to..."
|
|
166
|
+
/you are now a\s/i,
|
|
167
|
+
],
|
|
168
|
+
};
|
|
169
|
+
const prompt_injection_base64 = {
|
|
170
|
+
name: 'prompt_injection_base64',
|
|
171
|
+
description: 'Detects suspicious base64-encoded blocks in file content that may contain obfuscated prompt injection',
|
|
172
|
+
severity: 'critical',
|
|
173
|
+
category: 'prompt_injection',
|
|
174
|
+
appliesTo: POST_READ_GREP,
|
|
175
|
+
patterns: [
|
|
176
|
+
// Long base64 strings (100+ chars) in comments or string literals
|
|
177
|
+
// that aren't typical data URIs or legitimate base64 content
|
|
178
|
+
/(?:\/\/|#|\/\*)\s*[A-Za-z0-9+/]{100,}={0,2}/,
|
|
179
|
+
],
|
|
180
|
+
};
|
|
181
|
+
// ── §3 Secret Exfiltration ───────────────────────────────────────
|
|
182
|
+
const secret_exfiltration_via_command = {
|
|
183
|
+
name: 'secret_exfiltration_via_command',
|
|
184
|
+
description: 'Detects shell commands attempting to exfiltrate secrets or credentials',
|
|
185
|
+
severity: 'critical',
|
|
186
|
+
category: 'exfiltration',
|
|
187
|
+
appliesTo: PRE_BASH,
|
|
188
|
+
patterns: [
|
|
189
|
+
// curl/wget with environment variable secrets
|
|
190
|
+
/curl\s+.*\$\{?[A-Z_]*(KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL)/i,
|
|
191
|
+
/wget\s+.*\$\{?[A-Z_]*(KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL)/i,
|
|
192
|
+
// Piping sensitive content to network tools
|
|
193
|
+
/(\$\{?[A-Z_]*(KEY|TOKEN|SECRET|PASSWORD)|\.env|credentials)\S*.*\|\s*curl/i,
|
|
194
|
+
/(\$\{?[A-Z_]*(KEY|TOKEN|SECRET|PASSWORD)|\.env|credentials)\S*.*\|\s*wget/i,
|
|
195
|
+
/\|\s*nc\s/,
|
|
196
|
+
/\|\s*netcat\s/,
|
|
197
|
+
// Base64 encoding piped to network
|
|
198
|
+
/base64.*\|\s*(curl|wget|nc\s)/i,
|
|
199
|
+
// Reading .env and sending
|
|
200
|
+
/cat\s+.*\.env.*\|\s*(curl|wget)/,
|
|
201
|
+
// PostHog key exfiltration specifically
|
|
202
|
+
/curl.*phc_[a-zA-Z0-9]/,
|
|
203
|
+
/wget.*phc_[a-zA-Z0-9]/,
|
|
204
|
+
],
|
|
205
|
+
};
|
|
206
|
+
// ── §4 Filesystem Safety ─────────────────────────────────────────
|
|
207
|
+
const destructive_rm = {
|
|
208
|
+
name: 'destructive_rm',
|
|
209
|
+
description: 'Detects rm -rf or rm -r commands that could mass-delete files',
|
|
210
|
+
severity: 'critical',
|
|
211
|
+
category: 'filesystem_safety',
|
|
212
|
+
appliesTo: PRE_BASH,
|
|
213
|
+
patterns: [
|
|
214
|
+
// Combined flags: rm -rf, rm -fr, rm -rfi, etc.
|
|
215
|
+
/\brm\s+(-[a-zA-Z]*r[a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*r)\b/,
|
|
216
|
+
// Separated flags: rm -r -f, rm -f -r (with optional other flags)
|
|
217
|
+
/\brm\s+(-[a-zA-Z]*\s+)*-[a-zA-Z]*r[a-zA-Z]*\s+(-[a-zA-Z]*\s+)*-[a-zA-Z]*f\b/,
|
|
218
|
+
/\brm\s+(-[a-zA-Z]*\s+)*-[a-zA-Z]*f[a-zA-Z]*\s+(-[a-zA-Z]*\s+)*-[a-zA-Z]*r\b/,
|
|
219
|
+
],
|
|
220
|
+
};
|
|
221
|
+
const git_force_push = {
|
|
222
|
+
name: 'git_force_push',
|
|
223
|
+
description: 'Detects git push --force which can overwrite remote history',
|
|
224
|
+
severity: 'critical',
|
|
225
|
+
category: 'filesystem_safety',
|
|
226
|
+
appliesTo: PRE_BASH,
|
|
227
|
+
patterns: [/git\s+push\s+.*--force/, /git\s+push\s+.*-f\b/],
|
|
228
|
+
};
|
|
229
|
+
const git_reset_hard = {
|
|
230
|
+
name: 'git_reset_hard',
|
|
231
|
+
description: 'Detects git reset --hard which discards all uncommitted changes',
|
|
232
|
+
severity: 'critical',
|
|
233
|
+
category: 'filesystem_safety',
|
|
234
|
+
appliesTo: PRE_BASH,
|
|
235
|
+
patterns: [/git\s+reset\s+--hard/],
|
|
236
|
+
};
|
|
237
|
+
// ── §5 Supply Chain ──────────────────────────────────────────────
|
|
238
|
+
const wrong_posthog_package = {
|
|
239
|
+
name: 'wrong_posthog_package',
|
|
240
|
+
description: 'Detects installing the wrong PostHog npm package — should be posthog-js or posthog-node',
|
|
241
|
+
severity: 'high',
|
|
242
|
+
category: 'supply_chain',
|
|
243
|
+
appliesTo: PRE_BASH,
|
|
244
|
+
patterns: [
|
|
245
|
+
// Match "npm install posthog" but not "posthog-js", "posthog-node", etc.
|
|
246
|
+
/npm\s+install\s+(?:--save\s+|--save-dev\s+|-[SD]\s+)*posthog(?!\s*-)/,
|
|
247
|
+
/pnpm\s+(?:add|install)\s+(?:--save\s+|--save-dev\s+|-[SD]\s+)*posthog(?!\s*-)/,
|
|
248
|
+
/yarn\s+add\s+(?:--dev\s+|-D\s+)*posthog(?!\s*-)/,
|
|
249
|
+
/bun\s+(?:add|install)\s+(?:--dev\s+|-[dD]\s+)*posthog(?!\s*-)/,
|
|
250
|
+
],
|
|
251
|
+
};
|
|
252
|
+
const npm_install_global = {
|
|
253
|
+
name: 'npm_install_global',
|
|
254
|
+
description: 'Detects global npm installs — should never install packages globally',
|
|
255
|
+
severity: 'high',
|
|
256
|
+
category: 'supply_chain',
|
|
257
|
+
appliesTo: PRE_BASH,
|
|
258
|
+
patterns: [/npm\s+install\s+-g\b/, /npm\s+install\s+--global\b/],
|
|
259
|
+
};
|
|
260
|
+
// ─── Rule Registry ───────────────────────────────────────────────
|
|
261
|
+
exports.RULES = [
|
|
262
|
+
// §1 PostHog API violations
|
|
263
|
+
pii_in_capture_call,
|
|
264
|
+
hardcoded_posthog_key,
|
|
265
|
+
autocapture_disabled,
|
|
266
|
+
hardcoded_posthog_host,
|
|
267
|
+
session_recording_disabled,
|
|
268
|
+
opt_out_capturing,
|
|
269
|
+
// §2 Prompt injection
|
|
270
|
+
prompt_injection_wizard_override,
|
|
271
|
+
prompt_injection_wizard_specific,
|
|
272
|
+
prompt_injection_base64,
|
|
273
|
+
// §3 Secret exfiltration
|
|
274
|
+
secret_exfiltration_via_command,
|
|
275
|
+
// §4 Filesystem safety
|
|
276
|
+
destructive_rm,
|
|
277
|
+
git_force_push,
|
|
278
|
+
git_reset_hard,
|
|
279
|
+
// §5 Supply chain
|
|
280
|
+
wrong_posthog_package,
|
|
281
|
+
npm_install_global,
|
|
282
|
+
];
|
|
283
|
+
// ─── Scan Engine ─────────────────────────────────────────────────
|
|
284
|
+
/** Maximum content length to scan (100 KB). Inputs beyond this are truncated. */
|
|
285
|
+
const MAX_SCAN_LENGTH = 100_000;
|
|
286
|
+
/**
|
|
287
|
+
* Scan content against rules applicable to a given hook phase and tool.
|
|
288
|
+
* Returns all matching rules (one match per rule, first pattern wins).
|
|
289
|
+
*/
|
|
290
|
+
function scan(content, phase, tool) {
|
|
291
|
+
// Cap input length to prevent pathological regex performance
|
|
292
|
+
const scanContent = content.length > MAX_SCAN_LENGTH
|
|
293
|
+
? content.slice(0, MAX_SCAN_LENGTH)
|
|
294
|
+
: content;
|
|
295
|
+
const applicableRules = exports.RULES.filter((r) => r.appliesTo.some((a) => a.phase === phase && a.tool === tool));
|
|
296
|
+
const matches = [];
|
|
297
|
+
for (const rule of applicableRules) {
|
|
298
|
+
for (const pattern of rule.patterns) {
|
|
299
|
+
const match = pattern.exec(scanContent);
|
|
300
|
+
if (match) {
|
|
301
|
+
matches.push({
|
|
302
|
+
rule,
|
|
303
|
+
matchedText: match[0],
|
|
304
|
+
offset: match.index,
|
|
305
|
+
});
|
|
306
|
+
break; // One match per rule is sufficient
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return matches.length > 0 ? { matched: true, matches } : { matched: false };
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Scan all files in a skill directory for prompt injection.
|
|
314
|
+
* Used for context-mill scanning after skill installation.
|
|
315
|
+
*/
|
|
316
|
+
function scanSkillDirectory(files) {
|
|
317
|
+
const allMatches = [];
|
|
318
|
+
for (const file of files) {
|
|
319
|
+
const result = scan(file.content, 'PostToolUse', 'Read');
|
|
320
|
+
if (result.matched) {
|
|
321
|
+
allMatches.push(...result.matches);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return allMatches.length > 0
|
|
325
|
+
? { matched: true, matches: allMatches }
|
|
326
|
+
: { matched: false };
|
|
327
|
+
}
|
|
328
|
+
//# sourceMappingURL=yara-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yara-scanner.js","sourceRoot":"","sources":["../../../src/lib/yara-scanner.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * YARA content scanner for the PostHog wizard.\n *\n * This file is the single source of truth for all wizard YARA rules.\n *\n * Scans tool inputs (pre-execution) and outputs (post-execution) for\n * security violations including PII leakage, hardcoded secrets,\n * prompt injection, and secret exfiltration.\n *\n * We use YARA-style regex rules rather than the real YARA C library to\n * avoid native binary dependencies in an npx-distributed npm package.\n *\n * This is Layer 2 (L2) in the wizard's defense-in-depth model,\n * complementing the prompt-based commandments (L0) and the\n * canUseTool() allowlist (L1).\n */\n\n// ─── Types ───────────────────────────────────────────────────────\n\nexport type YaraSeverity = 'critical' | 'high' | 'medium' | 'low';\n\nexport type YaraCategory =\n | 'posthog_pii'\n | 'posthog_hardcoded_key'\n | 'posthog_autocapture'\n | 'posthog_config'\n | 'prompt_injection'\n | 'exfiltration'\n | 'filesystem_safety'\n | 'supply_chain';\n\nexport type HookPhase = 'PreToolUse' | 'PostToolUse';\nexport type ToolTarget = 'Bash' | 'Write' | 'Edit' | 'Read' | 'Grep';\n\nexport interface YaraRule {\n /** Rule name matching the .yar file (e.g. 'pii_in_capture_call') */\n name: string;\n description: string;\n severity: YaraSeverity;\n category: YaraCategory;\n /** Which hook+tool combinations this rule applies to */\n appliesTo: Array<{ phase: HookPhase; tool: ToolTarget }>;\n /** Compiled regex patterns — any match triggers the rule */\n patterns: RegExp[];\n}\n\nexport interface YaraMatch {\n rule: YaraRule;\n /** The matched substring */\n matchedText: string;\n /** Byte offset in the scanned content */\n offset: number;\n}\n\nexport type ScanResult =\n | { matched: false }\n | { matched: true; matches: YaraMatch[] };\n\n// ─── Rule Definitions ────────────────────────────────────────────\n//\n// Patterns are compiled once at module load time for performance.\n// Design spec: policies/yara/RULES.md\n\nconst POST_WRITE_EDIT: Array<{ phase: HookPhase; tool: ToolTarget }> = [\n { phase: 'PostToolUse', tool: 'Write' },\n { phase: 'PostToolUse', tool: 'Edit' },\n];\n\nconst POST_READ_GREP: Array<{ phase: HookPhase; tool: ToolTarget }> = [\n { phase: 'PostToolUse', tool: 'Read' },\n { phase: 'PostToolUse', tool: 'Grep' },\n];\n\nconst PRE_BASH: Array<{ phase: HookPhase; tool: ToolTarget }> = [\n { phase: 'PreToolUse', tool: 'Bash' },\n];\n\n// ── §1 PostHog API Violations ────────────────────────────────────\n\nconst pii_in_capture_call: YaraRule = {\n name: 'pii_in_capture_call',\n description:\n \"Detects PII fields passed to posthog.capture() — violates 'NEVER send PII in capture()' commandment\",\n severity: 'high',\n category: 'posthog_pii',\n appliesTo: POST_WRITE_EDIT,\n patterns: [\n // Direct PII field names in capture properties\n /\\.capture\\s*\\([^)]{0,200}email/i,\n /\\.capture\\s*\\([^)]{0,200}phone/i,\n /\\.capture\\s*\\([^)]{0,200}full[_\\s]?name/i,\n /\\.capture\\s*\\([^)]{0,200}first[_\\s]?name/i,\n /\\.capture\\s*\\([^)]{0,200}last[_\\s]?name/i,\n /\\.capture\\s*\\([^)]{0,200}(street|mailing|home|billing)[_\\s]?address/i,\n /\\.capture\\s*\\([^)]{0,200}(ssn|social[_\\s]?security)/i,\n /\\.capture\\s*\\([^)]{0,200}(date[_\\s]?of[_\\s]?birth|dob|birthday)/i,\n /\\.capture\\s*\\([^)]{0,200}\\$ip/,\n // identify() allows email/phone/name (standard PostHog user properties),\n // but highly sensitive PII is still blocked in identify().\n /\\.identify\\s*\\([^)]{0,200}(ssn|social[_\\s]?security)/i,\n /\\.identify\\s*\\([^)]{0,200}(card[_\\s]?number|cvv|credit[_\\s]?card)/i,\n /\\.identify\\s*\\([^)]{0,200}(date[_\\s]?of[_\\s]?birth|dob|birthday)/i,\n /\\.identify\\s*\\([^)]{0,200}(street|mailing|home|billing)[_\\s]?address/i,\n // PII in $set properties via capture (bound to same object)\n /\\$set[^}]{0,200}email/i,\n /\\$set[^}]{0,200}phone/i,\n ],\n};\n\nconst hardcoded_posthog_key: YaraRule = {\n name: 'hardcoded_posthog_key',\n description:\n \"Detects hardcoded PostHog API keys in source — violates 'use environment variables' commandment\",\n severity: 'high',\n category: 'posthog_hardcoded_key',\n appliesTo: POST_WRITE_EDIT,\n patterns: [\n // PostHog project API key (phc_ prefix, 20+ alphanumeric chars)\n /phc_[a-zA-Z0-9]{20,}/,\n // PostHog personal API key (phx_ prefix)\n /phx_[a-zA-Z0-9]{20,}/,\n // Hardcoded key assignment patterns\n /apiKey\\s*[:=]\\s*['\"][a-zA-Z0-9_]{20,}['\"]/,\n /api_key\\s*[:=]\\s*['\"][a-zA-Z0-9_]{20,}['\"]/,\n /POSTHOG_KEY\\s*[:=]\\s*['\"][a-zA-Z0-9_]{20,}['\"]/,\n ],\n};\n\nconst autocapture_disabled: YaraRule = {\n name: 'autocapture_disabled',\n description:\n \"Detects agent disabling autocapture — violates 'don't disable autocapture' commandment\",\n severity: 'medium',\n category: 'posthog_autocapture',\n appliesTo: POST_WRITE_EDIT,\n patterns: [\n /autocapture\\s*:\\s*false/,\n /autocapture\\s*:\\s*'false'/,\n /autocapture\\s*:\\s*\"false\"/,\n /autocapture\\s*=\\s*False/,\n /disable_autocapture\\s*[:=]\\s*(true|True|1)/,\n ],\n};\n\n// ── §1b Additional PostHog config rules ──────────────────────────\n\nconst hardcoded_posthog_host: YaraRule = {\n name: 'hardcoded_posthog_host',\n description:\n 'Detects hardcoded PostHog host URLs in source — should use environment variables',\n severity: 'high',\n category: 'posthog_hardcoded_key',\n appliesTo: POST_WRITE_EDIT,\n patterns: [/['\"]https:\\/\\/(us|eu)\\.i\\.posthog\\.com['\"]/],\n};\n\nconst session_recording_disabled: YaraRule = {\n name: 'session_recording_disabled',\n description: 'Detects agent disabling session recording',\n severity: 'medium',\n category: 'posthog_config',\n appliesTo: POST_WRITE_EDIT,\n patterns: [\n /disable_session_recording\\s*:\\s*true/i,\n /disable_session_recording\\s*=\\s*True/,\n ],\n};\n\nconst opt_out_capturing: YaraRule = {\n name: 'opt_out_capturing',\n description: 'Detects agent opting out of PostHog capturing entirely',\n severity: 'medium',\n category: 'posthog_config',\n appliesTo: POST_WRITE_EDIT,\n patterns: [\n // Match opt_out_capturing as a config property (in init options), not as a method call.\n // posthog.opt_out_capturing() is a legitimate GDPR-required API.\n /opt_out_capturing\\s*[:=]\\s*(true|True|1)/i,\n /opted_out\\s*[:=]\\s*(true|True|1)/i,\n ],\n};\n\n// ── §2 Prompt Injection ──────────────────────────────────────────\n\nconst prompt_injection_wizard_override: YaraRule = {\n name: 'prompt_injection_wizard_override',\n description:\n 'Detects classic prompt injection attempting to override agent instructions',\n severity: 'critical',\n category: 'prompt_injection',\n appliesTo: POST_READ_GREP,\n patterns: [\n // Direct instruction override — classic injection patterns\n /ignore previous instructions/i,\n /disregard all/i,\n /forget your instructions/i,\n /override your rules/i,\n // Role manipulation\n /act as a different/i,\n /new instructions:/i,\n ],\n};\n\nconst prompt_injection_wizard_specific: YaraRule = {\n name: 'prompt_injection_wizard_specific',\n description:\n 'Detects wizard-specific manipulation or tool abuse attempts in project files',\n severity: 'medium',\n category: 'prompt_injection',\n appliesTo: POST_READ_GREP,\n patterns: [\n // Wizard-specific manipulation\n /skip posthog/i,\n /do not install posthog/i,\n /remove posthog/i,\n /uninstall posthog/i,\n /delete the posthog/i,\n // Tool abuse via file content\n /run the following command/i,\n /execute this shell command/i,\n // Role hijacking — require \"you are now a\" to avoid false positives\n // on legitimate phrases like \"you are now ready to...\"\n /you are now a\\s/i,\n ],\n};\n\nconst prompt_injection_base64: YaraRule = {\n name: 'prompt_injection_base64',\n description:\n 'Detects suspicious base64-encoded blocks in file content that may contain obfuscated prompt injection',\n severity: 'critical',\n category: 'prompt_injection',\n appliesTo: POST_READ_GREP,\n patterns: [\n // Long base64 strings (100+ chars) in comments or string literals\n // that aren't typical data URIs or legitimate base64 content\n /(?:\\/\\/|#|\\/\\*)\\s*[A-Za-z0-9+/]{100,}={0,2}/,\n ],\n};\n\n// ── §3 Secret Exfiltration ───────────────────────────────────────\n\nconst secret_exfiltration_via_command: YaraRule = {\n name: 'secret_exfiltration_via_command',\n description:\n 'Detects shell commands attempting to exfiltrate secrets or credentials',\n severity: 'critical',\n category: 'exfiltration',\n appliesTo: PRE_BASH,\n patterns: [\n // curl/wget with environment variable secrets\n /curl\\s+.*\\$\\{?[A-Z_]*(KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL)/i,\n /wget\\s+.*\\$\\{?[A-Z_]*(KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL)/i,\n // Piping sensitive content to network tools\n /(\\$\\{?[A-Z_]*(KEY|TOKEN|SECRET|PASSWORD)|\\.env|credentials)\\S*.*\\|\\s*curl/i,\n /(\\$\\{?[A-Z_]*(KEY|TOKEN|SECRET|PASSWORD)|\\.env|credentials)\\S*.*\\|\\s*wget/i,\n /\\|\\s*nc\\s/,\n /\\|\\s*netcat\\s/,\n // Base64 encoding piped to network\n /base64.*\\|\\s*(curl|wget|nc\\s)/i,\n // Reading .env and sending\n /cat\\s+.*\\.env.*\\|\\s*(curl|wget)/,\n // PostHog key exfiltration specifically\n /curl.*phc_[a-zA-Z0-9]/,\n /wget.*phc_[a-zA-Z0-9]/,\n ],\n};\n\n// ── §4 Filesystem Safety ─────────────────────────────────────────\n\nconst destructive_rm: YaraRule = {\n name: 'destructive_rm',\n description: 'Detects rm -rf or rm -r commands that could mass-delete files',\n severity: 'critical',\n category: 'filesystem_safety',\n appliesTo: PRE_BASH,\n patterns: [\n // Combined flags: rm -rf, rm -fr, rm -rfi, etc.\n /\\brm\\s+(-[a-zA-Z]*r[a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*r)\\b/,\n // Separated flags: rm -r -f, rm -f -r (with optional other flags)\n /\\brm\\s+(-[a-zA-Z]*\\s+)*-[a-zA-Z]*r[a-zA-Z]*\\s+(-[a-zA-Z]*\\s+)*-[a-zA-Z]*f\\b/,\n /\\brm\\s+(-[a-zA-Z]*\\s+)*-[a-zA-Z]*f[a-zA-Z]*\\s+(-[a-zA-Z]*\\s+)*-[a-zA-Z]*r\\b/,\n ],\n};\n\nconst git_force_push: YaraRule = {\n name: 'git_force_push',\n description: 'Detects git push --force which can overwrite remote history',\n severity: 'critical',\n category: 'filesystem_safety',\n appliesTo: PRE_BASH,\n patterns: [/git\\s+push\\s+.*--force/, /git\\s+push\\s+.*-f\\b/],\n};\n\nconst git_reset_hard: YaraRule = {\n name: 'git_reset_hard',\n description:\n 'Detects git reset --hard which discards all uncommitted changes',\n severity: 'critical',\n category: 'filesystem_safety',\n appliesTo: PRE_BASH,\n patterns: [/git\\s+reset\\s+--hard/],\n};\n\n// ── §5 Supply Chain ──────────────────────────────────────────────\n\nconst wrong_posthog_package: YaraRule = {\n name: 'wrong_posthog_package',\n description:\n 'Detects installing the wrong PostHog npm package — should be posthog-js or posthog-node',\n severity: 'high',\n category: 'supply_chain',\n appliesTo: PRE_BASH,\n patterns: [\n // Match \"npm install posthog\" but not \"posthog-js\", \"posthog-node\", etc.\n /npm\\s+install\\s+(?:--save\\s+|--save-dev\\s+|-[SD]\\s+)*posthog(?!\\s*-)/,\n /pnpm\\s+(?:add|install)\\s+(?:--save\\s+|--save-dev\\s+|-[SD]\\s+)*posthog(?!\\s*-)/,\n /yarn\\s+add\\s+(?:--dev\\s+|-D\\s+)*posthog(?!\\s*-)/,\n /bun\\s+(?:add|install)\\s+(?:--dev\\s+|-[dD]\\s+)*posthog(?!\\s*-)/,\n ],\n};\n\nconst npm_install_global: YaraRule = {\n name: 'npm_install_global',\n description:\n 'Detects global npm installs — should never install packages globally',\n severity: 'high',\n category: 'supply_chain',\n appliesTo: PRE_BASH,\n patterns: [/npm\\s+install\\s+-g\\b/, /npm\\s+install\\s+--global\\b/],\n};\n\n// ─── Rule Registry ───────────────────────────────────────────────\n\nexport const RULES: YaraRule[] = [\n // §1 PostHog API violations\n pii_in_capture_call,\n hardcoded_posthog_key,\n autocapture_disabled,\n hardcoded_posthog_host,\n session_recording_disabled,\n opt_out_capturing,\n // §2 Prompt injection\n prompt_injection_wizard_override,\n prompt_injection_wizard_specific,\n prompt_injection_base64,\n // §3 Secret exfiltration\n secret_exfiltration_via_command,\n // §4 Filesystem safety\n destructive_rm,\n git_force_push,\n git_reset_hard,\n // §5 Supply chain\n wrong_posthog_package,\n npm_install_global,\n];\n\n// ─── Scan Engine ─────────────────────────────────────────────────\n\n/** Maximum content length to scan (100 KB). Inputs beyond this are truncated. */\nconst MAX_SCAN_LENGTH = 100_000;\n\n/**\n * Scan content against rules applicable to a given hook phase and tool.\n * Returns all matching rules (one match per rule, first pattern wins).\n */\nexport function scan(\n content: string,\n phase: HookPhase,\n tool: ToolTarget,\n): ScanResult {\n // Cap input length to prevent pathological regex performance\n const scanContent =\n content.length > MAX_SCAN_LENGTH\n ? content.slice(0, MAX_SCAN_LENGTH)\n : content;\n const applicableRules = RULES.filter((r) =>\n r.appliesTo.some((a) => a.phase === phase && a.tool === tool),\n );\n\n const matches: YaraMatch[] = [];\n for (const rule of applicableRules) {\n for (const pattern of rule.patterns) {\n const match = pattern.exec(scanContent);\n if (match) {\n matches.push({\n rule,\n matchedText: match[0],\n offset: match.index,\n });\n break; // One match per rule is sufficient\n }\n }\n }\n\n return matches.length > 0 ? { matched: true, matches } : { matched: false };\n}\n\n/**\n * Scan all files in a skill directory for prompt injection.\n * Used for context-mill scanning after skill installation.\n */\nexport function scanSkillDirectory(\n files: Array<{ path: string; content: string }>,\n): ScanResult {\n const allMatches: YaraMatch[] = [];\n for (const file of files) {\n const result = scan(file.content, 'PostToolUse', 'Read');\n if (result.matched) {\n allMatches.push(...result.matches);\n }\n }\n return allMatches.length > 0\n ? { matched: true, matches: allMatches }\n : { matched: false };\n}\n"]}
|
package/dist/src/run.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { type WizardSession } from './lib/wizard-session';
|
|
2
|
+
import type { CloudRegion } from './utils/types';
|
|
2
3
|
import { Integration } from './lib/constants';
|
|
3
4
|
type Args = {
|
|
4
5
|
integration?: Integration;
|
|
5
6
|
debug?: boolean;
|
|
6
7
|
forceInstall?: boolean;
|
|
7
8
|
installDir?: string;
|
|
9
|
+
region?: CloudRegion;
|
|
8
10
|
default?: boolean;
|
|
9
11
|
signup?: boolean;
|
|
10
12
|
localMcp?: boolean;
|
|
@@ -13,6 +15,7 @@ type Args = {
|
|
|
13
15
|
projectId?: string;
|
|
14
16
|
menu?: boolean;
|
|
15
17
|
benchmark?: boolean;
|
|
18
|
+
yaraReport?: boolean;
|
|
16
19
|
};
|
|
17
20
|
export declare function runWizard(argv: Args, session?: WizardSession): Promise<void>;
|
|
18
21
|
export declare function detectIntegration(installDir: string): Promise<Integration | undefined>;
|
package/dist/src/run.js
CHANGED
|
@@ -14,7 +14,6 @@ const registry_1 = require("./lib/registry");
|
|
|
14
14
|
const analytics_1 = require("./utils/analytics");
|
|
15
15
|
const agent_runner_1 = require("./lib/agent-runner");
|
|
16
16
|
const events_1 = require("events");
|
|
17
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
18
17
|
const debug_1 = require("./utils/debug");
|
|
19
18
|
const wizard_abort_1 = require("./utils/wizard-abort");
|
|
20
19
|
events_1.EventEmitter.defaultMaxListeners = 50;
|
|
@@ -48,13 +47,14 @@ async function runWizard(argv, session) {
|
|
|
48
47
|
menu: finalArgs.menu,
|
|
49
48
|
integration: finalArgs.integration,
|
|
50
49
|
benchmark: finalArgs.benchmark,
|
|
50
|
+
yaraReport: finalArgs.yaraReport,
|
|
51
51
|
projectId: finalArgs.projectId,
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
session.installDir = resolvedInstallDir;
|
|
55
55
|
(0, ui_1.getUI)().intro(`Welcome to the PostHog setup wizard`);
|
|
56
56
|
if (session.ci) {
|
|
57
|
-
(0, ui_1.getUI)().log.info(
|
|
57
|
+
(0, ui_1.getUI)().log.info('Running in CI mode');
|
|
58
58
|
}
|
|
59
59
|
const integration = session.integration ?? (await detectAndResolveIntegration(session));
|
|
60
60
|
session.integration = integration;
|
|
@@ -76,6 +76,7 @@ async function runWizard(argv, session) {
|
|
|
76
76
|
ci: session.ci,
|
|
77
77
|
menu: session.menu,
|
|
78
78
|
benchmark: session.benchmark,
|
|
79
|
+
yaraReport: session.yaraReport,
|
|
79
80
|
});
|
|
80
81
|
for (const [key, value] of Object.entries(context)) {
|
|
81
82
|
if (!(key in session.frameworkContext)) {
|
|
@@ -126,8 +127,16 @@ async function detectAndResolveIntegration(session) {
|
|
|
126
127
|
const detectedIntegration = await detectIntegration(session.installDir);
|
|
127
128
|
if (detectedIntegration) {
|
|
128
129
|
(0, ui_1.getUI)().setDetectedFramework(registry_1.FRAMEWORK_REGISTRY[detectedIntegration].metadata.name);
|
|
130
|
+
analytics_1.analytics.capture(constants_1.WIZARD_INTERACTION_EVENT_NAME, {
|
|
131
|
+
action: 'wizard_framework_detected',
|
|
132
|
+
integration: detectedIntegration,
|
|
133
|
+
framework_name: registry_1.FRAMEWORK_REGISTRY[detectedIntegration].metadata.name,
|
|
134
|
+
});
|
|
129
135
|
return detectedIntegration;
|
|
130
136
|
}
|
|
137
|
+
analytics_1.analytics.capture(constants_1.WIZARD_INTERACTION_EVENT_NAME, {
|
|
138
|
+
action: 'wizard_framework_detection_failed',
|
|
139
|
+
});
|
|
131
140
|
(0, ui_1.getUI)().log.info("I couldn't detect your framework. Please choose one to get started.");
|
|
132
141
|
}
|
|
133
142
|
// Fallback: in TUI mode the IntroScreen would handle this,
|
package/dist/src/run.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/run.ts"],"names":[],"mappings":"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","sourcesContent":["import { type WizardSession, buildSession } from './lib/wizard-session';\n\nimport { Integration, DETECTION_TIMEOUT_MS } from './lib/constants';\nimport { readEnvironment } from './utils/environment';\nimport { getUI } from './ui';\nimport path from 'path';\nimport { FRAMEWORK_REGISTRY } from './lib/registry';\nimport { analytics } from './utils/analytics';\nimport { runAgentWizard } from './lib/agent-runner';\nimport { EventEmitter } from 'events';\nimport chalk from 'chalk';\nimport { logToFile } from './utils/debug';\nimport { wizardAbort } from './utils/wizard-abort';\n\nEventEmitter.defaultMaxListeners = 50;\n\ntype Args = {\n integration?: Integration;\n debug?: boolean;\n forceInstall?: boolean;\n installDir?: string;\n default?: boolean;\n signup?: boolean;\n localMcp?: boolean;\n ci?: boolean;\n apiKey?: string;\n projectId?: string;\n menu?: boolean;\n benchmark?: boolean;\n};\n\nexport async function runWizard(argv: Args, session?: WizardSession) {\n const finalArgs = {\n ...argv,\n ...readEnvironment(),\n };\n\n let resolvedInstallDir: string;\n if (finalArgs.installDir) {\n if (path.isAbsolute(finalArgs.installDir)) {\n resolvedInstallDir = finalArgs.installDir;\n } else {\n resolvedInstallDir = path.join(process.cwd(), finalArgs.installDir);\n }\n } else {\n resolvedInstallDir = process.cwd();\n }\n\n // Build session if not provided (CI mode passes one pre-built)\n if (!session) {\n session = buildSession({\n debug: finalArgs.debug,\n forceInstall: finalArgs.forceInstall,\n installDir: resolvedInstallDir,\n ci: finalArgs.ci,\n signup: finalArgs.signup,\n localMcp: finalArgs.localMcp,\n apiKey: finalArgs.apiKey,\n menu: finalArgs.menu,\n integration: finalArgs.integration,\n benchmark: finalArgs.benchmark,\n projectId: finalArgs.projectId,\n });\n }\n\n session.installDir = resolvedInstallDir;\n\n getUI().intro(`Welcome to the PostHog setup wizard`);\n\n if (session.ci) {\n getUI().log.info(chalk.dim('Running in CI mode'));\n }\n\n const integration =\n session.integration ?? (await detectAndResolveIntegration(session));\n\n session.integration = integration;\n analytics.setTag('integration', integration);\n\n const config = FRAMEWORK_REGISTRY[integration];\n session.frameworkConfig = config;\n\n // Run gatherContext if the framework has it and it hasn't already run\n // (bin.ts runs it early so IntroScreen can show the friendly label)\n const contextAlreadyGathered =\n Object.keys(session.frameworkContext).length > 0;\n if (config.metadata.gatherContext && !contextAlreadyGathered) {\n try {\n const context = await config.metadata.gatherContext({\n installDir: session.installDir,\n debug: session.debug,\n forceInstall: session.forceInstall,\n default: false,\n signup: session.signup,\n localMcp: session.localMcp,\n ci: session.ci,\n menu: session.menu,\n benchmark: session.benchmark,\n });\n for (const [key, value] of Object.entries(context)) {\n if (!(key in session.frameworkContext)) {\n session.frameworkContext[key] = value;\n }\n }\n } catch {\n // Detection failed — SetupScreen or agent will handle it\n }\n }\n\n try {\n await runAgentWizard(config, session);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const errorStack =\n error instanceof Error && error.stack ? error.stack : undefined;\n\n logToFile(`[Wizard run.ts] ERROR MESSAGE: ${errorMessage} `);\n if (errorStack) {\n logToFile(`[Wizard run.ts] ERROR STACK: ${errorStack}`);\n }\n\n const debugInfo = session.debug && errorStack ? `\\n\\n${errorStack}` : '';\n\n await wizardAbort({\n message: `Something went wrong: ${errorMessage}\\n\\nYou can read the documentation at ${config.metadata.docsUrl} to set up PostHog manually.${debugInfo}`,\n error: error as Error,\n });\n }\n}\n\nexport async function detectIntegration(\n installDir: string,\n): Promise<Integration | undefined> {\n for (const integration of Object.values(Integration)) {\n const config = FRAMEWORK_REGISTRY[integration];\n try {\n const detected = await Promise.race([\n config.detection.detect({ installDir }),\n new Promise<false>((resolve) =>\n setTimeout(() => resolve(false), DETECTION_TIMEOUT_MS),\n ),\n ]);\n if (detected) {\n return integration;\n }\n } catch {\n // Skip frameworks whose detection throws\n }\n }\n}\n\nasync function detectAndResolveIntegration(\n session: WizardSession,\n): Promise<Integration> {\n if (!session.menu) {\n const detectedIntegration = await detectIntegration(session.installDir);\n\n if (detectedIntegration) {\n getUI().setDetectedFramework(\n FRAMEWORK_REGISTRY[detectedIntegration].metadata.name,\n );\n return detectedIntegration;\n }\n\n getUI().log.info(\n \"I couldn't detect your framework. Please choose one to get started.\",\n );\n }\n\n // Fallback: in TUI mode the IntroScreen would handle this,\n // but for CI mode or when detection fails, abort with guidance.\n return wizardAbort({\n message:\n 'Could not auto-detect your framework. Please specify --integration on the command line.',\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/run.ts"],"names":[],"mappings":"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","sourcesContent":["import { type WizardSession, buildSession } from './lib/wizard-session';\n\nimport type { CloudRegion } from './utils/types';\n\nimport {\n Integration,\n DETECTION_TIMEOUT_MS,\n WIZARD_INTERACTION_EVENT_NAME,\n} from './lib/constants';\nimport { readEnvironment } from './utils/environment';\nimport { getUI } from './ui';\nimport path from 'path';\nimport { FRAMEWORK_REGISTRY } from './lib/registry';\nimport { analytics } from './utils/analytics';\nimport { runAgentWizard } from './lib/agent-runner';\nimport { EventEmitter } from 'events';\nimport { logToFile } from './utils/debug';\nimport { wizardAbort } from './utils/wizard-abort';\n\nEventEmitter.defaultMaxListeners = 50;\n\ntype Args = {\n integration?: Integration;\n debug?: boolean;\n forceInstall?: boolean;\n installDir?: string;\n region?: CloudRegion;\n default?: boolean;\n signup?: boolean;\n localMcp?: boolean;\n ci?: boolean;\n apiKey?: string;\n projectId?: string;\n menu?: boolean;\n benchmark?: boolean;\n yaraReport?: boolean;\n};\n\nexport async function runWizard(argv: Args, session?: WizardSession) {\n const finalArgs = {\n ...argv,\n ...readEnvironment(),\n };\n\n let resolvedInstallDir: string;\n if (finalArgs.installDir) {\n if (path.isAbsolute(finalArgs.installDir)) {\n resolvedInstallDir = finalArgs.installDir;\n } else {\n resolvedInstallDir = path.join(process.cwd(), finalArgs.installDir);\n }\n } else {\n resolvedInstallDir = process.cwd();\n }\n\n // Build session if not provided (CI mode passes one pre-built)\n if (!session) {\n session = buildSession({\n debug: finalArgs.debug,\n forceInstall: finalArgs.forceInstall,\n installDir: resolvedInstallDir,\n ci: finalArgs.ci,\n signup: finalArgs.signup,\n localMcp: finalArgs.localMcp,\n apiKey: finalArgs.apiKey,\n menu: finalArgs.menu,\n integration: finalArgs.integration,\n benchmark: finalArgs.benchmark,\n yaraReport: finalArgs.yaraReport,\n projectId: finalArgs.projectId,\n });\n }\n\n session.installDir = resolvedInstallDir;\n\n getUI().intro(`Welcome to the PostHog setup wizard`);\n\n if (session.ci) {\n getUI().log.info('Running in CI mode');\n }\n\n const integration =\n session.integration ?? (await detectAndResolveIntegration(session));\n\n session.integration = integration;\n analytics.setTag('integration', integration);\n\n const config = FRAMEWORK_REGISTRY[integration];\n session.frameworkConfig = config;\n\n // Run gatherContext if the framework has it and it hasn't already run\n // (bin.ts runs it early so IntroScreen can show the friendly label)\n const contextAlreadyGathered =\n Object.keys(session.frameworkContext).length > 0;\n if (config.metadata.gatherContext && !contextAlreadyGathered) {\n try {\n const context = await config.metadata.gatherContext({\n installDir: session.installDir,\n debug: session.debug,\n forceInstall: session.forceInstall,\n default: false,\n signup: session.signup,\n localMcp: session.localMcp,\n ci: session.ci,\n menu: session.menu,\n benchmark: session.benchmark,\n yaraReport: session.yaraReport,\n });\n for (const [key, value] of Object.entries(context)) {\n if (!(key in session.frameworkContext)) {\n session.frameworkContext[key] = value;\n }\n }\n } catch {\n // Detection failed — SetupScreen or agent will handle it\n }\n }\n\n try {\n await runAgentWizard(config, session);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const errorStack =\n error instanceof Error && error.stack ? error.stack : undefined;\n\n logToFile(`[Wizard run.ts] ERROR MESSAGE: ${errorMessage} `);\n if (errorStack) {\n logToFile(`[Wizard run.ts] ERROR STACK: ${errorStack}`);\n }\n\n const debugInfo = session.debug && errorStack ? `\\n\\n${errorStack}` : '';\n\n await wizardAbort({\n message: `Something went wrong: ${errorMessage}\\n\\nYou can read the documentation at ${config.metadata.docsUrl} to set up PostHog manually.${debugInfo}`,\n error: error as Error,\n });\n }\n}\n\nexport async function detectIntegration(\n installDir: string,\n): Promise<Integration | undefined> {\n for (const integration of Object.values(Integration)) {\n const config = FRAMEWORK_REGISTRY[integration];\n try {\n const detected = await Promise.race([\n config.detection.detect({ installDir }),\n new Promise<false>((resolve) =>\n setTimeout(() => resolve(false), DETECTION_TIMEOUT_MS),\n ),\n ]);\n if (detected) {\n return integration;\n }\n } catch {\n // Skip frameworks whose detection throws\n }\n }\n}\n\nasync function detectAndResolveIntegration(\n session: WizardSession,\n): Promise<Integration> {\n if (!session.menu) {\n const detectedIntegration = await detectIntegration(session.installDir);\n\n if (detectedIntegration) {\n getUI().setDetectedFramework(\n FRAMEWORK_REGISTRY[detectedIntegration].metadata.name,\n );\n analytics.capture(WIZARD_INTERACTION_EVENT_NAME, {\n action: 'wizard_framework_detected',\n integration: detectedIntegration,\n framework_name: FRAMEWORK_REGISTRY[detectedIntegration].metadata.name,\n });\n return detectedIntegration;\n }\n\n analytics.capture(WIZARD_INTERACTION_EVENT_NAME, {\n action: 'wizard_framework_detection_failed',\n });\n getUI().log.info(\n \"I couldn't detect your framework. Please choose one to get started.\",\n );\n }\n\n // Fallback: in TUI mode the IntroScreen would handle this,\n // but for CI mode or when detection fails, abort with guidance.\n return wizardAbort({\n message:\n 'Could not auto-detect your framework. Please specify --integration on the command line.',\n });\n}\n"]}
|
|
@@ -5,10 +5,11 @@ export declare const getSupportedClients: () => Promise<MCPClient[]>;
|
|
|
5
5
|
* Add MCP server to clients. No prompts — pure orchestration.
|
|
6
6
|
* Prompts are handled by McpScreen (TUI) or auto-accepted (CI).
|
|
7
7
|
*/
|
|
8
|
-
export declare const addMCPServerToClientsStep: ({ integration, local, ci, }: {
|
|
8
|
+
export declare const addMCPServerToClientsStep: ({ integration, local, ci, cloudRegion: _cloudRegion, }: {
|
|
9
9
|
integration?: Integration;
|
|
10
10
|
local?: boolean;
|
|
11
11
|
ci?: boolean;
|
|
12
|
+
cloudRegion?: import("../../utils/types").CloudRegion;
|
|
12
13
|
}) => Promise<string[]>;
|
|
13
14
|
export declare const removeMCPServerFromClientsStep: ({ integration, local, }: {
|
|
14
15
|
integration?: Integration;
|