{"record":{"id":"17f503a07a99321b","repo":"langfuse/langfuse","slug":"invalid-encoding","errorCode":"invalid-encoding","errorMessage":"Invalid URL encoding","messagePattern":"Invalid URL encoding","errorType":"validation","errorClass":"OutboundUrlValidationError","httpStatus":400,"severity":"error","filePath":"packages/shared/src/server/outbound-url/validation.ts","lineNumber":195,"sourceCode":"  if (isIPBlocked(ip, whitelist.ips, whitelist.ip_ranges)) {\n    logger.warn(\n      `${logContext} validation blocked resolved IP address: ${ip} for hostname: ${hostname}`,\n    );\n    throw new OutboundUrlValidationError(\n      \"blocked-ip\",\n      \"Blocked IP address detected\",\n    );\n  }\n}\n\nfunction assertValidUrlEncoding(urlString: string): void {\n  // This intentionally checks encoding validity only. Do not parse or validate\n  // the decoded result: decoding the whole URL can turn encoded data into URL\n  // delimiters and make validation inspect a different hostname than fetch.\n  try {\n    decodeURIComponent(urlString);\n  } catch {\n    throw new OutboundUrlValidationError(\n      \"invalid-encoding\",\n      \"Invalid URL encoding\",\n    );\n  }\n}\n","sourceCodeStart":177,"sourceCodeEnd":201,"githubUrl":"https://github.com/langfuse/langfuse/blob/59d92c7cf365150d10b753b5a0d1708902a2ed60/packages/shared/src/server/outbound-url/validation.ts#L177-L201","documentation":"assertValidUrlEncoding runs decodeURIComponent on the URL string purely to verify it is valid percent-encoding; malformed sequences like '%zz' or a trailing lone '%' throw invalid-encoding. The decoded value is deliberately not used, to avoid parser-differential attacks between validation and fetch.","triggerScenarios":"Passing a URL containing invalid percent-escapes, e.g. 'https://host/path%zz', 'https://host/50%', or double-broken encodings, to any outbound URL validation entry point.","commonSituations":"String concatenation that forgets encodeURIComponent (raw '%' in query values); user input with stray percent signs; partially-encoded URLs from logs or configs.","solutions":["Encode URL components properly: use encodeURIComponent on values interpolated into the URL.","Fix or remove malformed % sequences in the configured URL.","Test with decodeURIComponent(url) in a scratch script before saving the config."],"exampleFix":"// before\nconst url = `https://host/?q=${q}`; // q = \"50% off\"\n// after\nconst url = `https://host/?q=${encodeURIComponent(q)}`;","handlingStrategy":"validation","validationCode":"function isValidEncoding(u: string): boolean { try { decodeURIComponent(u); return true; } catch { return false; } }","typeGuard":"null","tryCatchPattern":"catch (e) { if (e.code === \"invalid-encoding\") reencodeComponentsAndRetry(); else throw e; }","preventionTips":["Always encodeURIComponent dynamic query values.","Lint stored URLs with decodeURIComponent in CI."],"tags":["url","encoding","validation"],"backgroundTag":"invalid-url-encoding","analyzedSha":"59d92c7cf365150d10b753b5a0d1708902a2ed60","analyzedAt":"2026-08-27T22:22:00.402Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}