diff --git a/core/util/tts.ts b/core/util/tts.ts index aace86bf9dc..2d434d08872 100644 --- a/core/util/tts.ts +++ b/core/util/tts.ts @@ -12,22 +12,34 @@ const ttsKillTimeout: number = 5000; /** * Cleans a message text to safely be used in 'exec' context on host. + * This function sanitizes input to prevent command injection attacks. * * Return modified message text. */ export function sanitizeMessageForTTS(message: string): string { message = removeCodeBlocksAndTrim(message); - // Remove or replace problematic characters + // Remove or replace problematic characters that could enable command injection + // This includes shell metacharacters and escape sequences message = message - .replace(/"/g, "") - .replace(/`/g, "") - .replace(/\$/g, "") - .replace(/\\/g, "") - .replace(/[&|;()<>]/g, ""); + .replace(/"/g, "") // Remove double quotes + .replace(/'/g, "") // Remove single quotes + .replace(/`/g, "") // Remove backticks (command substitution) + .replace(/\$/g, "") // Remove dollar signs (variable expansion) + .replace(/\\/g, "") // Remove backslashes (escape sequences) + .replace(/[&|;()<>{}\[\]!#*?~^%]/g, "") // Remove shell metacharacters (includes % for cmd.exe variable expansion) + .replace(/\x00/g, "") // Remove null bytes + .replace(/\n/g, " ") // Replace newlines with spaces + .replace(/\r/g, " "); // Replace carriage returns with spaces message = message.trim().replace(/\s+/g, " "); + // Limit message length to prevent potential DoS + const MAX_TTS_LENGTH = 5000; + if (message.length > MAX_TTS_LENGTH) { + message = message.substring(0, MAX_TTS_LENGTH); + } + return message; } diff --git a/extensions/cli/package-lock.json b/extensions/cli/package-lock.json index 0e6a44eec36..02fffc87817 100644 --- a/extensions/cli/package-lock.json +++ b/extensions/cli/package-lock.json @@ -121,8 +121,8 @@ "dependencies": { "@anthropic-ai/sdk": "^0.62.0", "@aws-sdk/client-bedrock-runtime": "^3.931.0", - "@aws-sdk/client-sagemaker-runtime": "^3.777.0", - "@aws-sdk/credential-providers": "^3.931.0", + "@aws-sdk/client-sagemaker-runtime": "^3.894.0", + "@aws-sdk/credential-providers": "^3.974.0", "@continuedev/config-types": "^1.0.14", "@continuedev/config-yaml": "file:../packages/config-yaml", "@continuedev/fetch": "file:../packages/fetch", @@ -201,6 +201,7 @@ "@babel/preset-env": "^7.24.7", "@biomejs/biome": "1.6.4", "@google/generative-ai": "^0.11.4", + "@modelcontextprotocol/ext-apps": "^1.0.1", "@shikijs/colorized-brackets": "^3.7.0", "@shikijs/transformers": "^3.7.0", "@types/diff": "^7.0.1", @@ -272,16 +273,18 @@ "dev": true, "license": "Apache-2.0", "dependencies": { - "@ai-sdk/anthropic": "^1.0.10", - "@ai-sdk/openai": "^1.0.10", + "@ai-sdk/anthropic": "^3.0.44", + "@ai-sdk/deepseek": "^2.0.20", + "@ai-sdk/openai": "^3.0.29", + "@ai-sdk/xai": "^3.0.57", "@anthropic-ai/sdk": "^0.67.0", "@aws-sdk/client-bedrock-runtime": "^3.931.0", - "@aws-sdk/credential-providers": "^3.931.0", + "@aws-sdk/credential-providers": "^3.974.0", "@continuedev/config-types": "^1.0.14", "@continuedev/config-yaml": "^1.38.0", "@continuedev/fetch": "^1.6.0", "@google/genai": "^1.30.0", - "ai": "^4.0.33", + "ai": "^6.0.86", "dotenv": "^16.5.0", "google-auth-library": "^10.4.1", "json-schema": "^0.4.0", diff --git a/extensions/cli/src/stream/streamChatResponse.helpers.ts b/extensions/cli/src/stream/streamChatResponse.helpers.ts index 6f8f3fa18de..cf997579573 100644 --- a/extensions/cli/src/stream/streamChatResponse.helpers.ts +++ b/extensions/cli/src/stream/streamChatResponse.helpers.ts @@ -266,6 +266,7 @@ function calculateFallbackCost( } // Helper function to record telemetry +// eslint-disable-next-line complexity -- Pre-existing complexity; refactoring deferred export function recordStreamTelemetry(options: { requestStartTime: number; responseEndTime: number; diff --git a/extensions/cli/src/ui/hooks/useChat.imageProcessing.ts b/extensions/cli/src/ui/hooks/useChat.imageProcessing.ts index 83db7a3cdba..4a7a207f98a 100644 --- a/extensions/cli/src/ui/hooks/useChat.imageProcessing.ts +++ b/extensions/cli/src/ui/hooks/useChat.imageProcessing.ts @@ -1,13 +1,19 @@ import { logger } from "../../util/logger.js"; /** - * Dynamically import Sharp without using eval + * Dynamically import Sharp module for image processing. + * Sharp is an optional dependency for image resizing/conversion. + * Uses a variable module name to prevent TypeScript from trying to resolve the module at compile time. */ async function loadSharp(): Promise { try { - // Use Function constructor to avoid bundler issues with dynamic imports - const importSharp = new Function('return import("sharp")'); - const sharpModule = await importSharp().catch(() => null); + // Use a variable to store the module name to prevent TypeScript static analysis + // from trying to resolve the module (which would fail if sharp is not installed) + const moduleName = "sharp"; + // eslint-disable-next-line @typescript-eslint/no-require-imports + const sharpModule = await import( + /* webpackIgnore: true */ moduleName + ).catch(() => null); return sharpModule ? sharpModule.default || sharpModule : null; } catch { return null; diff --git a/gui/package-lock.json b/gui/package-lock.json index 20f55f719bc..eb43ac1f37e 100644 --- a/gui/package-lock.json +++ b/gui/package-lock.json @@ -120,7 +120,7 @@ "@anthropic-ai/sdk": "^0.62.0", "@aws-sdk/client-bedrock-runtime": "^3.931.0", "@aws-sdk/client-sagemaker-runtime": "^3.894.0", - "@aws-sdk/credential-providers": "^3.931.0", + "@aws-sdk/credential-providers": "^3.974.0", "@continuedev/config-types": "^1.0.14", "@continuedev/config-yaml": "file:../packages/config-yaml", "@continuedev/fetch": "file:../packages/fetch", diff --git a/gui/src/pages/config/sections/ToolsSection.tsx b/gui/src/pages/config/sections/ToolsSection.tsx index a48bd5df7ac..f439ee67722 100644 --- a/gui/src/pages/config/sections/ToolsSection.tsx +++ b/gui/src/pages/config/sections/ToolsSection.tsx @@ -1,4 +1,5 @@ import { ConfigYaml, parseConfigYaml } from "@continuedev/config-yaml"; +import DOMPurify from "dompurify"; import { ArrowPathIcon, ChevronDownIcon, @@ -395,7 +396,7 @@ function MCPServerPreview({ > ))}