Skip to content

fix(api): require HTTPS for custom Google Gemini base URLs (CWE-319) - #2033

Open
easonLiangWorldedtech wants to merge 1 commit into
Zoo-Code-Org:mainfrom
easonLiangWorldedtech:feat/gemini-https-endpoint-policy
Open

easonLiangWorldedtech wants to merge 1 commit into
Zoo-Code-Org:mainfrom
easonLiangWorldedtech:feat/gemini-https-endpoint-policy

Conversation

@easonLiangWorldedtech

@easonLiangWorldedtech easonLiangWorldedtech commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

What this does

googleGeminiBaseUrl is user-editable (settings, imported profiles), and the @google/genai client keeps API-key authentication for custom endpoints. Before this PR a cleartext custom base URL was accepted as-is, so the API key could be sent over an insecure endpoint (CWE-319).

This PR validates the custom endpoint before any request is built, in both createMessage and completePrompt:

  • HTTPS is required for custom Gemini base URLs.
  • Loopback HTTP stays allowed for local test proxies: http://localhost, http://[::1], and literal 127.0.0.0/8 IPv4 hosts.
  • Hostnames that merely resemble the loopback range are rejected: 127.example.test, 127.0.0.a, 127.0.a.b, 127.0.0.1.a, foo127.bar, and hosts outside the range such as 10.0.0.1.
  • Non-HTTP schemes (ftp://localhost) and malformed URLs are rejected.
  • Violations surface as a structured ApiProviderError (provider/model/operation context) before the request is built, so the key never leaves the process.

Content source

Carved out of the fork-side abort-signal provider rollout (fork PR #1303) at the maintainer's request: this endpoint policy changes which custom endpoints are accepted independently of cancellation, so separating it keeps that rollout reviewable. The helpers, guards, and security tests are ported from that rollout branch (the test block is re-nested to this file's structure); the rollout's timeout plumbing stays in that PR.

Budget

  • 2 files changed, +579 / -0 against main.
  • Production code: 66 lines in src/api/providers/gemini.ts (three module-private helpers plus two call-site guards); the remaining 513 lines are the security test matrix in src/api/providers/__tests__/gemini.spec.ts.
  • Changed executable lines are far below the CI cap; the size above the 400 soft cap is entirely test cases pinning the loopback boundary.

How to test

  1. Set googleGeminiBaseUrl to http://gemini.example.test and run any Gemini request → it fails with "Google Gemini base URL must use HTTPS (or a loopback HTTP endpoint for local test proxies)" before the request is sent.
  2. Set it to http://127.0.0.1:8080 (or http://localhost, http://[::1]) → the request proceeds against the local proxy.
  3. Focused suite from src/: vitest run --globals api/providers/__tests__/gemini.spec.ts.

Verification at this head

  • vitest run --globals --no-file-parallelism api/providers/__tests__/gemini.spec.ts api/providers/__tests__/gemini-handler.spec.ts → 63/63 passed.
  • Negative control: reverting the gemini.ts guards turns exactly the 11 reject tests red while the 5 loopback-allow tests stay green in both directions; byte-exact restore returns all green.
  • eslint --max-warnings=0 on both changed files → 0 errors / 0 warnings; suppression counts unchanged.
  • tsc --noEmit → 0 errors.
  • prettier --check → clean.

googleGeminiBaseUrl is user-editable (settings, imported profiles) and the
@google/genai client keeps API-key authentication for custom endpoints, so a
cleartext base URL would send the API key over an insecure endpoint (CWE-319).

Validate the endpoint before any request in createMessage and completePrompt:
HTTPS is required; plain HTTP is accepted only for loopback test proxies
(localhost, [::1], and literal 127.0.0.0/8 IPv4 hosts). Hostnames that merely
resemble the loopback range (127.example.test, 127.0.0.a, 127.0.0.1.a,
foo127.bar) or fall outside it (10.0.0.1) are rejected, as are non-HTTP
schemes such as ftp://localhost and malformed URLs. Violations surface as a
structured ApiProviderError before the request is built, so the key never
leaves the process.

Carved out of the abort-signal provider rollout (fork PR 1303) at the
maintainer's request so the endpoint policy can be reviewed independently of
the cancellation changes.
@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: Zoo-Code-Org/Zoo-Code/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 9888d633-680f-4548-a905-99c54902504c
📥 Commits

Reviewing files that changed from the base of the PR and between af28417 and ee0090f.

📒 Files selected for processing (2)
  • src/api/providers/__tests__/gemini.spec.ts
  • src/api/providers/gemini.ts

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 1 remain after this review.

📜 Recent review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Zoo Code / resolve PRs to reconcile
🧰 Additional context used
📓 Path-based instructions (5)
Treat model, provider, MCP, path, command, and tool data as untrusted.

⚙️ CodeRabbit configuration file

Files:

  • src/api/providers/gemini.ts
  • src/api/providers/__tests__/gemini.spec.ts
Require regression coverage at the lowest valid harness with behavior-focused assertions, including relevant negative, error, false/unset, and boundary cases.

⚙️ CodeRabbit configuration file

Files:

  • src/api/providers/__tests__/gemini.spec.ts
Check strict typing and exhaustive behavior across normal, boundary, error, cancellation, retry, and compatibility paths.

⚙️ CodeRabbit configuration file

Files:

  • src/api/providers/gemini.ts
  • src/api/providers/__tests__/gemini.spec.ts
Verify extension/webview contracts, cancellation and error propagation, VS Code lifecycle correctness, and behavior under retries and partial failure.

⚙️ CodeRabbit configuration file

Files:

  • src/api/providers/gemini.ts
  • src/api/providers/__tests__/gemini.spec.ts
Act as an adversarial second-opinion reviewer.

⚙️ CodeRabbit configuration file

Files:

  • src/api/providers/gemini.ts
  • src/api/providers/__tests__/gemini.spec.ts
🪛 GitHub Check: mutation-diff
src/api/providers/gemini.ts

[warning] 213-213: Mutation test advisory
src/api/providers/gemini.ts:213: 2 mutation test gaps; example: Survived ConditionalExpression mutant (replacement: false). See the job summary for the complete list and resolution guidance.

🔇 Additional comments (4)
src/api/providers/gemini.ts (3)

175-226: LGTM!

352-357: LGTM!

652-658: LGTM!

src/api/providers/__tests__/gemini.spec.ts (1)

440-944: LGTM!

📝 Summary

Summary by CodeRabbit

  • Bug Fixes
    • Gemini requests now reject invalid base URLs before contacting the service. HTTPS URLs are accepted; HTTP is allowed only for localhost and loopback addresses.
    • Invalid URLs, unsupported schemes, and non-loopback HTTP hosts are rejected for both streaming and prompt-completion requests.

Gemini requests now validate configured base URLs before request construction. HTTPS URLs are accepted. HTTP URLs are accepted only for localhost, [::1], or IPv4 addresses in 127.0.0.0/8. Tests cover valid and invalid URLs for both request operations.

Changes: Gemini base URL validation

Layer / File(s) Summary
URL validation policy and coverage
src/api/providers/gemini.ts, src/api/providers/__tests__/gemini.spec.ts
The validation helper rejects malformed URLs and HTTP URLs outside the specified loopback hosts. Tests cover HTTPS, valid loopback URLs, non-loopback hosts, and unsupported schemes.
Request-path validation
src/api/providers/gemini.ts
createMessage and completePrompt validate the configured URL before constructing requests. Errors include provider, model, and operation context.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to ee009

No actionable risk remains from this change after normal checks.

Pre-merge checks · Passed 6 · Failed 2

Failed Failed checks (2 warnings)

Check name Status Explanation Resolution
Regression Evidence Warning HTTPS custom base URL acceptance lacks focused coverage. The changed helper returns immediately for parsed.protocol === "https:" at src/api/providers/gemini.ts:213-215, and both request paths invo… Add focused provider tests with a valid non-loopback https:// googleGeminiBaseUrl. Exercise both completePrompt and createMessage, and assert that each client method is called with the HTTPS base URL.
Description check Warning The description provides detailed implementation, security rationale, testing steps, and verification results. However, it does not link an approved GitHub Issue and does not complete the required pre… Add an approved issue reference, such as "Closes: #123", complete the pre-submission checklist, and fill in the required documentation impact and contributor contact sections.
Passed Passed checks (6 passed)
Check name Status Explanation
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Security Boundaries Passed No concrete changed path matches the failure conditions. In src/api/providers/gemini.ts:175-226, googleGeminiBaseUrl is parsed with new URL; HTTPS is accepted, while HTTP is accepted only for `l…
Persistence Integrity Passed No changed persistence path exists. The production diff adds URL parsing and validation helpers, plus guards before Gemini requests in createMessage and completePrompt. The test-only diff adds val…
Lifecycle Resource Cleanup Passed PASS — The pull request adds URL parsing and validation in GeminiHandler.createMessage and completePrompt, plus security tests. The changed production lines create no listener, watcher, timer, tas…
Title check Passed The title clearly identifies the main change: requiring HTTPS for custom Google Gemini base URLs to address CWE-319.
Full details: Regression Evidence

Explanation

HTTPS custom base URL acceptance lacks focused coverage. The changed helper returns immediately for parsed.protocol === "https:" at src/api/providers/gemini.ts:213-215, and both request paths invoke it at lines 354-356 and 654-657. The new Gemini tests cover undefined URLs, loopback HTTP acceptance, and many rejection cases, but they contain no googleGeminiBaseUrl value using https://. A regression that rejects all custom HTTPS endpoints would pass the current tests.

Full details: Description check

Explanation

The description provides detailed implementation, security rationale, testing steps, and verification results. However, it does not link an approved GitHub Issue and does not complete the required pre-submission checklist or template sections.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@codecov

codecov Bot commented Oct 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.23529% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/api/providers/gemini.ts 88.23% 1 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@easonLiangWorldedtech

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Review status

Thanks for contributing. This comment tracks the review sequence and the next action.

Current step: Awaiting fresh human maintainer or CODEOWNER approval.

Automated review is complete for the latest commit but does not replace human approval.

Review-state labels are managed by this workflow; do not edit them manually. community-approved is managed the same way — do not add or remove it manually. It signals a fresh community code approval for the current head as an advisory priority only; maintainer review is still required.

@github-actions github-actions Bot added the awaiting-maintainer CodeRabbit approved; waiting for a human maintainer label Oct 13, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-maintainer CodeRabbit approved; waiting for a human maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants