mstro-app 0.4.20 → 0.4.22
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/README.md +66 -0
- package/dist/server/cli/headless/claude-invoker-process.js +1 -1
- package/dist/server/cli/headless/claude-invoker-process.js.map +1 -1
- package/dist/server/cli/headless/headless-logger.js +1 -1
- package/dist/server/cli/headless/headless-logger.js.map +1 -1
- package/dist/server/cli/headless/mcp-config.d.ts +1 -1
- package/dist/server/cli/headless/mcp-config.d.ts.map +1 -1
- package/dist/server/cli/headless/mcp-config.js +4 -1
- package/dist/server/cli/headless/mcp-config.js.map +1 -1
- package/dist/server/cli/headless/runner.d.ts.map +1 -1
- package/dist/server/cli/headless/runner.js +1 -0
- package/dist/server/cli/headless/runner.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/index.js +9 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/bouncer-integration.d.ts +2 -2
- package/dist/server/mcp/bouncer-integration.d.ts.map +1 -1
- package/dist/server/mcp/bouncer-integration.js +20 -20
- package/dist/server/mcp/bouncer-integration.js.map +1 -1
- package/dist/server/mcp/security-analysis.d.ts +6 -0
- package/dist/server/mcp/security-analysis.d.ts.map +1 -1
- package/dist/server/mcp/security-analysis.js +16 -1
- package/dist/server/mcp/security-analysis.js.map +1 -1
- package/dist/server/mcp/security-patterns.d.ts +8 -0
- package/dist/server/mcp/security-patterns.d.ts.map +1 -1
- package/dist/server/mcp/security-patterns.js +47 -2
- package/dist/server/mcp/security-patterns.js.map +1 -1
- package/dist/server/services/deploy/ai-broker.d.ts +63 -0
- package/dist/server/services/deploy/ai-broker.d.ts.map +1 -0
- package/dist/server/services/deploy/ai-broker.js +360 -0
- package/dist/server/services/deploy/ai-broker.js.map +1 -0
- package/dist/server/services/deploy/board-execution-handler.d.ts +114 -0
- package/dist/server/services/deploy/board-execution-handler.d.ts.map +1 -0
- package/dist/server/services/deploy/board-execution-handler.js +621 -0
- package/dist/server/services/deploy/board-execution-handler.js.map +1 -0
- package/dist/server/services/deploy/credentials.d.ts +35 -0
- package/dist/server/services/deploy/credentials.d.ts.map +1 -0
- package/dist/server/services/deploy/credentials.js +177 -0
- package/dist/server/services/deploy/credentials.js.map +1 -0
- package/dist/server/services/deploy/deploy-ai-service.d.ts +107 -0
- package/dist/server/services/deploy/deploy-ai-service.d.ts.map +1 -0
- package/dist/server/services/deploy/deploy-ai-service.js +294 -0
- package/dist/server/services/deploy/deploy-ai-service.js.map +1 -0
- package/dist/server/services/deploy/headless-session-handler.d.ts +94 -0
- package/dist/server/services/deploy/headless-session-handler.d.ts.map +1 -0
- package/dist/server/services/deploy/headless-session-handler.js +274 -0
- package/dist/server/services/deploy/headless-session-handler.js.map +1 -0
- package/dist/server/services/pathUtils.d.ts.map +1 -1
- package/dist/server/services/pathUtils.js +33 -1
- package/dist/server/services/pathUtils.js.map +1 -1
- package/dist/server/services/plan/agent-loader.d.ts +10 -0
- package/dist/server/services/plan/agent-loader.d.ts.map +1 -0
- package/dist/server/services/plan/agent-loader.js +65 -0
- package/dist/server/services/plan/agent-loader.js.map +1 -0
- package/dist/server/services/plan/composer.d.ts.map +1 -1
- package/dist/server/services/plan/composer.js +5 -1
- package/dist/server/services/plan/composer.js.map +1 -1
- package/dist/server/services/plan/dependency-resolver.d.ts +1 -1
- package/dist/server/services/plan/dependency-resolver.js +2 -2
- package/dist/server/services/plan/dependency-resolver.js.map +1 -1
- package/dist/server/services/plan/executor.d.ts +7 -3
- package/dist/server/services/plan/executor.d.ts.map +1 -1
- package/dist/server/services/plan/executor.js +27 -14
- package/dist/server/services/plan/executor.js.map +1 -1
- package/dist/server/services/plan/front-matter.d.ts +5 -0
- package/dist/server/services/plan/front-matter.d.ts.map +1 -1
- package/dist/server/services/plan/front-matter.js +19 -0
- package/dist/server/services/plan/front-matter.js.map +1 -1
- package/dist/server/services/plan/issue-prompt-builder.d.ts +1 -1
- package/dist/server/services/plan/issue-prompt-builder.d.ts.map +1 -1
- package/dist/server/services/plan/issue-prompt-builder.js +1 -1
- package/dist/server/services/plan/issue-retry.d.ts +25 -0
- package/dist/server/services/plan/issue-retry.d.ts.map +1 -0
- package/dist/server/services/plan/issue-retry.js +216 -0
- package/dist/server/services/plan/issue-retry.js.map +1 -0
- package/dist/server/services/plan/output-manager.d.ts +2 -2
- package/dist/server/services/plan/output-manager.js +2 -2
- package/dist/server/services/plan/parser-core.d.ts +1 -1
- package/dist/server/services/plan/parser-core.js +1 -1
- package/dist/server/services/plan/parser-core.js.map +1 -1
- package/dist/server/services/plan/parser-migration.d.ts +2 -2
- package/dist/server/services/plan/parser-migration.d.ts.map +1 -1
- package/dist/server/services/plan/parser-migration.js +5 -5
- package/dist/server/services/plan/parser-migration.js.map +1 -1
- package/dist/server/services/plan/parser.d.ts.map +1 -1
- package/dist/server/services/plan/parser.js +4 -7
- package/dist/server/services/plan/parser.js.map +1 -1
- package/dist/server/services/plan/prompt-builder.d.ts +1 -1
- package/dist/server/services/plan/prompt-builder.d.ts.map +1 -1
- package/dist/server/services/plan/review-gate.d.ts +4 -0
- package/dist/server/services/plan/review-gate.d.ts.map +1 -1
- package/dist/server/services/plan/review-gate.js +90 -35
- package/dist/server/services/plan/review-gate.js.map +1 -1
- package/dist/server/services/plan/state-reconciler.d.ts.map +1 -1
- package/dist/server/services/plan/state-reconciler.js +21 -11
- package/dist/server/services/plan/state-reconciler.js.map +1 -1
- package/dist/server/services/plan/types.d.ts +2 -2
- package/dist/server/services/plan/types.d.ts.map +1 -1
- package/dist/server/services/plan/watcher.js +1 -1
- package/dist/server/services/sentry.d.ts.map +1 -1
- package/dist/server/services/sentry.js +8 -4
- package/dist/server/services/sentry.js.map +1 -1
- package/dist/server/services/websocket/deploy-handlers.d.ts +14 -0
- package/dist/server/services/websocket/deploy-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/deploy-handlers.js +409 -0
- package/dist/server/services/websocket/deploy-handlers.js.map +1 -0
- package/dist/server/services/websocket/handler.d.ts.map +1 -1
- package/dist/server/services/websocket/handler.js +12 -0
- package/dist/server/services/websocket/handler.js.map +1 -1
- package/dist/server/services/websocket/handlers/deploy-handlers.d.ts +11 -0
- package/dist/server/services/websocket/handlers/deploy-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/handlers/deploy-handlers.js +180 -0
- package/dist/server/services/websocket/handlers/deploy-handlers.js.map +1 -0
- package/dist/server/services/websocket/plan-board-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/plan-board-handlers.js +54 -1
- package/dist/server/services/websocket/plan-board-handlers.js.map +1 -1
- package/dist/server/services/websocket/plan-helpers.d.ts +1 -1
- package/dist/server/services/websocket/plan-helpers.d.ts.map +1 -1
- package/dist/server/services/websocket/plan-helpers.js +3 -4
- package/dist/server/services/websocket/plan-helpers.js.map +1 -1
- package/dist/server/services/websocket/plan-issue-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/plan-issue-handlers.js +5 -1
- package/dist/server/services/websocket/plan-issue-handlers.js.map +1 -1
- package/dist/server/services/websocket/plan-sprint-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/plan-sprint-handlers.js +3 -11
- package/dist/server/services/websocket/plan-sprint-handlers.js.map +1 -1
- package/dist/server/services/websocket/settings-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/settings-handlers.js +17 -21
- package/dist/server/services/websocket/settings-handlers.js.map +1 -1
- package/dist/server/services/websocket/types.d.ts +264 -2
- package/dist/server/services/websocket/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/server/cli/headless/claude-invoker-process.ts +1 -1
- package/server/cli/headless/headless-logger.ts +1 -1
- package/server/cli/headless/mcp-config.ts +4 -1
- package/server/cli/headless/runner.ts +1 -0
- package/server/cli/headless/types.ts +4 -1
- package/server/index.ts +9 -1
- package/server/mcp/bouncer-integration.ts +19 -17
- package/server/mcp/security-analysis.ts +19 -0
- package/server/mcp/security-patterns.ts +53 -2
- package/server/services/deploy/ai-broker.ts +512 -0
- package/server/services/deploy/board-execution-handler.ts +847 -0
- package/server/services/deploy/credentials.ts +200 -0
- package/server/services/deploy/deploy-ai-service.ts +401 -0
- package/server/services/deploy/headless-session-handler.ts +415 -0
- package/server/services/pathUtils.ts +35 -1
- package/server/services/plan/agent-loader.ts +73 -0
- package/server/services/plan/agents/review-code.md +28 -0
- package/server/services/plan/agents/review-custom.md +27 -0
- package/server/services/plan/agents/review-quality.md +42 -0
- package/server/services/plan/composer.ts +5 -1
- package/server/services/plan/dependency-resolver.ts +2 -2
- package/server/services/plan/executor.ts +27 -15
- package/server/services/plan/front-matter.ts +23 -0
- package/server/services/plan/issue-prompt-builder.ts +2 -2
- package/server/services/plan/issue-retry.ts +297 -0
- package/server/services/plan/output-manager.ts +2 -2
- package/server/services/plan/parser-core.ts +2 -2
- package/server/services/plan/parser-migration.ts +5 -5
- package/server/services/plan/parser.ts +4 -5
- package/server/services/plan/prompt-builder.ts +1 -1
- package/server/services/plan/review-gate.ts +105 -34
- package/server/services/plan/state-reconciler.ts +21 -11
- package/server/services/plan/types.ts +3 -3
- package/server/services/plan/watcher.ts +1 -1
- package/server/services/sentry.ts +8 -4
- package/server/services/websocket/deploy-handlers.ts +544 -0
- package/server/services/websocket/handler.ts +11 -1
- package/server/services/websocket/handlers/deploy-handlers.ts +230 -0
- package/server/services/websocket/plan-board-handlers.ts +53 -1
- package/server/services/websocket/plan-helpers.ts +3 -4
- package/server/services/websocket/plan-issue-handlers.ts +6 -1
- package/server/services/websocket/plan-sprint-handlers.ts +3 -9
- package/server/services/websocket/settings-handlers.ts +18 -22
- package/server/services/websocket/types.ts +333 -2
|
@@ -123,6 +123,8 @@ export interface HeadlessConfig {
|
|
|
123
123
|
extraEnv?: Record<string, string>;
|
|
124
124
|
/** Tools to disallow in the spawned Claude session (passed as --disallowedTools) */
|
|
125
125
|
disallowedTools?: string[];
|
|
126
|
+
/** Enable deploy-mode patterns in the bouncer (stricter rules for end-user-driven sessions) */
|
|
127
|
+
deployMode?: boolean;
|
|
126
128
|
}
|
|
127
129
|
|
|
128
130
|
export interface SessionState {
|
|
@@ -209,7 +211,7 @@ export interface ExecutionResult {
|
|
|
209
211
|
}
|
|
210
212
|
|
|
211
213
|
/** Resolved config with all defaults applied */
|
|
212
|
-
export type ResolvedHeadlessConfig = Omit<Required<HeadlessConfig>, 'outputCallback' | 'thinkingCallback' | 'toolUseCallback' | 'tokenUsageCallback' | 'continueSession' | 'claudeSessionId' | 'imageAttachments' | 'model' | 'toolTimeoutProfiles' | 'onToolTimeout' | 'extraEnv' | 'disallowedTools'> & {
|
|
214
|
+
export type ResolvedHeadlessConfig = Omit<Required<HeadlessConfig>, 'outputCallback' | 'thinkingCallback' | 'toolUseCallback' | 'tokenUsageCallback' | 'continueSession' | 'claudeSessionId' | 'imageAttachments' | 'model' | 'toolTimeoutProfiles' | 'onToolTimeout' | 'extraEnv' | 'disallowedTools' | 'deployMode'> & {
|
|
213
215
|
outputCallback?: (text: string) => void;
|
|
214
216
|
thinkingCallback?: (text: string) => void;
|
|
215
217
|
toolUseCallback?: (event: ToolUseEvent) => void;
|
|
@@ -222,6 +224,7 @@ export type ResolvedHeadlessConfig = Omit<Required<HeadlessConfig>, 'outputCallb
|
|
|
222
224
|
onToolTimeout?: (checkpoint: ExecutionCheckpoint) => void;
|
|
223
225
|
extraEnv?: Record<string, string>;
|
|
224
226
|
disallowedTools?: string[];
|
|
227
|
+
deployMode?: boolean;
|
|
225
228
|
};
|
|
226
229
|
|
|
227
230
|
|
package/server/index.ts
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
import { createPlatformRelayContext, ensureClaudeSettings, setTerminalTitle, wrapWebSocket } from './server-setup.js'
|
|
28
28
|
import { AnalyticsEvents, initAnalytics, shutdownAnalytics, trackEvent } from './services/analytics.js'
|
|
29
29
|
import { AuthService } from './services/auth.js'
|
|
30
|
+
import { createAiBrokerRoutes, setDeployHealthUpdateListener, setDeployUsageReportListener } from './services/deploy/ai-broker.js'
|
|
30
31
|
import { FileService } from './services/files.js'
|
|
31
32
|
import { InstanceRegistry, type MstroInstance } from './services/instances.js'
|
|
32
33
|
import { PlatformConnection } from './services/platform.js'
|
|
@@ -81,7 +82,7 @@ app.use('*', cors({
|
|
|
81
82
|
app.use('*', logger())
|
|
82
83
|
|
|
83
84
|
const authMiddleware = async (c: Context, next: Next) => {
|
|
84
|
-
const publicPaths = ['/health', '/api/config']
|
|
85
|
+
const publicPaths = ['/health', '/api/config', '/api/deploy/ai']
|
|
85
86
|
if (publicPaths.some(path => c.req.path.startsWith(path))) {
|
|
86
87
|
return next()
|
|
87
88
|
}
|
|
@@ -104,6 +105,7 @@ app.route('/api/shutdown', createShutdownRoute(instanceRegistry))
|
|
|
104
105
|
app.route('/api/improvise', createImproviseRoutes(WORKING_DIR))
|
|
105
106
|
app.route('/api/files', createFileRoutes(fileService))
|
|
106
107
|
app.route('/api/notifications', createNotificationRoutes(WORKING_DIR))
|
|
108
|
+
app.route('/api/deploy/ai', createAiBrokerRoutes())
|
|
107
109
|
|
|
108
110
|
app.post('/api/reload-pty', async (c) => {
|
|
109
111
|
const success = await reloadPty()
|
|
@@ -193,6 +195,12 @@ async function startServer() {
|
|
|
193
195
|
wsHandler.setUsageReporter((report) => {
|
|
194
196
|
platformConnection.send({ type: 'reportUsage', data: report })
|
|
195
197
|
})
|
|
198
|
+
setDeployUsageReportListener((report) => {
|
|
199
|
+
platformConnection.send({ type: 'deployUsageReport', data: report })
|
|
200
|
+
})
|
|
201
|
+
setDeployHealthUpdateListener((update) => {
|
|
202
|
+
platformConnection.send({ type: 'deployAiHealthUpdate', data: update })
|
|
203
|
+
})
|
|
196
204
|
},
|
|
197
205
|
onDisconnected: () => {
|
|
198
206
|
if (platformRelayContext) {
|
|
@@ -19,6 +19,13 @@
|
|
|
19
19
|
* │ - Defaults to ALLOW - user is actively working with Claude │
|
|
20
20
|
* └─────────────────────────────────────────────────────────────┘
|
|
21
21
|
*
|
|
22
|
+
* SECURITY BOUNDARY: Layer 1 is a performance optimization, NOT a
|
|
23
|
+
* security boundary. Haiku (Layer 2) is the security boundary.
|
|
24
|
+
* Layer 1 patterns are public (open-source repo) and should be
|
|
25
|
+
* treated as a fast-path filter only. Never expand SAFE_OPERATIONS
|
|
26
|
+
* to include operations with side effects beyond the user's
|
|
27
|
+
* working directory.
|
|
28
|
+
*
|
|
22
29
|
* Haiku AI analysis lives in bouncer-haiku.ts.
|
|
23
30
|
* Pattern definitions live in security-patterns.ts.
|
|
24
31
|
* Analysis logic lives in security-analysis.ts.
|
|
@@ -168,8 +175,9 @@ async function runHaikuAnalysis(
|
|
|
168
175
|
startTime: number,
|
|
169
176
|
fin: (d: BouncerDecision, layer: string, opts?: Parameters<typeof finalizeDecision>[6]) => BouncerDecision,
|
|
170
177
|
): Promise<BouncerDecision> {
|
|
171
|
-
|
|
172
|
-
|
|
178
|
+
const aiDisabledByEnv = process.env.BOUNCER_USE_AI === 'false' && process.env.NODE_ENV !== 'production';
|
|
179
|
+
if (aiDisabledByEnv || request.context?._skipAI === true) {
|
|
180
|
+
console.error('[Bouncer] AI analysis disabled');
|
|
173
181
|
return fin({ decision: 'warn_allow', confidence: 60, reasoning: 'Operation requires review but AI analysis is disabled. Proceeding with caution.', threatLevel: 'medium' }, 'ai-disabled', { skipCache: true, skipAnalytics: true });
|
|
174
182
|
}
|
|
175
183
|
|
|
@@ -263,26 +271,20 @@ export { classifyRisk as classifyOperationRisk } from './security-patterns.js';
|
|
|
263
271
|
|
|
264
272
|
/**
|
|
265
273
|
* Legacy compatibility — redirects to reviewOperation.
|
|
266
|
-
* When useAI=false,
|
|
267
|
-
*
|
|
274
|
+
* When useAI=false, skips AI analysis by injecting a context flag
|
|
275
|
+
* that runHaikuAnalysis checks (avoids racy process.env mutation).
|
|
268
276
|
*/
|
|
269
277
|
export async function launchBouncerAgent(
|
|
270
278
|
request: BouncerReviewRequest,
|
|
271
279
|
useAI: boolean = true
|
|
272
280
|
): Promise<BouncerDecision> {
|
|
273
|
-
const prevValue = process.env.BOUNCER_USE_AI;
|
|
274
281
|
if (!useAI) {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
if (prevValue !== undefined) {
|
|
282
|
-
process.env.BOUNCER_USE_AI = prevValue;
|
|
283
|
-
} else {
|
|
284
|
-
delete process.env.BOUNCER_USE_AI;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
282
|
+
// Inject skipAI flag into the request context so runHaikuAnalysis
|
|
283
|
+
// can check it without mutating process.env (which races under concurrency).
|
|
284
|
+
request = {
|
|
285
|
+
...request,
|
|
286
|
+
context: { ...request.context, _skipAI: true },
|
|
287
|
+
};
|
|
287
288
|
}
|
|
289
|
+
return reviewOperation(request);
|
|
288
290
|
}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
12
|
CRITICAL_THREATS,
|
|
13
|
+
DEPLOY_PATTERNS,
|
|
13
14
|
matchesPattern,
|
|
14
15
|
NEEDS_AI_REVIEW,
|
|
15
16
|
normalizeOperation,
|
|
@@ -62,6 +63,17 @@ function isSafeExpansionUse(operation: string): boolean {
|
|
|
62
63
|
return safePrefix.test(cmd);
|
|
63
64
|
}
|
|
64
65
|
|
|
66
|
+
// ── Deploy Mode Detection ────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Check if the bouncer is running in deploy mode.
|
|
70
|
+
* Set by the MCP config when spawned for deploy (board/headless) executions.
|
|
71
|
+
* Deploy mode activates additional security patterns for end-user-driven sessions.
|
|
72
|
+
*/
|
|
73
|
+
export function isDeployMode(): boolean {
|
|
74
|
+
return process.env.BOUNCER_DEPLOY_MODE === 'true';
|
|
75
|
+
}
|
|
76
|
+
|
|
65
77
|
// ── Public API ────────────────────────────────────────────────
|
|
66
78
|
|
|
67
79
|
/**
|
|
@@ -104,6 +116,13 @@ export function requiresAIReview(operation: string): boolean {
|
|
|
104
116
|
return true;
|
|
105
117
|
}
|
|
106
118
|
|
|
119
|
+
// Deploy-specific patterns: when running in deploy mode (end-user driven),
|
|
120
|
+
// additional operations are flagged for AI review. These take precedence
|
|
121
|
+
// over safe operations because deploy context has stricter requirements.
|
|
122
|
+
if (isDeployMode() && matchesPattern(op, DEPLOY_PATTERNS)) {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
|
|
107
126
|
if (matchesPattern(op, SAFE_OPERATIONS)) {
|
|
108
127
|
// Safe bash commands must not contain chain operators, dangerous pipes,
|
|
109
128
|
// or subshell/backtick expansion that could hide dangerous operations.
|
|
@@ -13,6 +13,12 @@
|
|
|
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
15
|
*
|
|
16
|
+
* SECURITY NOTE: These patterns are public (open-source repo). Pattern
|
|
17
|
+
* visibility is intentional and follows industry practice (OWASP CRS,
|
|
18
|
+
* Snort, ModSecurity all publish rules publicly). The Haiku AI layer
|
|
19
|
+
* in bouncer-integration.ts is the actual security boundary — these
|
|
20
|
+
* patterns are a performance optimization for the fast path only.
|
|
21
|
+
*
|
|
16
22
|
* Analysis logic (requiresAIReview, classifyRisk) lives in security-analysis.ts
|
|
17
23
|
* and is re-exported here for backward compatibility.
|
|
18
24
|
*/
|
|
@@ -34,7 +40,7 @@ export interface SecurityPattern {
|
|
|
34
40
|
export const SENSITIVE_PATHS: SecurityPattern[] = [
|
|
35
41
|
// System directories - might be legitimate (e.g., user asked to configure something)
|
|
36
42
|
{ pattern: /^(Write|Edit):\s*\/etc\//i, reason: 'System configuration - verify user intent' },
|
|
37
|
-
{ pattern: /^(Write|Edit):\s*\/(bin|sbin|usr\/bin|usr\/sbin)\//i, reason: 'System binaries - verify user intent' },
|
|
43
|
+
{ pattern: /^(Write|Edit):\s*\/(bin|sbin|usr\/bin|usr\/sbin|usr\/local\/bin|usr\/local\/sbin)\//i, reason: 'System binaries - verify user intent' },
|
|
38
44
|
{ pattern: /^(Write|Edit):\s*\/boot\//i, reason: 'Boot directory - verify user intent' },
|
|
39
45
|
{ pattern: /^(Write|Edit):\s*\/root\//i, reason: 'Root home - verify user intent' },
|
|
40
46
|
{ pattern: /^(Write|Edit):\s*\/System\//i, reason: 'macOS system - verify user intent' },
|
|
@@ -63,7 +69,7 @@ export const SENSITIVE_PATHS: SecurityPattern[] = [
|
|
|
63
69
|
*/
|
|
64
70
|
export const CRITICAL_THREATS: SecurityPattern[] = [
|
|
65
71
|
{
|
|
66
|
-
pattern: /rm\s+-rf\s+(\/|~)($|\s)/i,
|
|
72
|
+
pattern: /rm\s+-rf\s+(\/|~)($|\s|;|&&|\|\|)/i,
|
|
67
73
|
reason: 'Deleting root (/) or home (~) directory is never a legitimate dev task'
|
|
68
74
|
},
|
|
69
75
|
{
|
|
@@ -239,6 +245,51 @@ export const NEEDS_AI_REVIEW: SecurityPattern[] = [
|
|
|
239
245
|
{ pattern: /\bclaude\b.*\bmcp\b.*\badd\b/i, reason: 'Adding MCP server - verify source is trusted' },
|
|
240
246
|
];
|
|
241
247
|
|
|
248
|
+
/**
|
|
249
|
+
* Deploy-specific patterns — additional restrictions for board/headless executions
|
|
250
|
+
* triggered by end-user prompts (untrusted input from deployed app users).
|
|
251
|
+
*
|
|
252
|
+
* These catch operations that are unusual in an automated board execution context
|
|
253
|
+
* and should be routed to AI review. They supplement NEEDS_AI_REVIEW above.
|
|
254
|
+
*/
|
|
255
|
+
export const DEPLOY_PATTERNS: SecurityPattern[] = [
|
|
256
|
+
// Credential access from deploy context is suspicious
|
|
257
|
+
{
|
|
258
|
+
pattern: /\b(cat|head|tail|less|more)\b.*\.(env|pem|key|crt|p12|pfx|jks)\b/i,
|
|
259
|
+
reason: 'Deploy execution reading credential/certificate files — verify intent'
|
|
260
|
+
},
|
|
261
|
+
|
|
262
|
+
// Git push from deploy context — end-user code should not push upstream
|
|
263
|
+
{
|
|
264
|
+
pattern: /\bgit\b.*\bpush\b/i,
|
|
265
|
+
reason: 'Deploy execution attempting git push — verify this is intended'
|
|
266
|
+
},
|
|
267
|
+
|
|
268
|
+
// Network listeners — deploy executions should not open ports
|
|
269
|
+
{
|
|
270
|
+
pattern: /\b(nc|netcat|ncat|socat)\b.*(\blisten\b|\s-l\b)/i,
|
|
271
|
+
reason: 'Deploy execution opening network listener — potential backdoor'
|
|
272
|
+
},
|
|
273
|
+
|
|
274
|
+
// Process manipulation from deploy context
|
|
275
|
+
{
|
|
276
|
+
pattern: /\b(kill|killall|pkill)\b/i,
|
|
277
|
+
reason: 'Deploy execution attempting process termination — verify intent'
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
// SSH/SCP from deploy context
|
|
281
|
+
{
|
|
282
|
+
pattern: /\b(ssh|scp|sftp)\b.*@/i,
|
|
283
|
+
reason: 'Deploy execution initiating SSH/SCP connection — verify intent'
|
|
284
|
+
},
|
|
285
|
+
|
|
286
|
+
// Cron/systemd manipulation
|
|
287
|
+
{
|
|
288
|
+
pattern: /\b(crontab|systemctl|launchctl)\b/i,
|
|
289
|
+
reason: 'Deploy execution manipulating scheduled tasks — verify intent'
|
|
290
|
+
},
|
|
291
|
+
];
|
|
292
|
+
|
|
242
293
|
// ── Utility functions ─────────────────────────────────────────
|
|
243
294
|
|
|
244
295
|
/**
|