Skip to content

fix: pass through gs:// image URLs on Vertex Gemini closes #4402 - #4568

Merged
akshaydeo merged 2 commits into
maximhq:devfrom
G-XD:fix/issue_4402
Jun 28, 2026
Merged

fix: pass through gs:// image URLs on Vertex Gemini closes #4402#4568
akshaydeo merged 2 commits into
maximhq:devfrom
G-XD:fix/issue_4402

Conversation

@G-XD

@G-XD G-XD commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes Vertex Gemini support for gs:// image URLs.

Vertex AI accepts Google Cloud Storage URIs in Gemini FileData.fileUri, but Bifrost’s Vertex Gemini
path reused Gemini converters that only allowed http/https image URLs. This caused gs:// image blocks
to be rejected or dropped before reaching Vertex.

This PR adds explicit provider-level image URL scheme handling so Vertex can opt into gs:// while
Gemini keeps its default http/https behavior.

Changes

  • Added schemas.SanitizeImageURLWithAllowedSchemes to support provider-specific image URL scheme
    allowlists.
    • Kept schemas.SanitizeImageURL restricted to the default http/https behavior.
    • Updated Gemini chat and responses converters to accept an explicit image URL scheme allowlist.
    • Preserved the latest upstream ctx-based canonical model resolution in Gemini converters.
    • Added Vertex-local Gemini image URL allowlist:
      • http
      • https
      • gs
    • Updated Vertex Gemini request paths to pass the Vertex allowlist explicitly:
      • ChatCompletion
      • ChatCompletionStream
      • Responses
      • ResponsesStream
      • CountTokens
    • Changed Gemini image URL conversion to return explicit errors for invalid URLs instead of silently
      skipping image blocks. (This intentionally surfaces invalid image URL inputs instead of silently sending a request with missing image content.)
    • Updated Gemini batch conversion to propagate message conversion errors.
    • Added tests for:
      • default sanitizer rejecting non-HTTP schemes
      • explicit gs:// opt-in
      • empty allowlist behavior
      • data URL behavior
      • Gemini rejecting gs://
      • Vertex preserving gs:// as FileData.fileUri
      • Vertex rejecting unsupported schemes like file://
      • Vertex Gemini allowlist contract

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

cd core
go test ./schemas ./providers/gemini ./providers/vertex

Expected outcome: all tests pass.

Screenshots/Recordings

N/A. No UI changes.

Breaking changes

  • Yes
  • No

Invalid or unsupported image URL schemes in Gemini chat/responses inputs now return an explicit conversion error instead of silently dropping the image block. This may affect callers that relied on the previous partial-success behavior.

Related issues

Fixes #4402

Security considerations

The default image URL sanitizer remains restricted to http/https. Support for additional schemes such as
gs:// is explicit and scoped to the Vertex provider path, avoiding accidental broadening of URL handling
behavior across other providers.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 99dab4c6-512e-4849-abd2-a36bc169260d

📥 Commits

Reviewing files that changed from the base of the PR and between 6c972c5 and f7e5ead.

📒 Files selected for processing (3)
  • core/providers/gemini/gemini_test.go
  • core/providers/vertex/vertex.go
  • core/schemas/utils.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • core/providers/gemini/gemini_test.go
  • core/providers/vertex/vertex.go
  • core/schemas/utils.go

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added configurable image URL scheme allowlists for Gemini request conversion (including support for gs:// where enabled).
  • Bug Fixes
    • Conversions now fail fast on invalid or disallowed image/message URL schemes instead of continuing with incomplete requests.
  • Tests
    • Added regression coverage to ensure gs:// is accepted for Vertex Gemini where intended and rejected when not allowed, with assertions around expected request parts and error messages.

Walkthrough

Refactors image URL sanitization to use scheme allowlists, threads them through Gemini request conversion paths, and wires Vertex Gemini-family conversions to allow gs:// image URLs.

Changes

GCS image URL scheme allowlist

Layer / File(s) Summary
Schema sanitizer allowlist refactor
core/schemas/utils.go, core/schemas/utils_test.go
SanitizeImageURL delegates to a shared sanitizer, SanitizeImageURLWithAllowedSchemes is added, and validation now uses caller-provided allowlists with updated tests.
Gemini conversion allowlist threading
core/providers/gemini/utils.go, core/providers/gemini/batch.go, core/providers/gemini/videos.go, core/providers/gemini/responses.go
convertBifrostMessagesToGemini returns errors and uses an image URL scheme allowlist; Gemini content, video input, batch conversion, and responses generation paths pass the allowlist through.
Gemini public image URL scheme wrappers
core/providers/gemini/chat.go, core/providers/gemini/responses.go, core/providers/gemini/gemini_test.go
Public chat and responses converters now delegate to WithImageURLSchemes variants, and tests assert default wrappers reject gs:// image URLs.
Vertex Gemini allowlist wiring
core/providers/vertex/vertex.go, core/providers/vertex/utils_test.go, core/providers/vertex/vertex_test.go, core/changelog.md
Vertex adds geminiImageURLSchemes = []string{"http", "https", "gs"} and uses it for all Gemini-family request conversions; tests cover gs:// preservation and disallowed schemes, and the changelog notes the fix.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant vertex.go
  participant gemini converter
  participant sanitization

  Caller->>vertex.go: Gemini request with gs:// image URL
  vertex.go->>gemini converter: WithImageURLSchemes(..., [http,https,gs])
  gemini converter->>sanitization: sanitize image URL with allowlist
  sanitization-->>gemini converter: FileData for gs:// URL
  gemini converter-->>vertex.go: Gemini request payload
  vertex.go-->>Caller: forwards image block intact
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • danpiths
  • roroghost17
  • akshaydeo

Poem

🐰 I hopped through clouds and GCS streams,
gs:// now follows its dreams.
No more vanished image light,
Vertex carries it just right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.06% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the main fix: passing gs:// image URLs through Vertex Gemini.
Description check ✅ Passed The PR description follows the template and includes the required sections with relevant implementation and testing details.
Linked Issues check ✅ Passed The changes address #4402 by preserving gs:// image URLs for Vertex Gemini and adding coverage for the expected behavior.
Out of Scope Changes check ✅ Passed The refactors and sanitizer changes stay within the same image URL handling scope and do not introduce unrelated functionality.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai
coderabbitai Bot requested review from akshaydeo and danpiths June 20, 2026 02:13
@greptile-apps

greptile-apps Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 3/5

The gs:// fix is incomplete for the unary ChatCompletion path on Vertex Gemini, and there is an unchecked marshal error in the OpenAI fallback branch.

The unary ChatCompletion closure still routes all Gemini models through the old ToGeminiChatCompletionRequest converter (line 543), which lacks the geminiImageURLSchemes allowlist. The new converter at line 577 checks an identical predicate and is unreachable — a gs:// image URL sent via ChatCompletion to Vertex Gemini will now error rather than be accepted. Additionally, the MarshalSorted error in the OpenAI fallback branch (lines 601–603) is silently overwritten, meaning a marshal failure would propagate a nil body downstream. Both issues are in the changed code and neither is covered by the added tests.

core/providers/vertex/vertex.go — the ChatCompletion closure and the OpenAI fallback branch both need attention.

Important Files Changed

Filename Overview
core/providers/vertex/vertex.go ChatCompletion Gemini path still calls old ToGeminiChatCompletionRequest (no geminiImageURLSchemes), making the new else-if IsGeminiModelFamily branch dead code; also swallows MarshalSorted error in the OpenAI fallback branch.
core/schemas/utils.go Adds SanitizeImageURLWithAllowedSchemes alongside the original SanitizeImageURL; refactors into a shared sanitizeImageURL private function; correct gs:// host validation works.
core/providers/gemini/utils.go convertBifrostMessagesToGemini gains allowedImageURLSchemes variadic param and now returns an error instead of silently skipping; defaults preserved correctly via the defaultGeminiImageURLSchemes guard.
core/providers/gemini/responses.go ToGeminiResponsesRequest delegates to new ToGeminiResponsesRequestWithImageURLSchemes; all four convertContentBlockToGeminiPart call-sites are correctly threaded with the allowlist.
core/providers/vertex/vertex_test.go New tests cover gs:// preservation and unsupported scheme rejection but call the converter directly rather than exercising the vertex.ChatCompletion routing.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Vertex ChatCompletion request] --> B{IsAnthropicModelFamily?}
    B -- yes --> C[Anthropic converter]
    B -- no --> D[CheckContextAndGetRequestBody closure]
    D --> E{IsGeminiModelFamily? line 543}
    E -- yes --> F["ToGeminiChatCompletionRequest OLD - no geminiImageURLSchemes - gs:// returns ERROR"]
    E -- no --> G[ToOpenAIChatRequest]
    F --> H[Delete model field]
    G --> H
    H --> Z[Return body]
    D -.->|dead code - same condition| I["else if IsGeminiModelFamily? line 577"]
    I -- yes --> J["ToGeminiChatCompletionRequestWithImageURLSchemes NEW - http,https,gs - gs:// OK"]
    I -- no --> K[ToOpenAIChatRequest fallback]
    style F fill:#f88,color:#000
    style J fill:#8f8,color:#000
Loading
%%{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[Vertex ChatCompletion request] --> B{IsAnthropicModelFamily?}
    B -- yes --> C[Anthropic converter]
    B -- no --> D[CheckContextAndGetRequestBody closure]
    D --> E{IsGeminiModelFamily? line 543}
    E -- yes --> F["ToGeminiChatCompletionRequest OLD - no geminiImageURLSchemes - gs:// returns ERROR"]
    E -- no --> G[ToOpenAIChatRequest]
    F --> H[Delete model field]
    G --> H
    H --> Z[Return body]
    D -.->|dead code - same condition| I["else if IsGeminiModelFamily? line 577"]
    I -- yes --> J["ToGeminiChatCompletionRequestWithImageURLSchemes NEW - http,https,gs - gs:// OK"]
    I -- no --> K[ToOpenAIChatRequest fallback]
    style F fill:#f88,color:#000
    style J fill:#8f8,color:#000
Loading

Reviews (4): Last reviewed commit: "Merge branch 'dev' into fix/issue_4402" | Re-trigger Greptile

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 20, 2026
@akshaydeo
akshaydeo dismissed coderabbitai[bot]’s stale review June 21, 2026 11:44

The merge-base changed after approval.

@akshaydeo
akshaydeo requested a review from a team as a code owner June 21, 2026 11:44
@G-XD
G-XD force-pushed the fix/issue_4402 branch from a2034ce to 4c8006d Compare June 22, 2026 02:38
@CLAassistant

CLAassistant commented Jun 22, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@G-XD
G-XD force-pushed the fix/issue_4402 branch from 4c8006d to eb37e25 Compare June 22, 2026 02:46
Comment thread core/providers/gemini/utils.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/providers/vertex/vertex.go`:
- Around line 439-443: The issue is that when Content-Type is missing, the code
attempts to call SanitizeImageURL on raw base64-encoded bytes (the encoded
variable), but SanitizeImageURL expects a URL string, not raw bytes. To fix this
fallback media-type branch, instead of sanitizing the encoded bytes as a URL,
construct a proper data URL by prepending a data URL scheme with a default media
type (such as "data:image/jpeg;base64,") to the base64-encoded data before
assigning it to img.URL, which will inline the image correctly without requiring
sanitization.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f57fa475-4686-4890-b06f-92840d04e75c

📥 Commits

Reviewing files that changed from the base of the PR and between a2034ce and eb37e25.

📒 Files selected for processing (11)
  • core/providers/gemini/batch.go
  • core/providers/gemini/chat.go
  • core/providers/gemini/gemini_test.go
  • core/providers/gemini/responses.go
  • core/providers/gemini/utils.go
  • core/providers/gemini/videos.go
  • core/providers/vertex/utils_test.go
  • core/providers/vertex/vertex.go
  • core/providers/vertex/vertex_test.go
  • core/schemas/utils.go
  • core/schemas/utils_test.go
🚧 Files skipped from review as they are similar to previous changes (8)
  • core/providers/gemini/videos.go
  • core/providers/gemini/batch.go
  • core/providers/vertex/utils_test.go
  • core/providers/gemini/utils.go
  • core/schemas/utils_test.go
  • core/schemas/utils.go
  • core/providers/vertex/vertex_test.go
  • core/providers/gemini/responses.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/providers/vertex/vertex.go`:
- Around line 439-443: The issue is that when Content-Type is missing, the code
attempts to call SanitizeImageURL on raw base64-encoded bytes (the encoded
variable), but SanitizeImageURL expects a URL string, not raw bytes. To fix this
fallback media-type branch, instead of sanitizing the encoded bytes as a URL,
construct a proper data URL by prepending a data URL scheme with a default media
type (such as "data:image/jpeg;base64,") to the base64-encoded data before
assigning it to img.URL, which will inline the image correctly without requiring
sanitization.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f57fa475-4686-4890-b06f-92840d04e75c

📥 Commits

Reviewing files that changed from the base of the PR and between a2034ce and eb37e25.

📒 Files selected for processing (11)
  • core/providers/gemini/batch.go
  • core/providers/gemini/chat.go
  • core/providers/gemini/gemini_test.go
  • core/providers/gemini/responses.go
  • core/providers/gemini/utils.go
  • core/providers/gemini/videos.go
  • core/providers/vertex/utils_test.go
  • core/providers/vertex/vertex.go
  • core/providers/vertex/vertex_test.go
  • core/schemas/utils.go
  • core/schemas/utils_test.go
🚧 Files skipped from review as they are similar to previous changes (8)
  • core/providers/gemini/videos.go
  • core/providers/gemini/batch.go
  • core/providers/vertex/utils_test.go
  • core/providers/gemini/utils.go
  • core/schemas/utils_test.go
  • core/schemas/utils.go
  • core/providers/vertex/vertex_test.go
  • core/providers/gemini/responses.go
🛑 Comments failed to post (1)
core/providers/vertex/vertex.go (1)

439-443: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fallback media-type branch currently rejects valid remote images.

At Line 439, schemas.SanitizeImageURL(encoded) is called with raw base64 bytes (not a URL), so this path errors when Content-Type is missing instead of inlining the image.

Suggested fix
@@
-				} else {
-					// Content-Type header absent; sniff the media type from the
-					// fetched bytes so we never emit a malformed "data:;base64,..."
-					// URI, which Anthropic-on-Vertex rejects.
-					sanitized, sErr := schemas.SanitizeImageURL(encoded)
-					if sErr != nil {
-						return sErr
-					}
-					img.URL = sanitized
-				}
+				} else {
+					// Content-Type header absent; sniff media type from bytes and
+					// still emit a valid data URI.
+					decoded, decodeErr := base64.StdEncoding.DecodeString(encoded)
+					if decodeErr != nil {
+						return fmt.Errorf("failed to decode fetched image for data URI: %w", decodeErr)
+					}
+					detectedType := http.DetectContentType(decoded)
+					img.URL = "data:" + detectedType + ";base64," + encoded
+				}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/providers/vertex/vertex.go` around lines 439 - 443, The issue is that
when Content-Type is missing, the code attempts to call SanitizeImageURL on raw
base64-encoded bytes (the encoded variable), but SanitizeImageURL expects a URL
string, not raw bytes. To fix this fallback media-type branch, instead of
sanitizing the encoded bytes as a URL, construct a proper data URL by prepending
a data URL scheme with a default media type (such as "data:image/jpeg;base64,")
to the base64-encoded data before assigning it to img.URL, which will inline the
image correctly without requiring sanitization.

@G-XD

G-XD commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/providers/vertex/vertex.go`:
- Around line 439-443: The issue is that when Content-Type is missing, the code
attempts to call SanitizeImageURL on raw base64-encoded bytes (the encoded
variable), but SanitizeImageURL expects a URL string, not raw bytes. To fix this
fallback media-type branch, instead of sanitizing the encoded bytes as a URL,
construct a proper data URL by prepending a data URL scheme with a default media
type (such as "data:image/jpeg;base64,") to the base64-encoded data before
assigning it to img.URL, which will inline the image correctly without requiring
sanitization.

🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f57fa475-4686-4890-b06f-92840d04e75c

📥 Commits
Reviewing files that changed from the base of the PR and between a2034ce and eb37e25.

📒 Files selected for processing (11)

  • core/providers/gemini/batch.go
  • core/providers/gemini/chat.go
  • core/providers/gemini/gemini_test.go
  • core/providers/gemini/responses.go
  • core/providers/gemini/utils.go
  • core/providers/gemini/videos.go
  • core/providers/vertex/utils_test.go
  • core/providers/vertex/vertex.go
  • core/providers/vertex/vertex_test.go
  • core/schemas/utils.go
  • core/schemas/utils_test.go

🚧 Files skipped from review as they are similar to previous changes (8)

  • core/providers/gemini/videos.go
  • core/providers/gemini/batch.go
  • core/providers/vertex/utils_test.go
  • core/providers/gemini/utils.go
  • core/schemas/utils_test.go
  • core/schemas/utils.go
  • core/providers/vertex/vertex_test.go
  • core/providers/gemini/responses.go

🛑 Comments failed to post (1)

core/providers/vertex/vertex.go (1)> 439-443: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fallback media-type branch currently rejects valid remote images.
At Line 439, schemas.SanitizeImageURL(encoded) is called with raw base64 bytes (not a URL), so this path errors when Content-Type is missing instead of inlining the image.

Suggested fix

@@
-				} else {
-					// Content-Type header absent; sniff the media type from the
-					// fetched bytes so we never emit a malformed "data:;base64,..."
-					// URI, which Anthropic-on-Vertex rejects.
-					sanitized, sErr := schemas.SanitizeImageURL(encoded)
-					if sErr != nil {
-						return sErr
-					}
-					img.URL = sanitized
-				}
+				} else {
+					// Content-Type header absent; sniff media type from bytes and
+					// still emit a valid data URI.
+					decoded, decodeErr := base64.StdEncoding.DecodeString(encoded)
+					if decodeErr != nil {
+						return fmt.Errorf("failed to decode fetched image for data URI: %w", decodeErr)
+					}
+					detectedType := http.DetectContentType(decoded)
+					img.URL = "data:" + detectedType + ";base64," + encoded
+				}

🤖 Prompt for AI Agents

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/providers/vertex/vertex.go` around lines 439 - 443, The issue is that
when Content-Type is missing, the code attempts to call SanitizeImageURL on raw
base64-encoded bytes (the encoded variable), but SanitizeImageURL expects a URL
string, not raw bytes. To fix this fallback media-type branch, instead of
sanitizing the encoded bytes as a URL, construct a proper data URL by prepending
a data URL scheme with a default media type (such as "data:image/jpeg;base64,")
to the base64-encoded data before assigning it to img.URL, which will inline the
image correctly without requiring sanitization.

Thanks @coderabbitai, but I don't think this is correct on two counts:

  1. Out of scope. This inlineRemoteURLSources / dataURLFromBase64Image
    path is existing code on dev (Anthropic-on-Vertex URL inlining). It
    is not touched by this PR, which only adds gs:// scheme support for
    the Gemini converter (issue [Bug]: Vertex provider drops image blocks whose URL uses gs:// scheme #4402).

  2. Factually incorrect. SanitizeImageURL(encoded) does not error on
    raw base64 input. The function checks isLikelyBase64 before
    attempting URL parsing — a base64 string matches base64Regex and
    flows through detectImageTypeFromBase64, which sniffs known image
    signatures (PNG/JPEG/GIF/BMP/WebP/SVG) and falls back to image/jpeg
    for unrecognized payloads. It always returns a valid data: URL on
    this path. The URL/scheme validation branch is unreachable for raw
    base64 input. This is the documented intent of using it as a fallback
    in dataURLFromBase64Image (see the comment at the call site).

So no fix needed here.

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@G-XD, you're absolutely right on both counts — I apologize for the noise.

  1. Out of scope: The inlineRemoteURLSources / dataURLFromBase64Image path is pre-existing Anthropic-on-Vertex code untouched by this PR; I should not have flagged it here.
  2. Factually incorrect: The isLikelyBase64 guard in SanitizeImageURL means raw base64 input never reaches the URL/scheme validation branch — it flows through detectImageTypeFromBase64 and always produces a valid data: URI. My concern was unfounded.

No fix needed here. Thanks for the detailed explanation.

🐇


✏️ Learnings added
Learnt from: G-XD
URL: https://github.com/maximhq/bifrost/pull/4568

Timestamp: 2026-06-24T02:59:01.298Z
Learning: In `core/providers/vertex/vertex.go`, the `dataURLFromBase64Image` helper calls `schemas.SanitizeImageURL(encoded)` where `encoded` is a raw base64 string (not a URL). This is safe because `SanitizeImageURL` in `core/schemas/utils.go` checks `isLikelyBase64` *before* attempting URL parsing. A base64 string matches `base64Regex` and is routed through `detectImageTypeFromBase64`, which sniffs image signatures (PNG/JPEG/GIF/BMP/WebP/SVG) and falls back to `image/jpeg`, always returning a valid `data:` URI. The URL/scheme validation branch is unreachable for raw base64 input. This is intentional and correct behavior.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@G-XD
G-XD force-pushed the fix/issue_4402 branch from eb37e25 to 6c972c5 Compare June 24, 2026 09:14
@coderabbitai
coderabbitai Bot requested a review from Pratham-Mishra04 June 24, 2026 09:15
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 24, 2026
Signed-off-by: Akshay Deo <akshay@akshaydeo.com>
@coderabbitai
coderabbitai Bot requested review from akshaydeo and roroghost17 June 28, 2026 06:27
@akshaydeo
akshaydeo merged commit fe6ce5c into maximhq:dev Jun 28, 2026
5 of 6 checks passed
@G-XD
G-XD deleted the fix/issue_4402 branch June 29, 2026 02:10
akshaydeo added a commit that referenced this pull request Jun 30, 2026
Signed-off-by: Akshay Deo <akshay@akshaydeo.com>
Co-authored-by: Akshay Deo <akshay@akshaydeo.com>
@coderabbitai coderabbitai Bot mentioned this pull request Jun 30, 2026
7 tasks
R-droid101 pushed a commit to R-droid101/bifrost that referenced this pull request Jul 1, 2026
… (maximhq#4568)

Signed-off-by: Akshay Deo <akshay@akshaydeo.com>
Co-authored-by: Akshay Deo <akshay@akshaydeo.com>
akshaydeo added a commit that referenced this pull request Jul 1, 2026
Signed-off-by: Akshay Deo <akshay@akshaydeo.com>
Co-authored-by: Akshay Deo <akshay@akshaydeo.com>
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.

[Bug]: Vertex provider drops image blocks whose URL uses gs:// scheme

3 participants