Skip to content

fix(capture): validate the Vertex region and model id before captioning - #7533

Merged
michaelwang11394 merged 2 commits into
mainfrom
harden-r3-binaries
Nov 11, 2026
Merged

michaelwang11394 merged 2 commits into
mainfrom
harden-r3-binaries

Conversation

@michaelwang11394

@michaelwang11394 michaelwang11394 commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

What changed

hyperframes capture captions images with Vertex AI. It reads the region (HYPERFRAMES_VERTEX_LOCATION) and the model id from the environment, which can come from a project's .env file. The Google SDK builds the request host from the region and the request path from the model id.

  • The region must be a plain Google Cloud location name: lowercase letters, digits and hyphens. This covers every regional location (for example us-central1, europe-west4, me-central2), the us and eu multi-regions, and global. A region can no longer contain a ., /, @, : or #, so the request host always stays on googleapis.com.
  • The model id must be one or more /-separated segments. Each segment starts with a letter or digit and contains only letters, digits, _, ., -, @ and :. This rejects % (which can encode ..), ?, #, a leading / and empty segments. A colon is allowed inside a segment because Vertex endpoint paths in domain-scoped projects contain one (projects/example.com:proj/...); it cannot change the request host.
  • If either check fails, captioning is skipped with a warning before a Google client is created, so no token is fetched and no request is sent.

Every real region and Google model id behaves exactly as before, including the defaults (us-central1, gemini-2.5-flash, gemini-3.1-flash-lite-preview). OpenRouter model ids are not checked, because they go in the request body rather than the URL.

Not done

  • hyperframes snapshot --describe also reads HYPERFRAMES_GEMINI_MODEL, and it is not checked here. That path uses a Gemini API key on a fixed host, and the SDK already rejects .., ? and & in model ids.
  • HYPERFRAMES_VERTEX_PROJECT_ID also goes into the request path and is not checked. It cannot change the request host.

Testing

  • New cases in packages/cli/src/capture/contentExtractor.test.ts: 10 rejection cases (5 regions, 5 model ids) that fail without the fix, plus accepted regions (global, us, eu, europe-west4) and accepted model ids (a bare id, publisher/model, a Model Garden id with @version, and a domain-scoped endpoint path). All 46 tests in the file pass.
  • Lint, format, comment ratchet, fallow and typecheck hooks pass.
  • Not run against a live Vertex project. Not run on Windows (no platform-specific code).

🤖 Generated with Claude Code

michaelwang11394 and others added 2 commits November 10, 2026 18:49
Vision captioning passes the region and model id to the Google SDK, which
builds the request host from the region and the request path from the model
id. A region that is not a plain Google Cloud region name, or a model id with
URL delimiters, now skips captioning with a warning instead of building a
request. Every real region (including "global") and model id still works.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Vertex endpoint paths in domain-scoped projects contain a colon
(projects/example.com:proj/...). The colon cannot change the request host,
so allow it inside a segment. Leading slashes, empty segments, percent
signs, query and fragment delimiters stay rejected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@heygengenesis heygengenesis 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.

Verdict: APPROVE · 0 blocker · 0 important · 0 nits · head 9bca2d9

I checked this against @google/genai 1.52.0. The SDK builds the Vertex host as https://${location}-aiplatform.googleapis.com/ (or the fixed global, us and eu hosts) and adds the model path by string concatenation. A location limited to [a-z][a-z0-9-]* therefore can't change the host. PROJECT_ENV_KEYS doesn't include GOOGLE_VERTEX_BASE_URL or GOOGLE_GEMINI_BASE_URL, so a project .env can't move the request somewhere else either. The model check adds % rejection on top of the SDK's own ../?/& rejection, which covers WHATWG %2e%2e dot segments.

— Genesis V2

@michaelwang11394
michaelwang11394 added this pull request to the merge queue Nov 11, 2026
Merged via the queue into main with commit bcc1437 Nov 11, 2026
74 of 75 checks passed
@michaelwang11394
michaelwang11394 deleted the harden-r3-binaries branch November 11, 2026 03:49
@miguel-heygen miguel-heygen mentioned this pull request Nov 11, 2026
3 of 4 tasks
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.

1 participant