Skip to content

fix: resolve base URL in createLanguageModel for API gateway support#565

Merged
buger merged 1 commit into
mainfrom
fix/dedup-base-url
May 21, 2026
Merged

fix: resolve base URL in createLanguageModel for API gateway support#565
buger merged 1 commit into
mainfrom
fix/dedup-base-url

Conversation

@buger
Copy link
Copy Markdown
Collaborator

@buger buger commented May 21, 2026

Summary

  • createLanguageModel() in npm/src/utils/provider.js resolved API keys but not base URLs from env vars
  • This caused dedup LLM calls to bypass API gateways and hit provider endpoints directly, failing with "API key not valid" when using gateway-issued keys
  • Added resolveBaseUrl() mirroring the env-var pattern already used by ProbeAgent and FallbackManager

Problem

When GOOGLE_API_URL points to an API gateway and GOOGLE_API_KEY is a gateway-issued key (not a raw Google key), the main AI calls work fine (they pass baseURL), but dedup calls fail because createLanguageModel() only passed apiKey without baseURL. Every dedup failure silently falls back to allow, letting all redundant searches through — causing tasks to run 5-6x longer than necessary.

Test plan

  • Verify dedup calls route through GOOGLE_API_URL when set
  • Verify no regression when GOOGLE_API_URL is not set (hits provider default)
  • Verify LLM_BASE_URL fallback works for all providers

Fixes #564

🤖 Generated with Claude Code

createLanguageModel() resolved API keys from env vars but not base URLs.
This caused dedup LLM calls to bypass API gateways (GOOGLE_API_URL, etc.)
and hit provider endpoints directly, failing with "API key not valid"
when using gateway-issued keys.

Add resolveBaseUrl() mirroring the env-var resolution already used by
ProbeAgent and FallbackManager, and pass it to createProviderInstance().

Fixes #564

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@probelabs
Copy link
Copy Markdown
Contributor

probelabs Bot commented May 21, 2026

PR Overview

Summary

This PR fixes a critical bug where createLanguageModel() in npm/src/utils/provider.js resolved API keys but not base URLs from environment variables. This caused deduplication LLM calls to bypass API gateways and hit provider endpoints directly, resulting in authentication failures when using gateway-issued keys.

Problem Statement

When GOOGLE_API_URL (or similar provider-specific URL env vars) points to an API gateway and the API key is a gateway-issued credential (not a raw provider key), the main AI calls work correctly because they pass baseURL through the full request pipeline. However, deduplication calls failed because createLanguageModel() only resolved and passed apiKey without baseURL. This caused every dedup request to fail with "API key not valid" errors, silently falling back to allow, which let all redundant searches through—causing tasks to run 5-6x longer than necessary.

Technical Changes

File Modified: npm/src/utils/provider.js (+26 lines, -2 lines)

  1. Added resolveBaseUrl() function (lines 87-107):

    • Mirrors the environment variable resolution pattern already used by ProbeAgent and FallbackManager
    • Supports provider-specific URL overrides:
      • ANTHROPIC_API_URL / ANTHROPIC_BASE_URL
      • OPENAI_API_URL
      • GOOGLE_API_URL
      • AWS_BEDROCK_BASE_URL
    • Falls back to LLM_BASE_URL for any provider
    • Returns undefined if no URL is configured (preserving default provider behavior)
  2. Updated createLanguageModel() function (line 124):

    • Now calls resolveBaseUrl() to get the gateway URL
    • Passes baseURL to createProviderInstance() alongside apiKey
    • Maintains graceful degradation (returns null on failure)

Architecture & Impact

Component Flow:

Environment Variables (GOOGLE_API_URL, LLM_BASE_URL, etc.)
    ↓
resolveBaseUrl() → baseURL string | undefined
    ↓
createLanguageModel() → provider instance with baseURL
    ↓
Dedup LLM calls → Route through API gateway
    ↓
Successful authentication with gateway-issued keys

Affected Systems:

  • Deduplication system: Now correctly routes through API gateways
  • LLM provider abstraction: Consistent URL resolution across all lightweight LLM calls
  • API gateway deployments: Can now use gateway-issued credentials for all LLM interactions

Before/After Behavior:

  • Before: Dedup calls hit provider endpoints directly → auth failures → silent fallback → 5-6x slower tasks
  • After: Dedup calls route through gateway → successful auth → proper deduplication → optimal performance

Scope & Context

Direct Impact:

  • All lightweight LLM calls (deduplication, etc.) now respect API gateway configuration
  • Consistent behavior between main AI calls and auxiliary LLM operations

Related Components (inferred from codebase structure):

  • ProbeAgent: Already implements similar URL resolution logic
  • FallbackManager: Already implements similar URL resolution logic
  • Environment configuration: GOOGLE_API_URL, LLM_BASE_URL, provider-specific URLs

Testing Considerations:

  • Verify dedup calls route through GOOGLE_API_URL when set
  • Verify no regression when GOOGLE_API_URL is not set (hits provider default)
  • Verify LLM_BASE_URL fallback works for all providers
  • Test with gateway-issued credentials vs. raw provider keys

References

Metadata
  • Review Effort: 2 / 5
  • Primary Label: bug

Powered by Visor from Probelabs

Last updated: 2026-05-21T13:32:54.473Z | Triggered by: pr_opened | Commit: 5fef1e0

💡 TIP: You can chat with Visor using /visor ask <your question>

@buger buger merged commit a3df0bd into main May 21, 2026
17 checks passed
@buger buger deleted the fix/dedup-base-url branch May 21, 2026 13:22
@probelabs
Copy link
Copy Markdown
Contributor

probelabs Bot commented May 21, 2026

Security Issues (3)

Severity Location Issue
🟡 Warning npm/src/utils/provider.js:87-109
The resolveBaseUrl() function reads base URLs directly from environment variables without any validation or sanitization. This could enable Server-Side Request Forgery (SSRF) attacks if an attacker can manipulate environment variables (e.g., through .env file injection, process.env manipulation in vulnerable code, or compromised CI/CD pipelines). Malicious URLs like 'file:///etc/passwd', 'http://169.254.169.254/latest/meta-data/' (AWS IMDSv1), or internal network addresses could be used to exfiltrate data or access internal services.
💡 SuggestionAdd URL validation to ensure base URLs use allowed protocols (https://, http://) and optionally restrict to allowed domains or block private/internal network ranges. Consider implementing a whitelist of allowed base URL patterns or adding validation similar to the MCP client's URL constructor usage (see probe/npm/src/agent/mcp/client.js:96-97).
🟡 Warning npm/src/utils/provider.js:121-122
The resolved baseURL is passed directly to createProviderInstance() without validation. While the underlying AI SDK providers may have their own validation, this creates a trust boundary issue. The codebase demonstrates security-conscious patterns elsewhere (e.g., path-validation.js with symlink attack prevention, bashPermissions.js for command validation), but URL validation is missing here.
💡 SuggestionConsider adding a validateBaseUrl() function that checks URL format, protocol, and optionally domain allowlists. This would align with the codebase's defense-in-depth approach seen in path validation and DSL code validation.
🟡 Warning npm/src/utils/provider.js:87-109
Base URLs from environment variables are used without sanitization, which could lead to information disclosure if malicious URLs contain credentials or sensitive data in query parameters that might be logged or exposed in error messages.
💡 SuggestionStrip credentials and sensitive query parameters from URLs before use, or ensure that logging and error handling throughout the codebase sanitizes URLs to prevent credential leakage.

✅ Performance Check Passed

No performance issues found – changes LGTM.

Quality Issues (4)

Severity Location Issue
🟡 Warning npm/src/utils/provider.js:95
The new resolveBaseUrl() function lacks dedicated unit tests. While it mirrors existing patterns in ProbeAgent and FallbackManager, the function has no test coverage for environment variable resolution, provider-specific URL fallback logic, or edge cases like undefined provider names.
💡 SuggestionAdd a dedicated test file (provider.test.js) or extend existing tests to verify: 1) Provider-specific URLs take precedence over LLM_BASE_URL, 2) LLM_BASE_URL fallback works for all providers, 3) Unknown providers return LLM_BASE_URL, 4) All environment variable combinations work correctly.
🟡 Warning npm/src/utils/provider.js:95
No integration tests verify that dedup LLM calls actually route through the resolved base URLs. The fix addresses a critical production issue where dedup calls bypassed API gateways, but there's no test ensuring this behavior works end-to-end.
💡 SuggestionAdd integration test that mocks an API gateway scenario: set GOOGLE_API_URL to a custom endpoint, verify createLanguageModel produces a provider with that baseURL, and confirm dedup calls use the configured gateway URL rather than the default Google endpoint.
🟡 Warning npm/src/utils/provider.js:95
The resolveBaseUrl() function duplicates environment variable resolution logic already present in ProbeAgent.initializeModel() and FallbackManager.buildFallbackProvidersFromEnv(). This creates triple maintenance burden for the same logic.
💡 SuggestionConsider consolidating base URL resolution into a single shared utility or configuration object to avoid synchronization issues. Alternatively, add JSDoc comments explicitly referencing the other implementations to maintain awareness of the duplication.
🟡 Warning npm/src/utils/provider.js:121
createLanguageModel() uses a broad catch-all try-catch that returns null on any error, silently hiding configuration issues. This makes debugging difficult when baseURL resolution fails due to invalid URLs or provider configuration.
💡 SuggestionConsider logging errors in debug mode or differentiating between expected failures (missing API keys) and unexpected errors (invalid URLs, provider instantiation failures). At minimum, add console.error in debug mode to aid troubleshooting.

Powered by Visor from Probelabs

Last updated: 2026-05-21T13:28:13.568Z | Triggered by: pr_opened | Commit: 5fef1e0

💡 TIP: You can chat with Visor using /visor ask <your question>

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.

Dedup LLM ignores GOOGLE_API_URL base URL — fails with API gateway keys

1 participant