mstro-app 0.4.2 → 0.4.4
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/bin/mstro.js +119 -40
- package/dist/server/cli/headless/claude-invoker-process.d.ts +11 -0
- package/dist/server/cli/headless/claude-invoker-process.d.ts.map +1 -0
- package/dist/server/cli/headless/claude-invoker-process.js +140 -0
- package/dist/server/cli/headless/claude-invoker-process.js.map +1 -0
- package/dist/server/cli/headless/claude-invoker-stall.d.ts +40 -0
- package/dist/server/cli/headless/claude-invoker-stall.d.ts.map +1 -0
- package/dist/server/cli/headless/claude-invoker-stall.js +98 -0
- package/dist/server/cli/headless/claude-invoker-stall.js.map +1 -0
- package/dist/server/cli/headless/claude-invoker-stream.d.ts +44 -0
- package/dist/server/cli/headless/claude-invoker-stream.d.ts.map +1 -0
- package/dist/server/cli/headless/claude-invoker-stream.js +276 -0
- package/dist/server/cli/headless/claude-invoker-stream.js.map +1 -0
- package/dist/server/cli/headless/claude-invoker-tools.d.ts +21 -0
- package/dist/server/cli/headless/claude-invoker-tools.d.ts.map +1 -0
- package/dist/server/cli/headless/claude-invoker-tools.js +137 -0
- package/dist/server/cli/headless/claude-invoker-tools.js.map +1 -0
- package/dist/server/cli/headless/claude-invoker.d.ts +6 -4
- package/dist/server/cli/headless/claude-invoker.d.ts.map +1 -1
- package/dist/server/cli/headless/claude-invoker.js +10 -804
- package/dist/server/cli/headless/claude-invoker.js.map +1 -1
- package/dist/server/cli/headless/haiku-assessments.d.ts +62 -0
- package/dist/server/cli/headless/haiku-assessments.d.ts.map +1 -0
- package/dist/server/cli/headless/haiku-assessments.js +281 -0
- package/dist/server/cli/headless/haiku-assessments.js.map +1 -0
- package/dist/server/cli/headless/headless-logger.d.ts +3 -2
- package/dist/server/cli/headless/headless-logger.d.ts.map +1 -1
- package/dist/server/cli/headless/headless-logger.js +28 -5
- package/dist/server/cli/headless/headless-logger.js.map +1 -1
- package/dist/server/cli/headless/native-timeout-detector.d.ts +44 -0
- package/dist/server/cli/headless/native-timeout-detector.d.ts.map +1 -0
- package/dist/server/cli/headless/native-timeout-detector.js +99 -0
- package/dist/server/cli/headless/native-timeout-detector.js.map +1 -0
- package/dist/server/cli/headless/stall-assessor.d.ts +2 -110
- package/dist/server/cli/headless/stall-assessor.d.ts.map +1 -1
- package/dist/server/cli/headless/stall-assessor.js +65 -457
- package/dist/server/cli/headless/stall-assessor.js.map +1 -1
- package/dist/server/cli/headless/types.d.ts +4 -1
- package/dist/server/cli/headless/types.d.ts.map +1 -1
- package/dist/server/cli/improvisation-attachments.d.ts +21 -0
- package/dist/server/cli/improvisation-attachments.d.ts.map +1 -0
- package/dist/server/cli/improvisation-attachments.js +116 -0
- package/dist/server/cli/improvisation-attachments.js.map +1 -0
- package/dist/server/cli/improvisation-retry.d.ts +52 -0
- package/dist/server/cli/improvisation-retry.d.ts.map +1 -0
- package/dist/server/cli/improvisation-retry.js +434 -0
- package/dist/server/cli/improvisation-retry.js.map +1 -0
- package/dist/server/cli/improvisation-session-manager.d.ts +10 -266
- package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -1
- package/dist/server/cli/improvisation-session-manager.js +117 -1079
- package/dist/server/cli/improvisation-session-manager.js.map +1 -1
- package/dist/server/cli/improvisation-types.d.ts +86 -0
- package/dist/server/cli/improvisation-types.d.ts.map +1 -0
- package/dist/server/cli/improvisation-types.js +10 -0
- package/dist/server/cli/improvisation-types.js.map +1 -0
- package/dist/server/cli/prompt-builders.d.ts +68 -0
- package/dist/server/cli/prompt-builders.d.ts.map +1 -0
- package/dist/server/cli/prompt-builders.js +312 -0
- package/dist/server/cli/prompt-builders.js.map +1 -0
- package/dist/server/index.js +33 -212
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/bouncer-haiku.d.ts +10 -0
- package/dist/server/mcp/bouncer-haiku.d.ts.map +1 -0
- package/dist/server/mcp/bouncer-haiku.js +152 -0
- package/dist/server/mcp/bouncer-haiku.js.map +1 -0
- package/dist/server/mcp/bouncer-integration.d.ts +3 -4
- package/dist/server/mcp/bouncer-integration.d.ts.map +1 -1
- package/dist/server/mcp/bouncer-integration.js +50 -196
- package/dist/server/mcp/bouncer-integration.js.map +1 -1
- package/dist/server/mcp/security-analysis.d.ts +38 -0
- package/dist/server/mcp/security-analysis.d.ts.map +1 -0
- package/dist/server/mcp/security-analysis.js +183 -0
- package/dist/server/mcp/security-analysis.js.map +1 -0
- package/dist/server/mcp/security-audit.d.ts +1 -1
- package/dist/server/mcp/security-audit.d.ts.map +1 -1
- package/dist/server/mcp/security-patterns.d.ts +1 -25
- package/dist/server/mcp/security-patterns.d.ts.map +1 -1
- package/dist/server/mcp/security-patterns.js +55 -260
- package/dist/server/mcp/security-patterns.js.map +1 -1
- package/dist/server/server-setup.d.ts +22 -0
- package/dist/server/server-setup.d.ts.map +1 -0
- package/dist/server/server-setup.js +101 -0
- package/dist/server/server-setup.js.map +1 -0
- package/dist/server/services/file-explorer-ops.d.ts +24 -0
- package/dist/server/services/file-explorer-ops.d.ts.map +1 -0
- package/dist/server/services/file-explorer-ops.js +211 -0
- package/dist/server/services/file-explorer-ops.js.map +1 -0
- package/dist/server/services/files.d.ts +2 -85
- package/dist/server/services/files.d.ts.map +1 -1
- package/dist/server/services/files.js +7 -427
- package/dist/server/services/files.js.map +1 -1
- package/dist/server/services/plan/composer.d.ts +1 -1
- package/dist/server/services/plan/composer.d.ts.map +1 -1
- package/dist/server/services/plan/composer.js +118 -32
- package/dist/server/services/plan/composer.js.map +1 -1
- package/dist/server/services/plan/config-installer.d.ts +25 -0
- package/dist/server/services/plan/config-installer.d.ts.map +1 -0
- package/dist/server/services/plan/config-installer.js +182 -0
- package/dist/server/services/plan/config-installer.js.map +1 -0
- package/dist/server/services/plan/dependency-resolver.d.ts +1 -1
- package/dist/server/services/plan/dependency-resolver.d.ts.map +1 -1
- package/dist/server/services/plan/dependency-resolver.js +4 -1
- package/dist/server/services/plan/dependency-resolver.js.map +1 -1
- package/dist/server/services/plan/executor.d.ts +38 -74
- package/dist/server/services/plan/executor.d.ts.map +1 -1
- package/dist/server/services/plan/executor.js +274 -460
- package/dist/server/services/plan/executor.js.map +1 -1
- package/dist/server/services/plan/front-matter.d.ts +18 -0
- package/dist/server/services/plan/front-matter.d.ts.map +1 -0
- package/dist/server/services/plan/front-matter.js +44 -0
- package/dist/server/services/plan/front-matter.js.map +1 -0
- package/dist/server/services/plan/output-manager.d.ts +22 -0
- package/dist/server/services/plan/output-manager.d.ts.map +1 -0
- package/dist/server/services/plan/output-manager.js +97 -0
- package/dist/server/services/plan/output-manager.js.map +1 -0
- package/dist/server/services/plan/parser-core.d.ts +20 -0
- package/dist/server/services/plan/parser-core.d.ts.map +1 -0
- package/dist/server/services/plan/parser-core.js +350 -0
- package/dist/server/services/plan/parser-core.js.map +1 -0
- package/dist/server/services/plan/parser-migration.d.ts +5 -0
- package/dist/server/services/plan/parser-migration.d.ts.map +1 -0
- package/dist/server/services/plan/parser-migration.js +124 -0
- package/dist/server/services/plan/parser-migration.js.map +1 -0
- package/dist/server/services/plan/parser.d.ts +11 -3
- package/dist/server/services/plan/parser.d.ts.map +1 -1
- package/dist/server/services/plan/parser.js +184 -369
- package/dist/server/services/plan/parser.js.map +1 -1
- package/dist/server/services/plan/prompt-builder.d.ts +17 -0
- package/dist/server/services/plan/prompt-builder.d.ts.map +1 -0
- package/dist/server/services/plan/prompt-builder.js +137 -0
- package/dist/server/services/plan/prompt-builder.js.map +1 -0
- package/dist/server/services/plan/review-gate.d.ts +28 -0
- package/dist/server/services/plan/review-gate.d.ts.map +1 -0
- package/dist/server/services/plan/review-gate.js +191 -0
- package/dist/server/services/plan/review-gate.js.map +1 -0
- package/dist/server/services/plan/state-reconciler.d.ts +1 -1
- package/dist/server/services/plan/state-reconciler.d.ts.map +1 -1
- package/dist/server/services/plan/state-reconciler.js +59 -7
- package/dist/server/services/plan/state-reconciler.js.map +1 -1
- package/dist/server/services/plan/types.d.ts +68 -0
- package/dist/server/services/plan/types.d.ts.map +1 -1
- package/dist/server/services/platform-credentials.d.ts +24 -0
- package/dist/server/services/platform-credentials.d.ts.map +1 -0
- package/dist/server/services/platform-credentials.js +68 -0
- package/dist/server/services/platform-credentials.js.map +1 -0
- package/dist/server/services/platform.d.ts +1 -31
- package/dist/server/services/platform.d.ts.map +1 -1
- package/dist/server/services/platform.js +11 -109
- package/dist/server/services/platform.js.map +1 -1
- package/dist/server/services/terminal/pty-manager.d.ts +7 -97
- package/dist/server/services/terminal/pty-manager.d.ts.map +1 -1
- package/dist/server/services/terminal/pty-manager.js +53 -266
- package/dist/server/services/terminal/pty-manager.js.map +1 -1
- package/dist/server/services/terminal/pty-utils.d.ts +57 -0
- package/dist/server/services/terminal/pty-utils.d.ts.map +1 -0
- package/dist/server/services/terminal/pty-utils.js +141 -0
- package/dist/server/services/terminal/pty-utils.js.map +1 -0
- package/dist/server/services/websocket/file-definition-handlers.d.ts +4 -0
- package/dist/server/services/websocket/file-definition-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/file-definition-handlers.js +153 -0
- package/dist/server/services/websocket/file-definition-handlers.js.map +1 -0
- package/dist/server/services/websocket/file-explorer-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/file-explorer-handlers.js +52 -391
- package/dist/server/services/websocket/file-explorer-handlers.js.map +1 -1
- package/dist/server/services/websocket/file-search-handlers.d.ts +5 -0
- package/dist/server/services/websocket/file-search-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/file-search-handlers.js +238 -0
- package/dist/server/services/websocket/file-search-handlers.js.map +1 -0
- package/dist/server/services/websocket/file-utils.js +3 -3
- package/dist/server/services/websocket/file-utils.js.map +1 -1
- package/dist/server/services/websocket/git-branch-handlers.d.ts +7 -0
- package/dist/server/services/websocket/git-branch-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/git-branch-handlers.js +110 -0
- package/dist/server/services/websocket/git-branch-handlers.js.map +1 -0
- package/dist/server/services/websocket/git-diff-handlers.d.ts +6 -0
- package/dist/server/services/websocket/git-diff-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/git-diff-handlers.js +123 -0
- package/dist/server/services/websocket/git-diff-handlers.js.map +1 -0
- package/dist/server/services/websocket/git-handlers.d.ts +2 -31
- package/dist/server/services/websocket/git-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/git-handlers.js +35 -541
- package/dist/server/services/websocket/git-handlers.js.map +1 -1
- package/dist/server/services/websocket/git-log-handlers.d.ts +6 -0
- package/dist/server/services/websocket/git-log-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/git-log-handlers.js +128 -0
- package/dist/server/services/websocket/git-log-handlers.js.map +1 -0
- package/dist/server/services/websocket/git-pr-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/git-pr-handlers.js +13 -53
- package/dist/server/services/websocket/git-pr-handlers.js.map +1 -1
- package/dist/server/services/websocket/git-tag-handlers.d.ts +6 -0
- package/dist/server/services/websocket/git-tag-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/git-tag-handlers.js +76 -0
- package/dist/server/services/websocket/git-tag-handlers.js.map +1 -0
- package/dist/server/services/websocket/git-utils.d.ts +43 -0
- package/dist/server/services/websocket/git-utils.d.ts.map +1 -0
- package/dist/server/services/websocket/git-utils.js +201 -0
- package/dist/server/services/websocket/git-utils.js.map +1 -0
- package/dist/server/services/websocket/handler.d.ts +2 -0
- package/dist/server/services/websocket/handler.d.ts.map +1 -1
- package/dist/server/services/websocket/handler.js +37 -112
- package/dist/server/services/websocket/handler.js.map +1 -1
- package/dist/server/services/websocket/plan-board-handlers.d.ts +11 -0
- package/dist/server/services/websocket/plan-board-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/plan-board-handlers.js +218 -0
- package/dist/server/services/websocket/plan-board-handlers.js.map +1 -0
- package/dist/server/services/websocket/plan-execution-handlers.d.ts +9 -0
- package/dist/server/services/websocket/plan-execution-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/plan-execution-handlers.js +142 -0
- package/dist/server/services/websocket/plan-execution-handlers.js.map +1 -0
- package/dist/server/services/websocket/plan-handlers.d.ts +7 -2
- package/dist/server/services/websocket/plan-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/plan-handlers.js +21 -462
- package/dist/server/services/websocket/plan-handlers.js.map +1 -1
- package/dist/server/services/websocket/plan-helpers.d.ts +19 -0
- package/dist/server/services/websocket/plan-helpers.d.ts.map +1 -0
- package/dist/server/services/websocket/plan-helpers.js +199 -0
- package/dist/server/services/websocket/plan-helpers.js.map +1 -0
- package/dist/server/services/websocket/plan-issue-handlers.d.ts +12 -0
- package/dist/server/services/websocket/plan-issue-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/plan-issue-handlers.js +162 -0
- package/dist/server/services/websocket/plan-issue-handlers.js.map +1 -0
- package/dist/server/services/websocket/plan-sprint-handlers.d.ts +7 -0
- package/dist/server/services/websocket/plan-sprint-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/plan-sprint-handlers.js +206 -0
- package/dist/server/services/websocket/plan-sprint-handlers.js.map +1 -0
- package/dist/server/services/websocket/quality-complexity.d.ts +14 -0
- package/dist/server/services/websocket/quality-complexity.d.ts.map +1 -0
- package/dist/server/services/websocket/quality-complexity.js +262 -0
- package/dist/server/services/websocket/quality-complexity.js.map +1 -0
- package/dist/server/services/websocket/quality-fix-agent.d.ts +16 -0
- package/dist/server/services/websocket/quality-fix-agent.d.ts.map +1 -0
- package/dist/server/services/websocket/quality-fix-agent.js +140 -0
- package/dist/server/services/websocket/quality-fix-agent.js.map +1 -0
- package/dist/server/services/websocket/quality-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/quality-handlers.js +34 -346
- package/dist/server/services/websocket/quality-handlers.js.map +1 -1
- package/dist/server/services/websocket/quality-linting.d.ts +9 -0
- package/dist/server/services/websocket/quality-linting.d.ts.map +1 -0
- package/dist/server/services/websocket/quality-linting.js +178 -0
- package/dist/server/services/websocket/quality-linting.js.map +1 -0
- package/dist/server/services/websocket/quality-review-agent.d.ts +19 -0
- package/dist/server/services/websocket/quality-review-agent.d.ts.map +1 -0
- package/dist/server/services/websocket/quality-review-agent.js +206 -0
- package/dist/server/services/websocket/quality-review-agent.js.map +1 -0
- package/dist/server/services/websocket/quality-service.d.ts +3 -51
- package/dist/server/services/websocket/quality-service.d.ts.map +1 -1
- package/dist/server/services/websocket/quality-service.js +9 -651
- package/dist/server/services/websocket/quality-service.js.map +1 -1
- package/dist/server/services/websocket/quality-tools.d.ts +23 -0
- package/dist/server/services/websocket/quality-tools.d.ts.map +1 -0
- package/dist/server/services/websocket/quality-tools.js +208 -0
- package/dist/server/services/websocket/quality-tools.js.map +1 -0
- package/dist/server/services/websocket/quality-types.d.ts +59 -0
- package/dist/server/services/websocket/quality-types.d.ts.map +1 -0
- package/dist/server/services/websocket/quality-types.js +101 -0
- package/dist/server/services/websocket/quality-types.js.map +1 -0
- package/dist/server/services/websocket/session-handlers.d.ts +3 -4
- package/dist/server/services/websocket/session-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/session-handlers.js +3 -378
- package/dist/server/services/websocket/session-handlers.js.map +1 -1
- package/dist/server/services/websocket/session-history.d.ts +4 -0
- package/dist/server/services/websocket/session-history.d.ts.map +1 -0
- package/dist/server/services/websocket/session-history.js +208 -0
- package/dist/server/services/websocket/session-history.js.map +1 -0
- package/dist/server/services/websocket/session-initialization.d.ts +5 -0
- package/dist/server/services/websocket/session-initialization.d.ts.map +1 -0
- package/dist/server/services/websocket/session-initialization.js +163 -0
- package/dist/server/services/websocket/session-initialization.js.map +1 -0
- package/dist/server/services/websocket/types.d.ts +12 -2
- package/dist/server/services/websocket/types.d.ts.map +1 -1
- package/package.json +1 -2
- package/server/cli/headless/claude-invoker-process.ts +204 -0
- package/server/cli/headless/claude-invoker-stall.ts +164 -0
- package/server/cli/headless/claude-invoker-stream.ts +353 -0
- package/server/cli/headless/claude-invoker-tools.ts +187 -0
- package/server/cli/headless/claude-invoker.ts +15 -1092
- package/server/cli/headless/haiku-assessments.ts +365 -0
- package/server/cli/headless/headless-logger.ts +26 -5
- package/server/cli/headless/native-timeout-detector.ts +117 -0
- package/server/cli/headless/stall-assessor.ts +65 -618
- package/server/cli/headless/types.ts +4 -1
- package/server/cli/improvisation-attachments.ts +148 -0
- package/server/cli/improvisation-retry.ts +602 -0
- package/server/cli/improvisation-session-manager.ts +140 -1349
- package/server/cli/improvisation-types.ts +98 -0
- package/server/cli/prompt-builders.ts +370 -0
- package/server/index.ts +35 -246
- package/server/mcp/bouncer-haiku.ts +182 -0
- package/server/mcp/bouncer-integration.ts +87 -248
- package/server/mcp/security-analysis.ts +217 -0
- package/server/mcp/security-audit.ts +1 -1
- package/server/mcp/security-patterns.ts +60 -283
- package/server/server-setup.ts +114 -0
- package/server/services/file-explorer-ops.ts +293 -0
- package/server/services/files.ts +20 -532
- package/server/services/plan/composer.ts +140 -35
- package/server/services/plan/config-installer.ts +187 -0
- package/server/services/plan/dependency-resolver.ts +4 -1
- package/server/services/plan/executor.ts +281 -488
- package/server/services/plan/front-matter.ts +48 -0
- package/server/services/plan/output-manager.ts +113 -0
- package/server/services/plan/parser-core.ts +406 -0
- package/server/services/plan/parser-migration.ts +128 -0
- package/server/services/plan/parser.ts +188 -394
- package/server/services/plan/prompt-builder.ts +161 -0
- package/server/services/plan/review-gate.ts +212 -0
- package/server/services/plan/state-reconciler.ts +68 -7
- package/server/services/plan/types.ts +101 -1
- package/server/services/platform-credentials.ts +83 -0
- package/server/services/platform.ts +16 -131
- package/server/services/terminal/pty-manager.ts +66 -313
- package/server/services/terminal/pty-utils.ts +176 -0
- package/server/services/websocket/file-definition-handlers.ts +165 -0
- package/server/services/websocket/file-explorer-handlers.ts +37 -452
- package/server/services/websocket/file-search-handlers.ts +291 -0
- package/server/services/websocket/file-utils.ts +3 -3
- package/server/services/websocket/git-branch-handlers.ts +130 -0
- package/server/services/websocket/git-diff-handlers.ts +140 -0
- package/server/services/websocket/git-handlers.ts +40 -625
- package/server/services/websocket/git-log-handlers.ts +149 -0
- package/server/services/websocket/git-pr-handlers.ts +17 -62
- package/server/services/websocket/git-tag-handlers.ts +91 -0
- package/server/services/websocket/git-utils.ts +230 -0
- package/server/services/websocket/handler.ts +39 -112
- package/server/services/websocket/plan-board-handlers.ts +277 -0
- package/server/services/websocket/plan-execution-handlers.ts +184 -0
- package/server/services/websocket/plan-handlers.ts +23 -544
- package/server/services/websocket/plan-helpers.ts +215 -0
- package/server/services/websocket/plan-issue-handlers.ts +204 -0
- package/server/services/websocket/plan-sprint-handlers.ts +252 -0
- package/server/services/websocket/quality-complexity.ts +294 -0
- package/server/services/websocket/quality-fix-agent.ts +181 -0
- package/server/services/websocket/quality-handlers.ts +36 -404
- package/server/services/websocket/quality-linting.ts +187 -0
- package/server/services/websocket/quality-review-agent.ts +246 -0
- package/server/services/websocket/quality-service.ts +11 -762
- package/server/services/websocket/quality-tools.ts +209 -0
- package/server/services/websocket/quality-types.ts +169 -0
- package/server/services/websocket/session-handlers.ts +5 -437
- package/server/services/websocket/session-history.ts +222 -0
- package/server/services/websocket/session-initialization.ts +209 -0
- package/server/services/websocket/types.ts +46 -2
|
@@ -12,10 +12,16 @@
|
|
|
12
12
|
* - Only truly catastrophic operations (rm -rf /, fork bombs) are auto-denied
|
|
13
13
|
* - Sensitive operations (system paths, credentials) get AI review with context
|
|
14
14
|
* - The question is: "Does this operation make sense given user intent?"
|
|
15
|
+
*
|
|
16
|
+
* Analysis logic (requiresAIReview, classifyRisk) lives in security-analysis.ts
|
|
17
|
+
* and is re-exported here for backward compatibility.
|
|
15
18
|
*/
|
|
16
19
|
|
|
17
20
|
import { resolve } from 'node:path';
|
|
18
21
|
|
|
22
|
+
// Re-export analysis functions for backward compatibility
|
|
23
|
+
export { classifyRisk, isSensitivePath, requiresAIReview } from './security-analysis.js';
|
|
24
|
+
|
|
19
25
|
export interface SecurityPattern {
|
|
20
26
|
pattern: RegExp;
|
|
21
27
|
reason?: string;
|
|
@@ -56,8 +62,6 @@ export const SENSITIVE_PATHS: SecurityPattern[] = [
|
|
|
56
62
|
* for context review. Only truly never-legitimate commands are here.
|
|
57
63
|
*/
|
|
58
64
|
export const CRITICAL_THREATS: SecurityPattern[] = [
|
|
59
|
-
// Deleting root or home - no legitimate dev task requires this
|
|
60
|
-
// If user really wants this, they can run it manually outside Claude
|
|
61
65
|
{
|
|
62
66
|
pattern: /rm\s+-rf\s+(\/|~)($|\s)/i,
|
|
63
67
|
reason: 'Deleting root (/) or home (~) directory is never a legitimate dev task'
|
|
@@ -86,7 +90,6 @@ export const CRITICAL_THREATS: SecurityPattern[] = [
|
|
|
86
90
|
pattern: /chmod\s+000\s+\//i,
|
|
87
91
|
reason: 'Attempting to make system directories inaccessible'
|
|
88
92
|
},
|
|
89
|
-
// Reverse shells - never legitimate in a dev workflow
|
|
90
93
|
{
|
|
91
94
|
pattern: /\/dev\/tcp\//i,
|
|
92
95
|
reason: 'Reverse shell via /dev/tcp - classic backdoor technique'
|
|
@@ -95,8 +98,6 @@ export const CRITICAL_THREATS: SecurityPattern[] = [
|
|
|
95
98
|
pattern: /\bnc\b.*-[elp].*\b\d+\b/i,
|
|
96
99
|
reason: 'Netcat listener/reverse shell - common backdoor technique'
|
|
97
100
|
},
|
|
98
|
-
// NOTE: curl|bash is NOT here - it goes to Haiku for context review
|
|
99
|
-
// The question is "did a bad actor inject this?" not "is curl|bash dangerous?"
|
|
100
101
|
];
|
|
101
102
|
|
|
102
103
|
/**
|
|
@@ -109,15 +110,13 @@ export const SAFE_OPERATIONS: SecurityPattern[] = [
|
|
|
109
110
|
{ pattern: /^Glob:/i },
|
|
110
111
|
{ pattern: /^Grep:/i },
|
|
111
112
|
|
|
112
|
-
// Write/Edit to user home directory or subdirectories
|
|
113
|
-
|
|
114
|
-
{ pattern: /^
|
|
115
|
-
{ pattern: /^
|
|
116
|
-
{ pattern: /^
|
|
117
|
-
{ pattern: /^Edit:\s*\/home\/[^/]+\//i }, // Linux home dirs - Edit
|
|
113
|
+
// Write/Edit to user home directory or subdirectories
|
|
114
|
+
{ pattern: /^Write:\s*\/Users\/[^/]+\//i },
|
|
115
|
+
{ pattern: /^Edit:\s*\/Users\/[^/]+\//i },
|
|
116
|
+
{ pattern: /^Write:\s*\/home\/[^/]+\//i },
|
|
117
|
+
{ pattern: /^Edit:\s*\/home\/[^/]+\//i },
|
|
118
118
|
|
|
119
119
|
// Safe bash commands - common development workflows
|
|
120
|
-
// NOTE: curl|bash goes to Haiku for context review, not auto-allowed
|
|
121
120
|
{ pattern: /^Bash:\s*(npm|yarn|pnpm|bun)\s+(install|ci|run|test|build|dev|start|lint|format)($|\s)/i },
|
|
122
121
|
{ pattern: /^Bash:\s*git\s+(status|log|diff|show|branch|clone|pull|fetch|add|stash|checkout)($|\s)/i },
|
|
123
122
|
{ pattern: /^Bash:\s*docker\s+(build|run|ps|logs|compose|images)($|\s)/i },
|
|
@@ -133,22 +132,42 @@ export const SAFE_OPERATIONS: SecurityPattern[] = [
|
|
|
133
132
|
{ pattern: /^Bash:\s*rm\s+-rf\s+(\.\/)?target($|\s)/i },
|
|
134
133
|
{ pattern: /^Bash:\s*rm\s+-rf\s+(\.\/)?__pycache__($|\s)/i },
|
|
135
134
|
|
|
136
|
-
// Write/Edit to temp directories
|
|
135
|
+
// Write/Edit to temp directories
|
|
137
136
|
{ pattern: /^(Write|Edit):\s*\/tmp\//i },
|
|
138
137
|
{ pattern: /^(Write|Edit):\s*\/var\/tmp\//i },
|
|
139
138
|
|
|
140
|
-
// Side-effect-free tools
|
|
139
|
+
// Side-effect-free tools
|
|
141
140
|
{ pattern: /^(ExitPlanMode|EnterPlanMode|TodoWrite|AskUserQuestion):/i },
|
|
141
|
+
|
|
142
|
+
// Additional common dev commands
|
|
143
|
+
{ pattern: /^Bash:\s*(tsc|tsx|node|bun|deno|npx|bunx)\s/i },
|
|
144
|
+
{ pattern: /^Bash:\s*(vitest|jest|mocha|tap)\s/i },
|
|
145
|
+
{ pattern: /^Bash:\s*(biome|eslint|prettier|tslint)\s+(check|lint|format)/i },
|
|
146
|
+
{ pattern: /^Bash:\s*(make|cmake|ninja|meson)($|\s)/i },
|
|
147
|
+
{ pattern: /^Bash:\s*git\s+(commit|push|tag|remote|rebase|merge|cherry-pick|reset|revert)($|\s)/i },
|
|
148
|
+
{ pattern: /^Bash:\s*git\s+(worktree|submodule|config|clean|gc)($|\s)/i },
|
|
149
|
+
{ pattern: /^Bash:\s*(uname|hostname|whoami|id|groups|uptime|df|du|free|top|ps|lsof|stat|file|readlink)($|\s)/i },
|
|
150
|
+
{ pattern: /^Bash:\s*(mv|cp|touch|ln|basename|dirname|realpath|mktemp|xargs|tee|tr|cut|paste|comm|diff|patch)($|\s)/i },
|
|
151
|
+
{ pattern: /^Bash:\s*(tar|gzip|gunzip|zip|unzip|bzip2)\s/i },
|
|
152
|
+
{ pattern: /^Bash:\s*(ruby|python3?|php|java|javac|scala|kotlinc|swift|rustc|gcc|g\+\+|clang)\s/i },
|
|
153
|
+
{ pattern: /^Bash:\s*(pip|pip3|gem|bundle|composer|maven|gradle|sbt|cargo|rustup)\s/i },
|
|
154
|
+
{ pattern: /^Bash:\s*(gh|hub)\s+(pr|issue|repo|release|run|api)\s/i },
|
|
155
|
+
{ pattern: /^Bash:\s*(flyctl|fly)\s+(status|logs|ssh|deploy|apps|machines|secrets)($|\s)/i },
|
|
156
|
+
{ pattern: /^Bash:\s*(terraform|tofu)\s+(init|plan|apply|validate|fmt|show|output)($|\s)/i },
|
|
157
|
+
{ pattern: /^Bash:\s*wc($|\s)/i },
|
|
158
|
+
|
|
159
|
+
// WebFetch/WebSearch are inherently read-only
|
|
160
|
+
{ pattern: /^WebFetch:/i },
|
|
161
|
+
{ pattern: /^WebSearch:/i },
|
|
162
|
+
|
|
163
|
+
// Agent and NotebookEdit are orchestration-only
|
|
164
|
+
{ pattern: /^Agent:/i },
|
|
165
|
+
{ pattern: /^NotebookEdit:/i },
|
|
142
166
|
];
|
|
143
167
|
|
|
144
168
|
/**
|
|
145
169
|
* Patterns that trigger AI context review
|
|
146
170
|
* These operations need context analysis to determine if they align with user intent
|
|
147
|
-
*
|
|
148
|
-
* The AI should consider:
|
|
149
|
-
* 1. Did the user explicitly request this operation?
|
|
150
|
-
* 2. Does it make sense given the task at hand?
|
|
151
|
-
* 3. Is the content/action appropriate for the target?
|
|
152
171
|
*/
|
|
153
172
|
export const NEEDS_AI_REVIEW: SecurityPattern[] = [
|
|
154
173
|
// Remote code execution patterns
|
|
@@ -158,103 +177,57 @@ export const NEEDS_AI_REVIEW: SecurityPattern[] = [
|
|
|
158
177
|
},
|
|
159
178
|
|
|
160
179
|
// Elevated privileges
|
|
161
|
-
{
|
|
162
|
-
pattern: /sudo/i,
|
|
163
|
-
reason: 'Elevated privileges - verify user intended this action'
|
|
164
|
-
},
|
|
180
|
+
{ pattern: /sudo/i, reason: 'Elevated privileges - verify user intended this action' },
|
|
165
181
|
|
|
166
182
|
// Destructive operations (except safe build artifact cleanup)
|
|
167
|
-
{
|
|
168
|
-
pattern: /rm\s+-rf/i,
|
|
169
|
-
reason: 'Recursive deletion - verify target matches user intent'
|
|
170
|
-
},
|
|
183
|
+
{ pattern: /rm\s+-rf/i, reason: 'Recursive deletion - verify target matches user intent' },
|
|
171
184
|
|
|
172
|
-
// Data exfiltration patterns
|
|
173
|
-
{
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
pattern: /\bscp\b.*@/i,
|
|
179
|
-
reason: 'SCP to remote host - potential data exfiltration'
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
pattern: /\|\s*curl\b/i,
|
|
183
|
-
reason: 'Pipe to curl - potential data exfiltration'
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
pattern: /curl\b.*-d\s*@/i,
|
|
187
|
-
reason: 'Curl with file upload - potential data exfiltration'
|
|
188
|
-
},
|
|
185
|
+
// Data exfiltration patterns
|
|
186
|
+
{ pattern: /\|\s*(nc|netcat|ncat)\b/i, reason: 'Pipe to netcat - potential data exfiltration' },
|
|
187
|
+
{ pattern: /\bscp\b.*@/i, reason: 'SCP to remote host - potential data exfiltration' },
|
|
188
|
+
{ pattern: /\|\s*curl\b/i, reason: 'Pipe to curl - potential data exfiltration' },
|
|
189
|
+
{ pattern: /curl\b.*-d\s*@/i, reason: 'Curl with file upload - potential data exfiltration' },
|
|
189
190
|
|
|
190
191
|
// ALL Write/Edit operations that aren't to /tmp go through context review
|
|
191
|
-
// This is the key change: we review based on context, not blanket allow/deny
|
|
192
192
|
{
|
|
193
193
|
pattern: /^(Write|Edit):\s*(?!\/tmp\/|\/var\/tmp\/)/i,
|
|
194
194
|
reason: 'File modification - verify aligns with user request'
|
|
195
195
|
},
|
|
196
196
|
|
|
197
|
-
// Reverse shells and bind shells
|
|
198
|
-
{
|
|
199
|
-
|
|
200
|
-
reason: 'Potential reverse shell via /dev/tcp'
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
pattern: /\b(nc|netcat|ncat)\b.*-e\s/i,
|
|
204
|
-
reason: 'Netcat with -e flag - potential reverse shell'
|
|
205
|
-
},
|
|
197
|
+
// Reverse shells and bind shells
|
|
198
|
+
{ pattern: /\/dev\/tcp\//i, reason: 'Potential reverse shell via /dev/tcp' },
|
|
199
|
+
{ pattern: /\b(nc|netcat|ncat)\b.*-e\s/i, reason: 'Netcat with -e flag - potential reverse shell' },
|
|
206
200
|
{
|
|
207
201
|
pattern: /\bsocket\b.*\bconnect\b.*\b(dup2|subprocess|exec)\b/i,
|
|
208
202
|
reason: 'Programmatic reverse shell pattern (socket+connect+exec)'
|
|
209
203
|
},
|
|
210
|
-
{
|
|
211
|
-
pattern: /\bperl\b.*\bsocket\b.*\bexec\b/i,
|
|
212
|
-
reason: 'Perl reverse shell pattern'
|
|
213
|
-
},
|
|
204
|
+
{ pattern: /\bperl\b.*\bsocket\b.*\bexec\b/i, reason: 'Perl reverse shell pattern' },
|
|
214
205
|
|
|
215
206
|
// Encoded/obfuscated payloads piped to shell or eval
|
|
216
207
|
{
|
|
217
208
|
pattern: /\b(base64|base32)\b.*-d.*\|\s*(bash|sh)\b/i,
|
|
218
209
|
reason: 'Decoded payload piped to shell - obfuscated command execution'
|
|
219
210
|
},
|
|
220
|
-
{
|
|
221
|
-
|
|
222
|
-
reason: 'Hex-encoded payload piped to shell'
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
pattern: /\bexec\b.*\b(base64|b64decode)\b/i,
|
|
226
|
-
reason: 'Exec with base64 decoding - obfuscated code execution'
|
|
227
|
-
},
|
|
211
|
+
{ pattern: /\\x[0-9a-f]{2}.*\|\s*(bash|sh)\b/i, reason: 'Hex-encoded payload piped to shell' },
|
|
212
|
+
{ pattern: /\bexec\b.*\b(base64|b64decode)\b/i, reason: 'Exec with base64 decoding - obfuscated code execution' },
|
|
228
213
|
{
|
|
229
214
|
pattern: /\bprintf\b.*\\x[0-9a-f].*\|\s*(bash|sh)\b/i,
|
|
230
215
|
reason: 'Printf hex payload piped to shell'
|
|
231
216
|
},
|
|
232
217
|
|
|
233
|
-
// Cloud metadata / SSRF
|
|
234
|
-
{
|
|
235
|
-
|
|
236
|
-
reason: 'AWS/Azure IMDS access - potential credential theft'
|
|
237
|
-
},
|
|
238
|
-
{
|
|
239
|
-
pattern: /metadata\.google\.internal/i,
|
|
240
|
-
reason: 'GCP metadata access - potential credential theft'
|
|
241
|
-
},
|
|
218
|
+
// Cloud metadata / SSRF
|
|
219
|
+
{ pattern: /169\.254\.169\.254/i, reason: 'AWS/Azure IMDS access - potential credential theft' },
|
|
220
|
+
{ pattern: /metadata\.google\.internal/i, reason: 'GCP metadata access - potential credential theft' },
|
|
242
221
|
|
|
243
|
-
// Persistence
|
|
222
|
+
// Persistence mechanisms
|
|
244
223
|
{
|
|
245
224
|
pattern: />>\s*~?\/?.*\/(authorized_keys|\.bashrc|\.bash_profile|\.zshrc|\.profile)/i,
|
|
246
225
|
reason: 'Appending to sensitive file - potential persistence mechanism'
|
|
247
226
|
},
|
|
248
|
-
{
|
|
249
|
-
pattern: /\bld\.so\.preload\b/i,
|
|
250
|
-
reason: 'LD_PRELOAD injection - shared library hijacking'
|
|
251
|
-
},
|
|
227
|
+
{ pattern: /\bld\.so\.preload\b/i, reason: 'LD_PRELOAD injection - shared library hijacking' },
|
|
252
228
|
|
|
253
229
|
// wget with file upload
|
|
254
|
-
{
|
|
255
|
-
pattern: /wget\b.*--post-file/i,
|
|
256
|
-
reason: 'wget file upload - potential data exfiltration'
|
|
257
|
-
},
|
|
230
|
+
{ pattern: /wget\b.*--post-file/i, reason: 'wget file upload - potential data exfiltration' },
|
|
258
231
|
|
|
259
232
|
// pip install from custom index (supply chain attack)
|
|
260
233
|
{
|
|
@@ -263,12 +236,11 @@ export const NEEDS_AI_REVIEW: SecurityPattern[] = [
|
|
|
263
236
|
},
|
|
264
237
|
|
|
265
238
|
// MCP server manipulation
|
|
266
|
-
{
|
|
267
|
-
pattern: /\bclaude\b.*\bmcp\b.*\badd\b/i,
|
|
268
|
-
reason: 'Adding MCP server - verify source is trusted'
|
|
269
|
-
},
|
|
239
|
+
{ pattern: /\bclaude\b.*\bmcp\b.*\badd\b/i, reason: 'Adding MCP server - verify source is trusted' },
|
|
270
240
|
];
|
|
271
241
|
|
|
242
|
+
// ── Utility functions ─────────────────────────────────────────
|
|
243
|
+
|
|
272
244
|
/**
|
|
273
245
|
* Check if operation matches any pattern in array
|
|
274
246
|
*/
|
|
@@ -295,198 +267,3 @@ export function normalizeOperation(operation: string): string {
|
|
|
295
267
|
}
|
|
296
268
|
return operation;
|
|
297
269
|
}
|
|
298
|
-
|
|
299
|
-
/** Check if a Bash command contains chain operators that could hide dangerous ops after a safe prefix. */
|
|
300
|
-
function containsChainOperators(operation: string): boolean {
|
|
301
|
-
const commandPart = operation.replace(/^Bash:\s*/i, '');
|
|
302
|
-
return /;|&&|\|\||\n/.test(commandPart);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/** Check if a Bash command pipes output to known exfiltration/network tools or shells. */
|
|
306
|
-
function containsDangerousPipe(operation: string): boolean {
|
|
307
|
-
const commandPart = operation.replace(/^Bash:\s*/i, '');
|
|
308
|
-
return /\|\s*(nc|netcat|ncat|curl|wget|scp|bash|sh)\b/i.test(commandPart);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/** Check if a Bash command redirects output to sensitive paths (append or overwrite). */
|
|
312
|
-
function containsSensitiveRedirect(operation: string): boolean {
|
|
313
|
-
const commandPart = operation.replace(/^Bash:\s*/i, '');
|
|
314
|
-
return />>?\s*~?\/?.*\/(authorized_keys|\.bashrc|\.bash_profile|\.zshrc|\.profile|\.ssh\/|\.aws\/|\.gnupg\/|ld\.so\.preload|crontab|sudoers)/i.test(commandPart)
|
|
315
|
-
|| />>?\s*\/etc\//i.test(commandPart);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/** Check if a Bash command contains subshell or backtick expansion (not simple ${VAR}). */
|
|
319
|
-
function containsBashExpansion(operation: string): boolean {
|
|
320
|
-
const commandPart = operation.replace(/^Bash:\s*/i, '');
|
|
321
|
-
return /`[^`]+`/.test(commandPart) || /\$\([^)]+\)/.test(commandPart);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
/** Check if a Bash command contains any form of shell expansion: ${VAR}, $(...), or backticks. */
|
|
325
|
-
function containsAnyExpansion(operation: string): boolean {
|
|
326
|
-
const cmd = operation.replace(/^Bash:\s*/i, '');
|
|
327
|
-
return /\$\{[^}]+\}/.test(cmd) || /\$\([^)]+\)/.test(cmd) || /`[^`]+`/.test(cmd);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
/** Check if expansion is safely used as an argument to a known-safe command prefix.
|
|
331
|
-
* e.g., "echo ${HOME}" or "cat ${FILE}" — the expansion can't change the command itself. */
|
|
332
|
-
function isSafeExpansionUse(operation: string): boolean {
|
|
333
|
-
const cmd = operation.replace(/^Bash:\s*/i, '').trim();
|
|
334
|
-
// If the expansion IS the command (first token), it's never safe
|
|
335
|
-
if (/^(\$\{|\$\(|`)/.test(cmd)) return false;
|
|
336
|
-
// Safe command prefixes where expansion as an argument is harmless
|
|
337
|
-
const safePrefix = /^(echo|printf|cat|ls|pwd|whoami|date|env|printenv|test|true|false)\s/i;
|
|
338
|
-
return safePrefix.test(cmd);
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* Determine if operation requires AI context review
|
|
343
|
-
*
|
|
344
|
-
* The philosophy here is:
|
|
345
|
-
* - SENSITIVE_PATHS: Always require review (credentials, system configs)
|
|
346
|
-
* - SAFE_OPERATIONS: No review needed, UNLESS the bash command contains
|
|
347
|
-
* chain operators, dangerous pipes, or subshell/backtick expansion
|
|
348
|
-
* - CRITICAL_THREATS: Auto-deny, no review (catastrophic operations)
|
|
349
|
-
* - Everything else: AI reviews context to determine if it matches user intent
|
|
350
|
-
*/
|
|
351
|
-
const SAFE_RM_PATTERNS = [
|
|
352
|
-
/rm\s+-rf\s+(\.\/)?node_modules($|\s)/i,
|
|
353
|
-
/rm\s+-rf\s+(\.\/)?dist($|\s)/i,
|
|
354
|
-
/rm\s+-rf\s+(\.\/)?build($|\s)/i,
|
|
355
|
-
/rm\s+-rf\s+(\.\/)?\.cache($|\s)/i,
|
|
356
|
-
/rm\s+-rf\s+(\.\/)?\.next($|\s)/i,
|
|
357
|
-
/rm\s+-rf\s+(\.\/)?target($|\s)/i,
|
|
358
|
-
/rm\s+-rf\s+(\.\/)?__pycache__($|\s)/i,
|
|
359
|
-
];
|
|
360
|
-
|
|
361
|
-
export function requiresAIReview(operation: string): boolean {
|
|
362
|
-
// Normalize paths to prevent .. traversal bypass
|
|
363
|
-
const op = normalizeOperation(operation);
|
|
364
|
-
|
|
365
|
-
// Check sensitive paths BEFORE safe operations — prevents home-dir
|
|
366
|
-
// safe pattern from masking .ssh, .aws, .bashrc, etc.
|
|
367
|
-
if (matchesPattern(op, SENSITIVE_PATHS)) return true;
|
|
368
|
-
|
|
369
|
-
// Bash commands with any shell expansion (${VAR}, $(...), backticks) are
|
|
370
|
-
// opaque — the bouncer can't predict what they expand to at runtime.
|
|
371
|
-
// Route to AI review BEFORE checking CRITICAL_THREATS or SAFE_OPERATIONS,
|
|
372
|
-
// UNLESS the command is clearly safe (expansion is just an argument to a
|
|
373
|
-
// known-safe prefix like "echo ${HOME}").
|
|
374
|
-
if (/^Bash:/i.test(op) && containsAnyExpansion(op) && !isSafeExpansionUse(op)) {
|
|
375
|
-
return true;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
if (matchesPattern(op, SAFE_OPERATIONS)) {
|
|
379
|
-
// Safe bash commands must not contain chain operators, dangerous pipes,
|
|
380
|
-
// or subshell/backtick expansion that could hide dangerous operations.
|
|
381
|
-
// A safe prefix (e.g., "git clone") with chain operators (&&, ;, ||)
|
|
382
|
-
// means the full command isn't necessarily safe — route to AI review.
|
|
383
|
-
if (/^Bash:/i.test(op) && (
|
|
384
|
-
containsChainOperators(op) ||
|
|
385
|
-
containsDangerousPipe(op) ||
|
|
386
|
-
containsBashExpansion(op) ||
|
|
387
|
-
containsSensitiveRedirect(op)
|
|
388
|
-
)) {
|
|
389
|
-
return true;
|
|
390
|
-
}
|
|
391
|
-
return false;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
if (matchesPattern(op, CRITICAL_THREATS)) return false;
|
|
395
|
-
|
|
396
|
-
if (matchesPattern(op, NEEDS_AI_REVIEW)) {
|
|
397
|
-
return !SAFE_RM_PATTERNS.some(p => p.test(op));
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
// Glob patterns and script execution are concerning in Bash commands
|
|
401
|
-
if (/^Bash:/.test(op)) {
|
|
402
|
-
if (/\*\*?/.test(op)) return true;
|
|
403
|
-
if (/^Bash:\s*\.\//.test(op)) return true;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
return false;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
/**
|
|
410
|
-
* Check if operation targets a sensitive path
|
|
411
|
-
* Used to provide additional context to AI reviewer
|
|
412
|
-
*/
|
|
413
|
-
export function isSensitivePath(operation: string): SecurityPattern | null {
|
|
414
|
-
return matchesPattern(operation, SENSITIVE_PATHS);
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
* Classify operation risk level for context-aware review
|
|
419
|
-
*
|
|
420
|
-
* Risk levels indicate how much scrutiny the AI should apply:
|
|
421
|
-
* - critical: Catastrophic if wrong (rm -rf /, fork bombs) - auto-deny
|
|
422
|
-
* - high: Needs clear user intent (sudo, sensitive paths, credentials)
|
|
423
|
-
* - medium: Normal file operations - verify matches user request
|
|
424
|
-
* - low: Safe operations - minimal review needed
|
|
425
|
-
*/
|
|
426
|
-
export function classifyRisk(operation: string): {
|
|
427
|
-
isDestructive: boolean;
|
|
428
|
-
riskLevel: 'low' | 'medium' | 'high' | 'critical';
|
|
429
|
-
reasons: string[];
|
|
430
|
-
} {
|
|
431
|
-
// Critical threats are auto-denied
|
|
432
|
-
const criticalThreat = matchesPattern(operation, CRITICAL_THREATS);
|
|
433
|
-
if (criticalThreat) {
|
|
434
|
-
return {
|
|
435
|
-
isDestructive: true,
|
|
436
|
-
riskLevel: 'critical',
|
|
437
|
-
reasons: [criticalThreat.reason || 'Critical threat detected']
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
// Sensitive paths need high scrutiny but aren't auto-denied
|
|
442
|
-
const sensitivePath = matchesPattern(operation, SENSITIVE_PATHS);
|
|
443
|
-
if (sensitivePath) {
|
|
444
|
-
return {
|
|
445
|
-
isDestructive: false, // Not inherently destructive, just sensitive
|
|
446
|
-
riskLevel: 'high',
|
|
447
|
-
reasons: [sensitivePath.reason || 'Sensitive path - requires clear user intent']
|
|
448
|
-
};
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
// Other patterns that need elevated review
|
|
452
|
-
const elevatedPatterns: SecurityPattern[] = [
|
|
453
|
-
{ pattern: /sudo/i, reason: 'Elevated privileges requested' },
|
|
454
|
-
{ pattern: /DROP\s+(TABLE|DATABASE)/i, reason: 'Database deletion' },
|
|
455
|
-
{ pattern: /chmod\s+777/i, reason: 'Dangerous permissions' },
|
|
456
|
-
{ pattern: /(curl|wget).*\|.*(bash|sh)/i, reason: 'Remote code execution' },
|
|
457
|
-
{ pattern: /pkill|killall/i, reason: 'Process termination' },
|
|
458
|
-
{ pattern: /\|\s*(nc|netcat|ncat)\b/i, reason: 'Data exfiltration via netcat' },
|
|
459
|
-
{ pattern: /\bscp\b.*@/i, reason: 'Data exfiltration via SCP' },
|
|
460
|
-
{ pattern: /curl\b.*-d\s*@/i, reason: 'Data exfiltration via curl file upload' },
|
|
461
|
-
];
|
|
462
|
-
|
|
463
|
-
for (const pattern of elevatedPatterns) {
|
|
464
|
-
if (pattern.pattern.test(operation)) {
|
|
465
|
-
return {
|
|
466
|
-
isDestructive: true,
|
|
467
|
-
riskLevel: 'high',
|
|
468
|
-
reasons: [pattern.reason || 'Elevated risk operation']
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
// Medium risk: only recursive deletions outside safe dirs
|
|
474
|
-
// NOTE: Write/Edit are NOT flagged as risky - they're normal dev operations
|
|
475
|
-
if (/rm\s+-rf/i.test(operation)) {
|
|
476
|
-
// Check if it's actually safe (build artifacts, temp)
|
|
477
|
-
if (matchesPattern(operation, SAFE_OPERATIONS)) {
|
|
478
|
-
return { isDestructive: false, riskLevel: 'low', reasons: [] };
|
|
479
|
-
}
|
|
480
|
-
return {
|
|
481
|
-
isDestructive: true,
|
|
482
|
-
riskLevel: 'medium',
|
|
483
|
-
reasons: ['Recursive deletion']
|
|
484
|
-
};
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
return {
|
|
488
|
-
isDestructive: false,
|
|
489
|
-
riskLevel: 'low',
|
|
490
|
-
reasons: []
|
|
491
|
-
};
|
|
492
|
-
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// Copyright (c) 2025-present Mstro, Inc. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License. See LICENSE file for details.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Server Setup Utilities — Helpers for the main server entry point.
|
|
6
|
+
*
|
|
7
|
+
* - ensureClaudeSettings: Ensures .claude/settings.json has recommended defaults
|
|
8
|
+
* - wrapWebSocket / createPlatformRelayContext: WSContext adapters
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
12
|
+
import { basename, join } from 'node:path'
|
|
13
|
+
import type { WebSocket as NodeWebSocket } from 'ws'
|
|
14
|
+
import type { WSContext } from './services/websocket/types.js'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Set the terminal tab title
|
|
18
|
+
* Format: "mstro: directory_name"
|
|
19
|
+
*/
|
|
20
|
+
export function setTerminalTitle(directory: string): void {
|
|
21
|
+
const dirName = basename(directory) || directory
|
|
22
|
+
const title = `mstro: ${dirName}`
|
|
23
|
+
process.stdout.write(`\x1b]0;${title}\x07`)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Ensure .claude/settings.json exists with recommended settings
|
|
28
|
+
* for optimal Claude Code performance with Mstro
|
|
29
|
+
*/
|
|
30
|
+
export function ensureClaudeSettings(workingDir: string): void {
|
|
31
|
+
const claudeDir = join(workingDir, '.claude')
|
|
32
|
+
const settingsPath = join(claudeDir, 'settings.json')
|
|
33
|
+
|
|
34
|
+
if (!existsSync(claudeDir)) {
|
|
35
|
+
mkdirSync(claudeDir, { recursive: true })
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const recommendedSettings = {
|
|
39
|
+
env: {
|
|
40
|
+
CLAUDE_CODE_MAX_OUTPUT_TOKENS: "64000",
|
|
41
|
+
DISABLE_NONESSENTIAL_TRAFFIC: "1"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!existsSync(settingsPath)) {
|
|
46
|
+
writeFileSync(settingsPath, JSON.stringify(recommendedSettings, null, 2))
|
|
47
|
+
console.log(`📝 Created .claude/settings.json with recommended settings`)
|
|
48
|
+
} else {
|
|
49
|
+
try {
|
|
50
|
+
const existingSettings = JSON.parse(readFileSync(settingsPath, 'utf-8'))
|
|
51
|
+
let updated = false
|
|
52
|
+
|
|
53
|
+
if (!existingSettings.env) {
|
|
54
|
+
existingSettings.env = {}
|
|
55
|
+
updated = true
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (!existingSettings.env.CLAUDE_CODE_MAX_OUTPUT_TOKENS) {
|
|
59
|
+
existingSettings.env.CLAUDE_CODE_MAX_OUTPUT_TOKENS = "64000"
|
|
60
|
+
updated = true
|
|
61
|
+
}
|
|
62
|
+
if (!existingSettings.env.DISABLE_NONESSENTIAL_TRAFFIC) {
|
|
63
|
+
existingSettings.env.DISABLE_NONESSENTIAL_TRAFFIC = "1"
|
|
64
|
+
updated = true
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (updated) {
|
|
68
|
+
writeFileSync(settingsPath, JSON.stringify(existingSettings, null, 2))
|
|
69
|
+
console.log(`📝 Updated .claude/settings.json with recommended env settings`)
|
|
70
|
+
}
|
|
71
|
+
} catch (_e) {
|
|
72
|
+
console.warn(`⚠️ Could not parse existing .claude/settings.json, skipping update`)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Wrap a ws WebSocket to match our WSContext interface
|
|
79
|
+
*/
|
|
80
|
+
export function wrapWebSocket(ws: NodeWebSocket, workingDir: string): WSContext {
|
|
81
|
+
return {
|
|
82
|
+
send: (data: string | Buffer) => ws.send(data),
|
|
83
|
+
close: () => ws.close(),
|
|
84
|
+
readyState: ws.readyState,
|
|
85
|
+
_workingDir: workingDir,
|
|
86
|
+
_ws: ws
|
|
87
|
+
} as WSContext
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Create a virtual WebSocket context that sends responses through the platform relay.
|
|
92
|
+
* This allows messages from the web (via platform) to be handled by the same wsHandler.
|
|
93
|
+
*/
|
|
94
|
+
export function createPlatformRelayContext(
|
|
95
|
+
platformSend: (message: unknown) => void,
|
|
96
|
+
workingDir: string
|
|
97
|
+
): WSContext {
|
|
98
|
+
return {
|
|
99
|
+
send: (data: string | Buffer) => {
|
|
100
|
+
try {
|
|
101
|
+
const response = typeof data === 'string' ? JSON.parse(data) : JSON.parse(data.toString())
|
|
102
|
+
platformSend(response)
|
|
103
|
+
} catch (e) {
|
|
104
|
+
console.error('[PlatformRelay] Failed to parse response:', e)
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
close: () => {
|
|
108
|
+
// No-op for platform relay
|
|
109
|
+
},
|
|
110
|
+
readyState: 1, // WebSocket.OPEN
|
|
111
|
+
_workingDir: workingDir,
|
|
112
|
+
_isPlatformRelay: true
|
|
113
|
+
} as WSContext
|
|
114
|
+
}
|