Skip to content

feat: configurable proxy auth header - #165

Open
frederikprijck wants to merge 19 commits into
mainfrom
worktree-bearer-auth
Open

frederikprijck wants to merge 19 commits into
mainfrom
worktree-bearer-auth

Conversation

@frederikprijck

@frederikprijck frederikprijck commented Jul 30, 2026

Copy link
Copy Markdown
Member

What

Adds an optional, configurable HTTP auth header for the LLM proxy, so the framework can authenticate against a proxy that requires its own header (e.g. LiteLLM's x-litellm-api-key: Bearer <jwt>) instead of only the provider-native API-key env vars.

// eval.config.js
proxy: {
  baseUrl: PROXY_BASE_URL,
  authHeader: { name: 'x-litellm-api-key', valuePrefix: 'Bearer ', tokenEnv: 'LLM_PROXY_TOKEN' },
}

Entirely opt-in. Omit authHeader and behaviour is unchanged.

Two credentials, two switches

LLM_API_KEY takes precedence, so existing deployments keep working untouched and adopting the header is an explicit act — unset LLM_API_KEY.

LLM_API_KEY proxy.authHeader What authenticates
set unset provider-native API key (default)
set configured provider-native API key — header ignored (logged)
unset configured the configured header, token from tokenEnv
unset unset nothing — CLI exits with an error

Because the header path needs LLM_API_KEY absent, validateApiKey() no longer hard-exits when it is missing and authHeader is configured — otherwise the feature would be unreachable.

Where the header is sent

All seven proxy call sites resolve it from one place (resolveProxyAuthHeader()), so the name/prefix/token rules live in exactly one module:

Site Mechanism
claude-code ANTHROPIC_CUSTOM_HEADERS env var
codex [model_providers.llmproxy.env_http_headers] referencing a fixed env var name, so the token is never written to config.toml
gemini-cli GEMINI_CLI_CUSTOM_HEADERS env var (gemini-cli ≥ 0.51)
copilot ProviderConfig.headers
baseline createOpenAI({ headers })
LLM judge fetch headers — drops Authorization rather than sending a placeholder
recommendation generator same as the judge

When the header is configured, provider-native key vars get the inert placeholder unused-see-proxy-auth-header. That is load-bearing, not cosmetic: the Gemini CLI's validateAuthMethod rejects an empty GEMINI_API_KEY, and the Claude binary requires one of its credential vars to be set.

The token is never logged and never written to disk. Log lines carry the header name only; warnings name the env var, never its contents.

Verified against a live LiteLLM proxy

Path Result
baseline grade A
LLM judge 12/13 graders
claude-code grade A (92)
codex grade A (95)
gemini-cli grade A (94)
sandbox.passthroughEnv → Docker token forwarded

Every per-runner mechanism was grounded in the installed SDK source rather than documentation.

Notes for reviewers

  • Sandbox: the token's env var is app-named, so it must be added to sandbox.passthroughEnv. Omitting it makes sandboxed runs fail while host runs succeed.
  • AGENTS.md gains a warning that the gemini-cli loopback proxy (127.0.0.1:9876) is not an obsolete header-injecting shim — it is an SSE-unwrapping workaround for a LiteLLM v1.86.0+ bug and is still required. Bypassing it makes Gemini runs fail with fetch failed sending request.
  • 1295 tests pass; lint and format clean.

Summary by CodeRabbit

  • New Features

    • Added configurable proxy authentication with custom headers, token environment variables, and optional prefixes.
    • Added support across LLM judges, recommendations, baseline evaluations, and supported CLI runners.
    • Added secure credential forwarding for sandboxed runs and provider-specific CLI guidance.
    • Added new grading options, command-order checks, and trace-aware judging support.
  • Bug Fixes

    • Improved authentication validation and clarified errors when required proxy tokens are missing.
  • Documentation

    • Updated configuration, architecture, authentication, grading, testing, and contributor guidance.
  • Tests

    • Added coverage for authentication resolution, runner behavior, fallback handling, precedence, and secret protection.

- Add resolveProxyAuthHeader and PLACEHOLDER_API_KEY to imports
- Add CODEX_PROXY_AUTH_TOKEN_ENV constant for fixed env var name
- Update writeCodexConfig to accept proxyAuthHeaderName param and write
  env_http_headers section when configured
- Resolve proxy auth at call site and pass header name to writeCodexConfig
- Inject token value into codexEnv[CODEX_PROXY_AUTH_TOKEN_ENV] when configured
- Set OPENAI_API_KEY to PLACEHOLDER_API_KEY when using auth header
- Add test suite verifying env_http_headers written, token never in TOML,
  and env_http_headers omitted when unconfigured
Add four tests that assert on the environment passed to the Codex SDK
constructor, covering the central pairing between the TOML reference
and the injected env var:

When an auth header is configured:
- LLM_PROXY_AUTH_TOKEN is injected with the resolved token value
- OPENAI_API_KEY is set to the placeholder

When no auth header is configured (backward-compatibility guard):
- OPENAI_API_KEY equals the LLM_API_KEY value
- LLM_PROXY_AUTH_TOKEN is absent from the env

These tests catch regressions where the header name is written into
config.toml but the token is never injected into the subprocess env,
or where OPENAI_API_KEY retains the real key instead of the placeholder.
The baseline runner now checks for a configured proxy auth header via
resolveProxyAuthHeader() and injects it into OpenAI's createOpenAI
headers option. When configured, the credential travels in the custom
header; the provider-native apiKey field gets the placeholder value.

Tests verify:
- headers are passed to createOpenAI when configured
- apiKey uses PLACEHOLDER_API_KEY when a header is configured
- behavior unchanged when no header is configured
- original apiKey used as fallback when no header configured
FIX 1: Wire up recommendation generator with proxy auth
- Import and call resolveProxyAuthHeader() in generator.ts callLlm()
- Compose authHeaders dict exactly like judge and agent runners
- Add generator-auth.test.ts mirroring llm-judge-auth.test.ts pattern
- Covers both configured header (Authorization absent) and unconfigured
  default path (Authorization present)

FIX 2: Clarify that LLM_API_KEY remains required
- AGENTS.md: add Important block stating LLM_API_KEY must be set even
  when proxy.authHeader is configured (CLI validator demands it)
- ARCHITECTURE.md: reword "either/or" to "plus optionally" so it's
  clear both are needed
- .env.example already correct (doesn't imply LLM_API_KEY is optional)

FIX 3: Document valuePrefix default
- README.md proxy.authHeader row: clarify valuePrefix defaults to ''
  (bare token) when omitted

FIX 4: Wire-level baseline test not added
- Attempted but SDK/mock structure makes it impractical without major
  restructuring (existing test mocks createOpenAI and generateText at
  module level; wire-level test would need real SDK + fetch mock)
- Existing option-level test already verifies headers object is passed
  to createOpenAI correctly (baseline.test.ts:188-210)
- TypeScript doesn't guard excess-property names in the conditional
  spread idiom, but the option-level test proves the name is honoured
The provider-native API key now wins whenever it is set, even with
`proxy.authHeader` configured. An existing deployment that still exports
LLM_API_KEY keeps its current behaviour untouched, so adopting the custom
header is an explicit act: unset LLM_API_KEY. The resolver logs one line
when it ignores a configured header, so the skipped config is never silent.

Because the header path now requires LLM_API_KEY to be absent,
validateApiKey() can no longer hard-exit when it is unset — that would
leave the header unreachable (set => legacy wins, unset => exit). It
returns '' when proxy.authHeader is configured; call sites already write
PLACEHOLDER_API_KEY into provider-native key fields.

In apps/auth0-evals the header name comes from LLM_PROXY_AUTH_HEADER, and
the authHeader block is omitted entirely when that var is unset — an empty
name would otherwise send ": Bearer <token>" and fail confusingly.

Also corrects the design spec's "flagged for the operator" note. It claimed
the 127.0.0.1:9876 loopback proxy was a header-injecting shim made obsolete
by GEMINI_CLI_CUSTOM_HEADERS. It is not: gemini-sse-proxy.js works around a
LiteLLM v1.86.0+ bug that double-wraps streamGenerateContent responses in
SSE, forwards headers verbatim, and is still required. Bypassing it fails
with "fetch failed sending request" after nine retries; with it running the
same eval scores A (94).
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The framework adds configurable proxy authentication with LLM_API_KEY precedence. It supports core requests and four runners, validates proxy tokens at CLI startup, injects provision-specific context, and expands evaluation guidance and documentation.

Changes

Proxy authentication and evaluation guidance

Layer / File(s) Summary
Authentication contract and resolver
packages/evals-core/src/config/*, packages/evals-core/src/index.ts, packages/evals-core/tests/config/*
Adds proxy authentication configuration, centralized resolution, token handling, placeholder credentials, public exports, and tests.
Request authentication and CLI validation
packages/evals-core/src/graders/*, packages/evals/src/cli/*, packages/evals/src/recommendations/*, packages/evals/src/runners/baseline.ts, related tests
Uses proxy headers for requests and requires the configured token when LLM_API_KEY is absent.
Runner authentication propagation
packages/evals/src/runners/*, packages/evals/tests/runners/*
Adds proxy authentication handling for Claude Code, Codex, Copilot, and Gemini CLI.
Application configuration and provision context
apps/auth0-evals/*, docs/ARCHITECTURE.md, packages/evals/README.md
Adds proxy environment settings, judge configuration, provision-specific CLI context, and authentication documentation.
Evaluation guidance and repository documentation
AGENTS.md
Adds grading primitives, judge exclusions, command guidance, and repository conventions.

Estimated code review effort: 4 (Complex) | ~60 minutes

Merge Risk: 🟠 High · up to eb270

Proxy tokens may be exposed to agent-run commands or sent over cleartext connections, so the authentication paths should be secured before merge. A test type error and contradictory grading guidance also remain.

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant ProxyAuthResolver
  participant EvalRunner
  participant LLMProxy
  CLI->>ProxyAuthResolver: validate and resolve configured token
  ProxyAuthResolver-->>EvalRunner: return header and placeholder key
  EvalRunner->>LLMProxy: send authenticated request
Loading

Suggested reviewers: sanchitmehtagit

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 70.59% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 17 functions across 20 files. (4 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the pull request's primary change: adding a configurable proxy authentication header.
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.
Full details: Docstring Coverage

Explanation

Docstring coverage is 70.59% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 17 functions across 20 files. (4 skipped: 4 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-bearer-auth

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.

These were process artifacts for building the feature, not documentation the
repo needs to carry. The user-facing behaviour is documented in AGENTS.md,
packages/evals/README.md, .env.example, and docs/ARCHITECTURE.md.

Carries one finding out of the spec before deleting it: the gemini-cli
loopback proxy is an SSE-unwrapping workaround for a LiteLLM bug, not an
obsolete header-injecting shim. That correction now lives in AGENTS.md, so
nobody removes a load-bearing workaround while "simplifying" the config.
@frederikprijck

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
✅ 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.

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

Actionable comments posted: 5

🧹 Nitpick comments (1)
packages/evals-core/src/graders/llm-judge.ts (1)

78-91: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the duplicated auth-header decision into a shared helper.

packages/evals-core/src/graders/llm-judge.ts and packages/evals/src/recommendations/generator.ts each duplicate the identical logic — resolve proxyAuth, then choose between the custom header and Authorization: Bearer ${apiKey} — with the same explanatory comment. proxy-auth.ts's own module doc states the goal that header rules "live in exactly one place," but this decision is currently copy-pasted in two files.

  • packages/evals-core/src/graders/llm-judge.ts#L78-L91: replace the inline proxyAuth/authHeaders composition with a call to a shared helper (e.g., resolveAuthHeaders(apiKey)) exported from proxy-auth.ts.
  • packages/evals/src/recommendations/generator.ts#L181-L197: replace the identical inline block with the same shared helper.
🤖 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 `@packages/evals-core/src/graders/llm-judge.ts` around lines 78 - 91, Extract
the duplicated proxy-auth versus bearer-auth header selection into a shared
helper exported from proxy-auth.ts, such as resolveAuthHeaders(apiKey). Update
packages/evals-core/src/graders/llm-judge.ts lines 78-91 and
packages/evals/src/recommendations/generator.ts lines 181-197 to call this
helper and remove their inline resolution logic and explanatory comments,
preserving the existing header behavior.
🤖 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 `@apps/auth0-evals/.env.example`:
- Around line 28-34: Update the proxy-auth example in .env.example so the
default LLM_API_KEY placeholder does not remain active when users enable
LLM_PROXY_AUTH_HEADER and LLM_PROXY_TOKEN; comment out that placeholder or make
the examples mutually exclusive, while preserving the documented proxy
configuration.

In `@apps/auth0-evals/eval.config.js`:
- Around line 9-14: Add Vitest coverage for the environment-dependent branches
in the app-level eval configuration, including unset and configured
PROXY_AUTH_HEADER_NAME, missing LLM_PROXY_TOKEN, LLM_API_KEY precedence, and
sandbox passthrough of LLM_PROXY_TOKEN. Add the tests under apps/auth0-evals,
isolate and restore environment variables between cases, and verify the
resulting configuration behavior; ensure npm test passes.

In `@docs/ARCHITECTURE.md`:
- Line 275: Update both Mermaid diagrams in ARCHITECTURE.md to reflect the
proxy-auth flow described near the framework/consumer architecture: include
proxy.authHeader configuration, proxy token-variable resolution, LLM_API_KEY
taking precedence when both credentials exist, and forwarding the resolved
authentication through the sandbox. Keep the existing prose and unrelated
diagram flows unchanged.

In `@packages/evals-core/src/graders/llm-judge.ts`:
- Around line 78-91: Move the resolveProxyAuthHeader call and authHeaders
construction into the try block surrounding the withRetry fetch in the judge
flow, ensuring exceptions from header resolution are handled by the existing
catch and normalized as JudgeError. Preserve the current proxy-header and
API-key fallback behavior.

In `@packages/evals/src/cli/validators.ts`:
- Around line 24-49: Add Vitest coverage in the evals package for
hasProxyAuthHeader and validateApiKey: verify an uninitialized config preserves
the existing exit behavior, an initialized config without proxy.authHeader still
exits, and an initialized config with proxy.authHeader returns an empty string
without exiting. Mock or reset environment, framework configuration, and exit
behavior between cases so the tests remain isolated.

---

Nitpick comments:
In `@packages/evals-core/src/graders/llm-judge.ts`:
- Around line 78-91: Extract the duplicated proxy-auth versus bearer-auth header
selection into a shared helper exported from proxy-auth.ts, such as
resolveAuthHeaders(apiKey). Update packages/evals-core/src/graders/llm-judge.ts
lines 78-91 and packages/evals/src/recommendations/generator.ts lines 181-197 to
call this helper and remove their inline resolution logic and explanatory
comments, preserving the existing header behavior.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4122b290-ad49-4de6-915f-0ce93cad3707

📥 Commits

Reviewing files that changed from the base of the PR and between 1a32fea and 4a9f065.

📒 Files selected for processing (25)
  • AGENTS.md
  • apps/auth0-evals/.env.example
  • apps/auth0-evals/eval.config.js
  • docs/ARCHITECTURE.md
  • packages/evals-core/src/config/framework.ts
  • packages/evals-core/src/config/proxy-auth.ts
  • packages/evals-core/src/graders/llm-judge.ts
  • packages/evals-core/src/index.ts
  • packages/evals-core/tests/config/proxy-auth.test.ts
  • packages/evals-core/tests/graders/llm-judge-auth.test.ts
  • packages/evals/README.md
  • packages/evals/src/cli/validators.ts
  • packages/evals/src/recommendations/generator.ts
  • packages/evals/src/runners/baseline.ts
  • packages/evals/src/runners/claude-code/agent.ts
  • packages/evals/src/runners/codex/agent.ts
  • packages/evals/src/runners/copilot/agent.ts
  • packages/evals/src/runners/gemini-cli/agent.ts
  • packages/evals/tests/baseline.test.ts
  • packages/evals/tests/generator-auth.test.ts
  • packages/evals/tests/runners/claude-code-agent.test.ts
  • packages/evals/tests/runners/codex-agent.test.ts
  • packages/evals/tests/runners/copilot-agent.test.ts
  • packages/evals/tests/runners/gemini-cli-agent.test.ts
  • packages/evals/tests/runners/gemini-cli-proxy.test.ts

Comment thread apps/auth0-evals/.env.example
Comment thread apps/auth0-evals/eval.config.js
Comment thread docs/ARCHITECTURE.md
Comment thread packages/evals-core/src/graders/llm-judge.ts Outdated
Comment thread packages/evals/src/cli/validators.ts Outdated
- Move resolveProxyAuthHeader() inside the try block in llmJudge so a
  throw there normalizes to JudgeError like every other failure path.
- Add test coverage for validateApiKey()'s proxy.authHeader branch
  (empty apiKey without exiting, still exits when unconfigured,
  LLM_API_KEY precedence).
- Update both ARCHITECTURE.md Mermaid diagrams to show credential
  resolution and sandbox token forwarding, matching the prose.
- Clarify .env.example so enabling the proxy auth header also says to
  comment out the default LLM_API_KEY line, without disabling it by
  default for the common path.

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

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 `@packages/evals/tests/cli-config.test.ts`:
- Around line 82-90: Update withAuthHeader so its setFrameworkConfig fixture is
created through the existing complete framework-config factory, then override
only proxy.authHeader while preserving the base configuration. Remove the as
unknown as Required<FrameworkConfig> cast and ensure the fixture supplies
skills, workspace, braintrust, scoring, and sandbox through the factory.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 05293eaa-6836-4f96-8f7d-96138b5f39a5

📥 Commits

Reviewing files that changed from the base of the PR and between 4a9f065 and e798b96.

📒 Files selected for processing (4)
  • apps/auth0-evals/.env.example
  • docs/ARCHITECTURE.md
  • packages/evals-core/src/graders/llm-judge.ts
  • packages/evals/tests/cli-config.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/evals-core/src/graders/llm-judge.ts
  • apps/auth0-evals/.env.example

Comment thread packages/evals/tests/cli-config.test.ts
@sanchitmehtagit

Copy link
Copy Markdown
Contributor

@coderabbit.ai generate sequence diagram

@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown

Tip

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

@sanchitmehtagit

sequenceDiagram
    autonumber
    participant User as User or CI
    participant App as Evals application
    participant Config as Framework configuration
    participant Env as Environment variables
    participant Resolver as resolveProxyAuthHeader()
    participant Consumer as Runner, baseline, judge, or generator
    participant Sandbox as Sandbox runner
    participant Proxy as LLM proxy
    participant Provider as LLM provider

    User->>App: Start evaluation or LLM request
    App->>Config: Load proxy.authHeader configuration
    App->>Resolver: Resolve request credentials
    Resolver->>Env: Read LLM_API_KEY

    alt LLM_API_KEY is set
        Env-->>Resolver: Provider API key
        Resolver-->>Consumer: No proxy authentication header
        Consumer->>Provider: Request with provider-native authentication
        Provider-->>Consumer: Response
    else LLM_API_KEY is not set and proxy.authHeader is configured
        Resolver->>Env: Read configured tokenEnv
        alt Proxy token is set
            Env-->>Resolver: Proxy token
            Resolver-->>Consumer: Resolved custom header and token

            alt Consumer runs in a sandbox
                Consumer->>Sandbox: Forward LLM_PROXY_TOKEN
                Consumer->>Sandbox: Set inert provider API-key placeholder
                Sandbox->>Proxy: Request with custom proxy header
            else Consumer runs directly
                Consumer->>Proxy: Request with custom proxy header
            end

            Proxy->>Provider: Forward LLM request
            Provider-->>Proxy: LLM response
            Proxy-->>Consumer: LLM response
        else Proxy token is not set
            Resolver-->>Consumer: No resolved proxy authentication header
            Consumer-->>App: Continue with existing validation or fallback behavior
        end
    else No configured credentials
        Resolver-->>Consumer: No proxy authentication header
        Consumer-->>App: Existing API-key validation fails
    end
Loading

You are interacting with an AI system.

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

Solid, well-documented feature: single resolution point, clean secret handling, and thorough docs/tests. Two things worth a look before merge, one of which breaks judge graders in exactly the mode this PR adds.

Comment thread packages/evals/src/cli/validators.ts Outdated
Comment thread packages/evals-core/src/config/proxy-auth.ts
Judge graders silently zeroed out in authHeader-only mode: validateApiKey()
returns '' as the deliberate empty-credential signal, but the judge executor's
!ctx.apiKey guard treated that falsy value the same as a missing key. Narrow
the guard to ctx.apiKey === undefined so the empty-string convention reaches
llmJudge() as intended.

Also fail closed at CLI startup when proxy.authHeader is configured but its
token env var is unset (e.g. a typo) and LLM_API_KEY is absent — previously
every runner proceeded with no working credential and failed later on an
opaque 401 from the proxy.
# Conflicts:
#	apps/auth0-evals/.env.example
#	docs/ARCHITECTURE.md

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/evals-core/src/config/framework.ts (1)

30-30: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Sensitive Data Exposure (CWE-319): Cleartext Transmission of Sensitive Information

Reachability: Internal · Exploitability: Moderate

Require HTTPS before sending the proxy token.

When proxy.baseUrl uses http:// and LLM_API_KEY is unset, reject the configuration before constructing or sending authHeader. Allow only an explicit loopback exception if required.

🤖 Prompt for AI Agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. Verify each finding against current code. Fix
only still-valid issues, skip the rest with a brief reason, keep changes
minimal, and validate.

In `@packages/evals-core/src/config/framework.ts` at line 30, Validate
proxy.baseUrl before constructing authHeader: reject non-HTTPS URLs when the
proxy token would be used, including when LLM_API_KEY is unset, while allowing
only an explicitly permitted loopback HTTP exception. Ensure validation occurs
before any token is constructed or sent.
packages/evals/src/runners/codex/agent.ts (1)

550-550: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Sensitive Data Exposure (CWE-319): Cleartext Transmission of Sensitive Information

Reachability: Internal · Exploitability: Difficult

Reject non-TLS proxy URLs when sending proxy-header credentials.

CODEX_PROXY_AUTH_TOKEN_ENV sends the credential as a custom header, while proxy URLs accept arbitrary schemes without transport validation. Reject non-loopback http:// URLs, including agent-specific overrides, before starting a job.

🤖 Prompt for AI Agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. Verify each finding against current code. Fix
only still-valid issues, skip the rest with a brief reason, keep changes
minimal, and validate.

In `@packages/evals/src/runners/codex/agent.ts` at line 550, Validate the proxy
URL before starting a job when CODEX_PROXY_AUTH_TOKEN_ENV credentials are sent,
rejecting non-TLS http:// URLs unless they target a loopback host. Apply the
same validation to agent-specific proxy overrides, while preserving valid
https:// and loopback http:// URLs; update the proxy setup flow near the
codexEnv assignment.
AGENTS.md (1)

519-519: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Correct the corpus-scope guidance for grader primitives.

contains, notContains, and matches search workspace files by default. source: 'response' searches the agent reply, and source: 'both' searches both. The current “source files only” statement contradicts this contract and can produce incorrect MCP grading results. Replace it with the accurate scope.

🤖 Prompt for AI Agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. Verify each finding against current code. Fix
only still-valid issues, skip the rest with a brief reason, keep changes
minimal, and validate.

In `@AGENTS.md` at line 519, Update the corpus-scope guidance under the
Conventions section to state that contains, notContains, and matches search
workspace files by default, source: 'response' searches the agent reply, and
source: 'both' searches both; remove the contradictory “source files only”
wording.
🤖 Prompt for all review comments with AI agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. 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 `@docs/ARCHITECTURE.md`:
- Line 215: Ensure proxy credentials never reach agent tool subprocesses: remove
or isolate values placed in ANTHROPIC_CUSTOM_HEADERS, GEMINI_CLI_CUSTOM_HEADERS,
and LLM_PROXY_AUTH_TOKEN for proxy-only runs, and scrub these variables from
every tool-command environment in addition to the existing filteredEnv()
handling. Do not rely on cliContext as the security boundary; enforce credential
isolation where tool commands inherit their environment.

In `@packages/evals-core/tests/graders/executor-registry.test.ts`:
- Line 180: Update the GraderContext fixture in executor-registry tests to
include the required agentText field with an empty-string value, preserving the
existing files-only behavior.

---

Outside diff comments:
In `@AGENTS.md`:
- Line 519: Update the corpus-scope guidance under the Conventions section to
state that contains, notContains, and matches search workspace files by default,
source: 'response' searches the agent reply, and source: 'both' searches both;
remove the contradictory “source files only” wording.

In `@packages/evals-core/src/config/framework.ts`:
- Line 30: Validate proxy.baseUrl before constructing authHeader: reject
non-HTTPS URLs when the proxy token would be used, including when LLM_API_KEY is
unset, while allowing only an explicitly permitted loopback HTTP exception.
Ensure validation occurs before any token is constructed or sent.

In `@packages/evals/src/runners/codex/agent.ts`:
- Line 550: Validate the proxy URL before starting a job when
CODEX_PROXY_AUTH_TOKEN_ENV credentials are sent, rejecting non-TLS http:// URLs
unless they target a loopback host. Apply the same validation to agent-specific
proxy overrides, while preserving valid https:// and loopback http:// URLs;
update the proxy setup flow near the codexEnv assignment.

After applying the fix, consider running `coderabbit review --agent` for local
review. Visit https://docs.coderabbit.ai/cli.
🪄 Autofix

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: defaults

Review profile: CHILL

Plan: Team

Run ID: e5a98fe4-ba76-4ef9-876d-c5d6e27c967f

📥 Commits

Reviewing files that changed from the base of the PR and between e798b96 and eb27067.

📒 Files selected for processing (17)
  • AGENTS.md
  • apps/auth0-evals/.env.example
  • apps/auth0-evals/eval.config.js
  • docs/ARCHITECTURE.md
  • packages/evals-core/src/config/framework.ts
  • packages/evals-core/src/config/proxy-auth.ts
  • packages/evals-core/src/graders/executors/llm-judge.ts
  • packages/evals-core/src/graders/llm-judge.ts
  • packages/evals-core/src/index.ts
  • packages/evals-core/tests/graders/executor-registry.test.ts
  • packages/evals/README.md
  • packages/evals/src/cli/validators.ts
  • packages/evals/src/runners/claude-code/agent.ts
  • packages/evals/src/runners/codex/agent.ts
  • packages/evals/src/runners/copilot/agent.ts
  • packages/evals/src/runners/gemini-cli/agent.ts
  • packages/evals/tests/cli-config.test.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/evals/src/runners/copilot/agent.ts
  • apps/auth0-evals/.env.example
  • packages/evals-core/src/config/proxy-auth.ts
  • packages/evals/README.md

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

Comment thread docs/ARCHITECTURE.md
Exec->>Agent: run task in workspace
Note over Exec: sandbox.passthroughEnv forwards the<br/>token var into the container
Exec->>Agent: run task in workspace (credential injected —<br/>native key header, or the configured proxy header)
Agent-->>Exec: edited workspace + RunRecord trace (includes finalSummary)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 8 \
  'LLM_PROXY_TOKEN|passthroughEnv|runJobInDocker|spawn|exec(File)?|docker' \
  apps/auth0-evals packages/evals

Repository: auth0/auth0-evals

Length of output: 50376


Sensitive Data Exposure (CWE-200): Exposure of Sensitive Information to an Unauthorized Actor

Exploitability: Moderate

Keep proxy credentials out of tool subprocesses.

filteredEnv() removes LLM_PROXY_TOKEN, but proxy-only runs copy its value into ANTHROPIC_CUSTOM_HEADERS, GEMINI_CLI_CUSTOM_HEADERS, or LLM_PROXY_AUTH_TOKEN. Agent tool commands inherit these environment variables and can exfiltrate the credential. Use a private credential channel or scrub these variables from every tool-command environment. cliContext is not an enforcement boundary.

🤖 Prompt for AI Agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. Verify each finding against current code. Fix
only still-valid issues, skip the rest with a brief reason, keep changes
minimal, and validate.

In `@docs/ARCHITECTURE.md` at line 215, Ensure proxy credentials never reach agent
tool subprocesses: remove or isolate values placed in ANTHROPIC_CUSTOM_HEADERS,
GEMINI_CLI_CUSTOM_HEADERS, and LLM_PROXY_AUTH_TOKEN for proxy-only runs, and
scrub these variables from every tool-command environment in addition to the
existing filteredEnv() handling. Do not rely on cliContext as the security
boundary; enforce credential isolation where tool commands inherit their
environment.

After applying the fix, consider running `coderabbit review --agent` for local
review. Visit https://docs.coderabbit.ai/cli.

maxCodeChars: 16_384,
enforceMaxChars: true,
},
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- test fixture ---'
sed -n '130,190p' packages/evals-core/tests/graders/executor-registry.test.ts
printf '%s\n' '--- GraderContext declarations and uses ---'
rg -n -C 3 'interface GraderContext|type GraderContext|agentText' packages/evals-core

Repository: auth0/auth0-evals

Length of output: 17169


Add the required agentText field.

GraderContext.agentText is required. This fixture omits it, so TypeScript reports a missing property when test sources are checked. Add agentText: '' to preserve files-only behavior.

Proposed fix
       judge: {
         model: 'm',
         baseUrl: 'https://llm.example.com/v1',
         maxTokens: 1024,
         maxCodeChars: 16_384,
         enforceMaxChars: true,
       },
+      agentText: '',
     };
🤖 Prompt for AI Agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. Verify each finding against current code. Fix
only still-valid issues, skip the rest with a brief reason, keep changes
minimal, and validate.

In `@packages/evals-core/tests/graders/executor-registry.test.ts` at line 180,
Update the GraderContext fixture in executor-registry tests to include the
required agentText field with an empty-string value, preserving the existing
files-only behavior.

After applying the fix, consider running `coderabbit review --agent` for local
review. Visit https://docs.coderabbit.ai/cli.

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