Skip to content

fix: allow query strings and fragments in image URL regex (#484) - #485

Merged
robert-j-y merged 1 commit into
mainfrom
devin/1777126008-fix-issue-484-image-url-query-params
Apr 28, 2026
Merged

fix: allow query strings and fragments in image URL regex (#484)#485
robert-j-y merged 1 commit into
mainfrom
devin/1777126008-fix-issue-484-image-url-query-params

Conversation

@robert-j-y

@robert-j-y robert-j-y commented Apr 25, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes #484 — the supportedUrls['image/*'] regex anchored the extension to the end of the string with $, so any valid image URL with a query string or fragment (e.g. https://cdn.example.com/photo.png?height=200) did NOT match. When supportedUrls doesn't match, the AI SDK's LanguageModelV3 layer downloads the image and inlines it as base64 into the prompt, which bloats conversation history and inflates token usage.

The fix relaxes the pattern to allow an optional ?... and/or #... suffix after the extension. Strict allowlist behavior is preserved — the extension is still required and must remain terminal in the path. The same fix is applied to both src/chat/index.ts and src/completion/index.ts to keep them in sync. The data:image/... pattern is left unchanged.

Before / after

// before — src/chat/index.ts:73, src/completion/index.ts:57
/^https?:\/\/.+\.(jpg|jpeg|png|gif|webp)$/i

// after
/^https?:\/\/.+\.(jpg|jpeg|png|gif|webp)(?:[?#].*)?$/i
const re = /^https?:\/\/.+\.(jpg|jpeg|png|gif|webp)(?:[?#].*)?$/i;

re.test('https://cdn.example.com/photo.png');                  // true (unchanged)
re.test('https://cdn.example.com/photo.png?height=200');       // true (was false)
re.test('https://cdn.example.com/photo.webp#frag');            // true (was false)
re.test('https://cdn.example.com/photo.PNG?x=1#frag');         // true (was false)
re.test('https://cdn.example.com/some.png/redirect');          // false (still rejected — extension not terminal)
re.test('https://example.com/document.pdf');                   // false (unchanged)

Test coverage

Added e2e/issues/issue-484-image-url-query-params.test.ts with 32 unit-style cases (no network) covering both chat and completion supportedUrls:

  • query strings, fragments, and combined ?...#... suffixes
  • plain URLs (no suffix) and data: URIs — must still match
  • non-image URLs and wrong scheme — must still be rejected
  • defensive: URL-encoded query values, pre-signed S3-style URLs with multiple query params, empty ? / #, uppercase extension with query
  • defensive: extension-in-path shapes (.../some.png/redirect, .../photo.jpg/thumbnail) — must REMAIN rejected (guards against overly-loose relaxations)

On current main 16 of these cases fail; with the fix all 32 pass.

Reviewer checklist

Verified against the diff at HEAD:

  • Both src/chat/index.ts:73 and src/completion/index.ts:57 updated identically (same regex literal in both files)
  • data:image/... pattern unchanged (/^data:image\/[a-zA-Z]+;base64,/)
  • application/* and text/* patterns untouched
  • No as / type assertions introduced (only as const literal-narrowing in the new test, which is allowed)
  • Strict allowlist behavior preserved: extension is still required and must be terminal in the path (defensive cases .../some.png/redirect and .../photo.jpg/thumbnail confirmed still rejected)
  • Regression test fails on main (16/32 fail) and passes on this branch (32/32)

Checklist

  • I have run pnpm stylecheck and pnpm typecheck
  • I have run pnpm test and all tests pass
  • I have added tests for my changes (if applicable)
  • I have updated documentation (if applicable) — N/A, internal regex bug fix with no public API change

Changeset

  • I have run pnpm changeset to create a changeset file

The supportedUrls['image/*'] regex anchored the extension to the end of
the string, so URLs with ?query or #fragment did not match and got
downloaded + base64-inlined by the AI SDK layer. Updated both chat and
completion models to accept an optional [?#].* suffix after the
extension. Strict allowlist behavior (extension required, terminal) is
preserved.

Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>
@robert-j-y
robert-j-y merged commit bf664b1 into main Apr 28, 2026
2 checks passed
@robert-j-y
robert-j-y deleted the devin/1777126008-fix-issue-484-image-url-query-params branch April 28, 2026 19:08
@github-actions github-actions Bot mentioned this pull request Apr 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Zod Schema for Image URLs restricts query params

1 participant