diff --git a/Dockerfile b/Dockerfile index 3933e7e..a870073 100644 --- a/Dockerfile +++ b/Dockerfile @@ -68,7 +68,23 @@ RUN apk update && apk add --no-cache \ nodejs-22 \ npm \ python3 \ - ruby + ruby \ + # Chromium browser and dependencies for Playwright + chromium \ + # Additional libraries Chromium needs + nss \ + freetype \ + harfbuzz \ + # X11 libraries for headless browser + libx11 \ + libxcomposite \ + libxdamage \ + libxext \ + libxfixes \ + libxrandr \ + mesa-gbm \ + # Font rendering + fontconfig # Copy Go binaries from builder COPY --from=builder /go/bin/subfinder /usr/local/bin/ @@ -116,6 +132,9 @@ USER pentest # Set environment variables ENV NODE_ENV=production ENV PATH="/usr/local/bin:$PATH" +ENV SHANNON_DOCKER=true +ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 +ENV PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium-browser # Set entrypoint diff --git a/src/ai/claude-executor.js b/src/ai/claude-executor.js index d494cbe..cce87a2 100644 --- a/src/ai/claude-executor.js +++ b/src/ai/claude-executor.js @@ -157,13 +157,31 @@ async function runClaudePrompt(prompt, sourceDir, allowedTools = 'Read', context // Add Playwright MCP server if this agent needs browser automation if (playwrightMcpName) { const userDataDir = `/tmp/${playwrightMcpName}`; + + // Detect if running in Docker via explicit environment variable + const isDocker = process.env.SHANNON_DOCKER === 'true'; + + // Build args array - conditionally add --executable-path for Docker + const mcpArgs = [ + '@playwright/mcp@latest', + '--isolated', + '--user-data-dir', userDataDir, + ]; + + // Docker: Use system Chromium; Local: Use Playwright's bundled browsers + if (isDocker) { + mcpArgs.push('--executable-path', '/usr/bin/chromium-browser'); + mcpArgs.push('--browser', 'chromium'); + } + mcpServers[playwrightMcpName] = { type: 'stdio', command: 'npx', - args: ['@playwright/mcp@latest', '--isolated', '--user-data-dir', userDataDir], + args: mcpArgs, env: { ...process.env, PLAYWRIGHT_HEADLESS: 'true', // Ensure headless mode for security and CI compatibility + ...(isDocker && { PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' }), // Only skip in Docker }, }; }