From 210384d97b6a97f26a985c7b3d38ab4639e9fda9 Mon Sep 17 00:00:00 2001 From: "fix-it-felix-sentry[bot]" <260785270+fix-it-felix-sentry[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 13:42:01 +0000 Subject: [PATCH 1/2] fix: Add path traversal protection for schema file loading Add validation to prevent path traversal vulnerabilities when loading structured output schema files. The fix ensures that resolved file paths remain within the intended schemas directory by validating that the resolved path starts with the schemas directory path. This addresses a potential security issue where malicious input could potentially manipulate file paths through path traversal sequences. The fix adds checks in two locations: 1. In schemaPathFor() for schema files 2. In getMcpOutputSchema() for the common schema file Resolves: https://linear.app/getsentry/issue/VULN-1596 Resolves: https://linear.app/getsentry/issue/ENG-7560 Co-Authored-By: Claude Sonnet 4.5 --- src/core/structured-output-schema.ts | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/core/structured-output-schema.ts b/src/core/structured-output-schema.ts index 8f075d8d2..61441ba8a 100644 --- a/src/core/structured-output-schema.ts +++ b/src/core/structured-output-schema.ts @@ -73,7 +73,17 @@ function readJsonObject(filePath: string, label: string): JsonObject { } function schemaPathFor(ref: StructuredOutputSchemaRef): string { - return path.join(getStructuredOutputSchemasDir(), ref.schema, `${ref.version}.schema.json`); + const schemasDir = getStructuredOutputSchemasDir(); + const schemaPath = path.join(schemasDir, ref.schema, `${ref.version}.schema.json`); + const resolvedPath = path.resolve(schemaPath); + const resolvedSchemasDir = path.resolve(schemasDir); + + // Prevent path traversal attacks by ensuring the resolved path is within the schemas directory + if (!resolvedPath.startsWith(resolvedSchemasDir + path.sep) && resolvedPath !== resolvedSchemasDir) { + throw new Error(`Invalid schema path: attempted path traversal detected for ${ref.schema}@${ref.version}`); + } + + return schemaPath; } function collectAndRewriteCommonRefs(value: unknown, pendingDefs: Set): unknown { @@ -192,8 +202,19 @@ export function getMcpOutputSchema(ref: StructuredOutputSchemaRef): JsonObject { } const rootSchema = readJsonObject(schemaPathFor(ref), `${ref.schema}@${ref.version}`); + + // Validate common schema path to prevent path traversal + const schemasDir = getStructuredOutputSchemasDir(); + const commonSchemaPath = path.join(schemasDir, '_defs', 'common.schema.json'); + const resolvedCommonPath = path.resolve(commonSchemaPath); + const resolvedSchemasDir = path.resolve(schemasDir); + + if (!resolvedCommonPath.startsWith(resolvedSchemasDir + path.sep) && resolvedCommonPath !== resolvedSchemasDir) { + throw new Error('Invalid common schema path: attempted path traversal detected'); + } + const commonSchema = readJsonObject( - path.join(getStructuredOutputSchemasDir(), '_defs', 'common.schema.json'), + commonSchemaPath, 'common structured output definitions', ); const bundled = bundleSchema(rootSchema, commonSchema); From 599fce87185127b5ed4542479b0bcc894740262b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 30 Apr 2026 18:11:29 +0000 Subject: [PATCH 2/2] fix: Remove redundant path traversal check for hardcoded common schema path --- src/core/structured-output-schema.ts | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/core/structured-output-schema.ts b/src/core/structured-output-schema.ts index 61441ba8a..846fb3192 100644 --- a/src/core/structured-output-schema.ts +++ b/src/core/structured-output-schema.ts @@ -79,8 +79,13 @@ function schemaPathFor(ref: StructuredOutputSchemaRef): string { const resolvedSchemasDir = path.resolve(schemasDir); // Prevent path traversal attacks by ensuring the resolved path is within the schemas directory - if (!resolvedPath.startsWith(resolvedSchemasDir + path.sep) && resolvedPath !== resolvedSchemasDir) { - throw new Error(`Invalid schema path: attempted path traversal detected for ${ref.schema}@${ref.version}`); + if ( + !resolvedPath.startsWith(resolvedSchemasDir + path.sep) && + resolvedPath !== resolvedSchemasDir + ) { + throw new Error( + `Invalid schema path: attempted path traversal detected for ${ref.schema}@${ref.version}`, + ); } return schemaPath; @@ -203,20 +208,9 @@ export function getMcpOutputSchema(ref: StructuredOutputSchemaRef): JsonObject { const rootSchema = readJsonObject(schemaPathFor(ref), `${ref.schema}@${ref.version}`); - // Validate common schema path to prevent path traversal const schemasDir = getStructuredOutputSchemasDir(); const commonSchemaPath = path.join(schemasDir, '_defs', 'common.schema.json'); - const resolvedCommonPath = path.resolve(commonSchemaPath); - const resolvedSchemasDir = path.resolve(schemasDir); - - if (!resolvedCommonPath.startsWith(resolvedSchemasDir + path.sep) && resolvedCommonPath !== resolvedSchemasDir) { - throw new Error('Invalid common schema path: attempted path traversal detected'); - } - - const commonSchema = readJsonObject( - commonSchemaPath, - 'common structured output definitions', - ); + const commonSchema = readJsonObject(commonSchemaPath, 'common structured output definitions'); const bundled = bundleSchema(rootSchema, commonSchema); bundledSchemaCache.set(cacheKey, bundled); return cloneJson(bundled);