fix(otel): stop base64 media regex from matching across commas - #872
fix(otel): stop base64 media regex from matching across commas#872jerichosiahaya wants to merge 1 commit into
Conversation
MediaService.process() scans span attributes for data URIs with
/data:[^;]+;base64,.../g. The mediatype segment [^;]+ excludes only
semicolons, so when a trace payload contains a plain-text 'data:'
mention earlier in the same string (e.g. user message text), the
regex greedily matches from that first 'data:' through unrelated
text, including any commas, all the way to a later real
';base64,' data URI. The resulting bogus match fails to parse
('[Langfuse SDK] [ERROR] Error parsing base64 data URI Error:
Data is not base64 encoded'), and the real media is silently
dropped.
Exclude commas too ([^;,]+): real mediatypes (image/png,
application/pdf, ...) never contain a comma, so legitimate matches
are unaffected, but the regex can no longer span past one.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@jerichosiahaya is attempting to deploy a commit to the langfuse Team on Vercel. A member of the Team first needs to authorize it. |
|
|
The bugThe regex that scans trace payloads for base64 file attachments was too permissive:
[^;]+ means "any character except ;" — which allowed the match to run across commas and unrelated text. If a trace payload contained the literal text data: before a real attached file, the regex would glue the two together into one bogus match, which then failed to parse as a valid data URI and threw: [Langfuse SDK] [ERROR] Error parsing base64 data URI Error: Data is not base64 encoded The fixAdded , to the excluded characters. A real file's mediatype (image/png, application/pdf, etc.) never contains a comma, so this closes the false-match path without affecting any legitimate file upload. What else was added
|
MediaService.process() scans span attributes for data URIs with /data:[^;]+;base64,.../g. The mediatype segment [^;]+ excludes only semicolons, so when a trace payload contains a plain-text 'data:' mention earlier in the same string (e.g. user message text), the regex greedily matches from that first 'data:' through unrelated text, including any commas, all the way to a later real ';base64,' data URI. The resulting bogus match fails to parse ('[Langfuse SDK] [ERROR] Error parsing base64 data URI Error: Data is not base64 encoded'), and the real media is silently dropped.
Exclude commas too ([^;,]+): real mediatypes (image/png, application/pdf, ...) never contain a comma, so legitimate matches are unaffected, but the regex can no longer span past one.
Problem
Changes
Verification
pnpm lintpnpm typecheckpnpm testpnpm test:integrationpnpm test:e2epnpm format:checkRelease info
Bump level
Libraries affected
Changelog notes
Greptile Summary
This PR fixes a greedy-regex bug in
MediaService.process()where a plain-textdata:mention earlier in a span attribute string could be stitched to a later, realdata:URIby the extraction regex, producing a bogus match that failed base64 parsing and silently dropped the real media. The one-character change ([^;]+→[^;,]+) prevents cross-comma greedy matching; MIME types never contain commas, so no valid data URI is affected.packages/otel/src/MediaService.ts): adds,to the excluded character set in the mediatype segment, so the regex anchors tightly and cannot span past a comma into unrelated text.tests/unit/mediaService.test.ts): adds three unit tests covering a normal data URI extraction, the regression scenario (plain-textdata:followed by a real URI in the same string), and the no-URI-present path.Confidence Score: 5/5
This is a minimal, targeted regex fix in a single character class; the change cannot affect any valid MIME type and directly closes the greedy-match escape hatch that caused bogus URI parsing.
The one-character change is logically sound — MIME types never contain commas, so adding ',' to the negated class only restricts invalid matches. The three new unit tests directly exercise the fixed path, the regression scenario, and the no-URI path, giving good coverage of the changed behavior. No edge cases are introduced or regressed.
No files require special attention. The test mock returns getUploadUrl synchronously (not a Promise), which works fine in JS/TS but differs from the real API shape — worth keeping in mind if the test suite is later extended.
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A["span attribute value (string)"] --> B["Apply regex\n/data:[^;,]+;base64,[A-Za-z0-9+/]+=*/g"] B --> C{Matches found?} C -- No --> D[Skip attribute] C -- Yes --> E[Deduplicate matches via Set] E --> F["For each match: create LangfuseMedia\n(base64DataUri)"] F --> G["media.getTag() → langfuseMediaTag"] G --> H{Tag created?} H -- No --> I[Log warning, skip item] H -- Yes --> J[scheduleUpload in background] J --> K["Replace raw data URI in attribute\nwith @@@langfuse-media:... tag"] K --> L[Update span.attributes key]%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% flowchart TD A["span attribute value (string)"] --> B["Apply regex\n/data:[^;,]+;base64,[A-Za-z0-9+/]+=*/g"] B --> C{Matches found?} C -- No --> D[Skip attribute] C -- Yes --> E[Deduplicate matches via Set] E --> F["For each match: create LangfuseMedia\n(base64DataUri)"] F --> G["media.getTag() → langfuseMediaTag"] G --> H{Tag created?} H -- No --> I[Log warning, skip item] H -- Yes --> J[scheduleUpload in background] J --> K["Replace raw data URI in attribute\nwith @@@langfuse-media:... tag"] K --> L[Update span.attributes key]Reviews (1): Last reviewed commit: "fix(otel): stop base64 media regex from ..." | Re-trigger Greptile