Skip to content

fix(cli): let veryfront eval reach an operator-set private Veryfront API - #4506

Merged
kojiwakayama merged 2 commits into
mainfrom
fix/cli-staging-internal-api-egress
Sep 16, 2026
Merged

kojiwakayama merged 2 commits into
mainfrom
fix/cli-staging-internal-api-egress

Conversation

@kojiwakayama

Copy link
Copy Markdown
Contributor

Description

veryfront eval against the staging Veryfront API failed every record with Outbound network egress blocked for host: <host>, and gateway billing finalization was skipped the same way. The staging API is reachable only over the tailnet, so its public DNS answer is a private address. The host egress guard rejects that as request forgery for both the Veryfront Cloud gateway fetch and billing finalization.

Root cause:

  • src/security/sandbox/worker-egress-guard.ts (resolveWorkerHostEgressAddresses) throws Worker network egress blocked for host for a private DNS answer. src/security/http/outbound-fetch.ts (fetchWithBoundaryErrors) rethrows it as OutboundRequestBlockedError.
  • src/provider/veryfront-cloud/shared.ts (createVeryfrontCloudFetch) and cli/commands/eval/command.ts (finalizeGatewayBillingGroup) both use createOriginBoundOutboundFetch(apiBaseUrl). The only exemptions were VERYFRONT_HOST_ALLOWED_INTERNAL_PROVIDER_ORIGINS and VERYFRONT_HOST_ALLOW_INTERNAL_EGRESS.

Fix:

  • evalCommand calls trustOperatorConfiguredVeryfrontApiOrigins() before it loads project config or agent modules. The call seals the origins of VERYFRONT_API_URL and VERYFRONT_API_BASE_URL from the process environment, read through getHostEnvExcludingEnvFile.
  • The new createVeryfrontApiOriginBoundOutboundFetch() lets exactly those origins resolve to a private address. The Veryfront Cloud gateway fetch and billing finalization use it.

Security reasoning:

  • Only the operator's shell or CI environment counts. Values from a project .env file, veryfront.json endpoints, scoped request contexts, and server-returned URLs are ignored. This matches the CLI's existing rule that repository-steered API hosts need shell confirmation.
  • The set is sealed on first use, so later environment writes, including writes by project code, cannot widen it.
  • The exemption covers an exact origin (scheme, host, port). Redirects stay rejected, and per-hop origin authorization stays in place.
  • Provider, OIDC, remote tool, and project-configured transports never consult the set.
  • Hosted runtimes and veryfront serve never seal the set. Their VERYFRONT_API_URL names a cluster-internal service, so this change does not loosen them.
  • A DNS answer that mixes public and private records is treated like any other answer for a trusted origin. The trust follows the configured origin, not the addresses.

Verified against staging from a tailnet machine with a placeholder token:

  • Before: Outbound network egress blocked for host: <staging API host> for the model request and billing finalization.
  • After (URL exported in the shell): both requests reach the API and return 401 for the placeholder token.

Related Issue(s)

Refs https://github.com/veryfront/veryfront-issue-inbox/issues/1444

The eval classification for a blocked model request is stacked on #4505 in a separate PR.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)

Checklist

  • I have made corresponding changes to the documentation (if applicable)
  • I have added tests that prove my fix is effective or that my feature works

Verification:

  • deno task test:file for src/security/http/, src/security/sandbox/, src/security/application-auth/, src/provider/veryfront-cloud/, cli/commands/eval/, src/sandbox/, src/embedding/, src/provider/model-registry.test.ts, and src/platform/adapters/veryfront-api-transport.test.ts: all pass
  • deno task typecheck, deno task lint, deno task fmt:check, deno task lint:test-typecheck, and deno task docs:public:check: pass
  • lint:module-boundaries, lint:dependency-boundaries, lint:ban-test-only, lint:cli-boundary, lint:check-awaits, lint:anti-slop, lint:secret-scanning-config, and lint:testing-front-door: pass

`veryfront eval` against staging failed every record with "Outbound network
egress blocked for host: api.veryfront.org", and gateway billing finalization
was skipped the same way. Staging is reachable only over the tailnet, so its
public DNS answer is a private address, and the host egress guard rejects that
as request forgery for both the Veryfront Cloud gateway fetch and billing
finalization.

`veryfront eval` now seals the origins of VERYFRONT_API_URL and
VERYFRONT_API_BASE_URL from the process environment before it loads project
config or agent modules. The Veryfront Cloud gateway and billing transport
lets exactly those origins resolve to a private address.

- Values copied from a project .env file, veryfront.json endpoints, scoped
  request contexts, and server-returned URLs are not trusted.
- The set is sealed on first use, so later environment writes cannot widen it.
- Only the Veryfront API transport consults it. Provider, OIDC, remote tool,
  and project-configured transports keep the private-address block.
- Redirects stay rejected and other destination origins stay unauthorized.
- Hosted runtimes and `veryfront serve` never seal the set, so pods where
  VERYFRONT_API_URL names a cluster-internal service are unchanged.

Refs veryfront/veryfront-issue-inbox#1444
@coderabbitai

coderabbitai Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 18 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: d5579bf1-fe8b-4dc3-bed2-ff58eded841e

📥 Commits

Reviewing files that changed from the base of the PR and between 7c47cc6 and c4e0b57.

📒 Files selected for processing (8)
  • cli/commands/eval/command.test.ts
  • cli/commands/eval/command.ts
  • docs/guides/configuration.md
  • src/provider/veryfront-cloud/provider.test.ts
  • src/provider/veryfront-cloud/shared.ts
  • src/security/README.md
  • src/security/http/outbound-fetch.test.ts
  • src/security/http/outbound-fetch.ts

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.

@github-actions

Copy link
Copy Markdown

📦 Client bundle boundary

Entrypoint Modules Source size Server leaks
src/index.client.ts 289 2307 KiB ✅ 0

A server module in a client graph aborts hydration in the browser. New leaks fail CI; known leaks are tracked in scripts/lint/client-bundle-baseline.json to burn down.

@gitar-bot

gitar-bot Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

Gitar is working

Gitar

Comment thread src/security/http/outbound-fetch.test.ts Fixed
@kojiwakayama
kojiwakayama marked this pull request as ready for review September 16, 2026 16:00
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for security reviews. Please try again later.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your trial has ended. Reactivate Greptile to resume code reviews.

Comment thread src/security/http/outbound-fetch.test.ts Fixed
@github-actions

Copy link
Copy Markdown

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: 4be402d5a2

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@codecov

codecov Bot commented Sep 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.91525% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/security/http/outbound-fetch.ts 96.00% 1 Missing and 1 partial ⚠️
cli/commands/eval/command.ts 83.33% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

…unit boundary

Two new tests stubbed only the plain transport. Node and Bun take the pinned
path for every guarded request, so they opened a real socket to the private
test address and timed out. Every stub transport now supplies pinnedFetch.

The Veryfront Cloud fetch test mutated process environment in
shared.test.ts, which the semantic unit-boundary audit classifies as
network-only. It moves to provider.test.ts, which already owns process state.

The private-DNS helper no longer passes an init argument its stub ignores.

Refs veryfront/veryfront-issue-inbox#1444
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for security reviews. Please try again later.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your trial has ended. Reactivate Greptile to resume code reviews.

@kojiwakayama

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: c4e0b5785f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@sonarqubecloud

Copy link
Copy Markdown

@kojiwakayama
kojiwakayama added this pull request to the merge queue Sep 16, 2026
Merged via the queue into main with commit 789c3df Sep 16, 2026
97 of 101 checks passed
@kojiwakayama
kojiwakayama deleted the fix/cli-staging-internal-api-egress branch September 16, 2026 17:28
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.

2 participants