Skip to content

feat(v1): keep credentials out of platform uploads - #2508

Open
xeophon wants to merge 34 commits into
mainfrom
claude/simplify-trace-filtering-355c8c
Open

xeophon wants to merge 34 commits into
mainfrom
claude/simplify-trace-filtering-355c8c

Conversation

@xeophon

@xeophon xeophon commented Sep 2, 2026

Copy link
Copy Markdown
Member

Overview

Replaces #2475 with a from-scratch, minimal implementation of the same goal: credentials never reach the Platform. No prime-evals dependency, no release ordering, no sidecar files.

What --push does now

Structural. The uploaded episode projection (UPLOAD_EXCLUDE) is the disk record minus the two config fields that hold credentials: client.headers and harness.env. harness.forward_env only names variables and stays.

By value. Every credential the run knows is replaced with [REDACTED] in every outbound request body:

  • the run's and each agent's resolved client API key
  • the credentials in the host environment and in every environment or header mapping (env, *_env, headers) anywhere in the run's env config, the traced agent configs, and the task data (a client's headers, a harness env, a task config's headers, Harbor's verifier_env and nested verifier.env) — values under credential-like names (KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL|COOKIE|AUTHORIZATION|AUTH|SIGNATURE|SIG|PAT as the name's last word, optionally numbered — compound names are head-final, so HF_TOKEN, X-Api-Key, PGPASSWORD, API_KEY_2 are credentials while TOKEN_URL, COOKIE_DOMAIN, KEY_FILE, SSH_AUTH_SOCK, KEYCLOAK_REALM are not); plus URL credentials anywhere in the traced agent configs and task data (a client base_url, a harness cdp_url, a task's connection string), plus, for any value that is a URL (scheme://host…, never prose), the password (or bare user token) of its userinfo and its credential-named query values (DATABASE_URL, an authenticated HTTP_PROXY, wss://…?token=…); a value that is a JSON object is a mapping too and gets the same rules inside it (DOCKER_AUTH_CONFIG, a service-account blob); 8+ chars
  • everything a rollout records on the new Trace.upload_secrets (rides the eval wire, excluded from disk and stdout like the raw tensors): its interception tokens, the shared-tool URL signatures and any external tool URL's credentials (tool endpoints are not traced), credentials the runtime minted (Runtime.secrets, e.g. the Docker egress proxy token), and the client key plus credential-named header, harness, and task runtime variables as they were while the harness ran, so a key rotated before --push is still redacted. A retried attempt's secrets ride with the errors it leaves behind (Agent.run, run_episode_with_retry via Episode.upload_secrets)

Redaction is exact-match only, over the serialized JSON text: each JSON string is decoded and then searched again for quoted JSON inside it, recursively, so any escape spelling at any nesting depth is matched. Only JSON strings are touched, so numbers and structure cannot be corrupted, and a string without a hit keeps its exact bytes. Nothing is guessed from the shape of the text, so ordinary content is never rewritten.

Each sample is redacted with the small run-wide set plus its own rollout's upload_secrets, so the pattern every string is searched with does not grow with the number of rollouts. Saved traces are unchanged, so the run stays reproducible from its output dir. The log reports how many occurrences were redacted.

Deliberately not carried over from #2475

  • Shape-based credential detection. Every review round on Keep runtime secrets out of uploaded traces #2475 / prime#882 added another pattern (cookie pairs, Digest auth, apiKeys, escaped quotes, …) and another false-positive guard (token_usage, oauth, schema context). That is a scanner's job; we redact what we know. pi-share-hf takes the same position and leaves generic detection to trufflehog.
  • The fingerprint sidecar for resume. A resumed --push redacts everything except the values only the earlier attempt's rollouts knew: its interception and runtime tokens (dead with that run) and credentials rotated since; the module docstring says so.
  • resolve_headers / team-id relocation, the prime-evals client, run_shielded call-site moves: unrelated to keeping secrets out.

Split with the prime CLI

Verifiers redacts what only it knows (its config, its tokens). User-supplied values live in the prime CLI: the companion PR PrimeIntellect-ai/prime#888 adds --secret to prime traces upload and prime eval push, plus the same environment scan, using the same ~40-line redactor. The two copies are intentionally independent so neither repo waits on the other's release.

Test

test_push_traces_uploads_redacted_projection drives push_traces against a mock transport: headers/env dropped, every known secret gone from the body (echoed plainly, inside a quoted tool result with \/ and uppercase-hex escapes, and two documents deep), a credential inside the task's verifier_env replaced while its key and non-credential neighbours stay, ordinary and short values kept, disk record untouched.


Note

High Risk
Changes the security boundary for eval uploads; missed or incorrect redaction could still expose secrets in platform payloads, and secrets shorter than 8 characters are intentionally not redacted.

Overview
Platform --push no longer ships raw credentials. Uploads use a stricter episode projection (drops client.headers and harness.env) and run every outbound JSON body through exact-match redaction to [REDACTED], including secrets nested inside quoted tool-result strings.

Rollouts now record what to scrub. Trace.upload_secrets (and Episode.upload_secrets on retries) captures API keys, env/header/task runtime credentials, interception and tool URL tokens, and runtime-minted secrets (e.g. Docker egress proxy). Those lists ride the eval wire but are stripped from disk, traces.jsonl, and CLI JSON via EXCLUDE_FIELDS / EPISODE_EXCLUDE_FIELDS.

New verifiers/v1/utils/redact.py discovers credential values from env-like maps and URLs, then Redactor rewrites only JSON string leaves. A large integration test asserts the mock upload body is clean while local to_record() stays full-fidelity.

Reviewed by Cursor Bugbot for commit 41205cf. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Redact credentials from platform upload bodies and exclude secrets from saved records

  • Collects credential values (API keys, environment/header mappings, URL userinfo/query params, runtime secrets, tool URL signatures) during rollout startup and service provisioning into per-trace and per-episode upload_secrets lists retained in memory
  • Adds a Redactor in redact.py that replaces known secret occurrences inside JSON string tokens at any nesting depth, preserving structure and non-matching content
  • Gathers a run-wide secret set in platform.py from explicit values, clients, host env, environment/header-like mappings, and URL credentials, then runs all platform request bodies through the Redactor before upload
  • Adds shared exclusion policies (EXCLUDE_FIELDS, EPISODE_EXCLUDE_FIELDS, UPLOAD_EXCLUDE) so Trace.to_record, Episode.to_record, episode-file serialization, and CLI trace output omit upload_secrets, client headers, harness environments, and raw node fields from saved/disk records
  • Aggregates upload_secrets from discarded retry attempts into the final episode via retries.py and agent.py
  • Risk: Redactor.json in redact.py rejects non-finite numbers; any code path that previously uploaded JSON containing NaN/Infinity will now raise. Oversized serialized samples are rejected against the configured request limit in push_traces.

Macroscope summarized 41205cf.

The `--push` upload drops the config fields that hold credentials (client
headers, harness env) from the episode projection and replaces every credential
value the run knows — client API keys, credential-named header / harness / host
environment values, and the per-rollout interception tokens — wherever it
appears in the serialized samples. Redaction is exact-match only; nothing is
guessed from the shape of the text.

Rollouts record their interception tokens on `Trace.upload_secrets`, which rides
the eval wire but is excluded from disk and stdout like the raw tensors.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-02T17:31:25.064811Z 40cd0cb New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Comment thread verifiers/v1/utils/platform.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 11eb4d611d

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread verifiers/v1/utils/platform.py
@macroscopeapp

macroscopeapp Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces a broad credential-protection path spanning rollouts, retries, serialization, runtimes, and platform uploads. Since it changes how sensitive credentials are collected and removed from outbound data, security-focused human review is required.

You can add or adjust custom eligibility rules. Learn more.

Task.runtime_env() values are live-only and never traced, so credential-named
ones are recorded on Trace.upload_secrets at rollout time like the interception
tokens. The redactor also matches the `\/` escape other JSON encoders emit for
`/`, and moves to utils/redact.py so rollout.py can share the name filter
without importing the platform client.
Comment thread verifiers/v1/utils/redact.py Outdated
Comment thread verifiers/v1/utils/platform.py
Mirrors prime#888: each JSON string is decoded before matching, so every valid
escape spelling of the outer string is covered and one more nesting level of
quoted JSON documents is reached; strings without a hit keep their exact bytes.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9b195c7454

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread verifiers/v1/utils/platform.py
Comment thread verifiers/v1/rollout.py
…ime credentials

The redactor no longer enumerates escape spellings: each JSON string is decoded
and then searched again for quoted JSON inside it, so any escape at any nesting
depth is matched and the code shrinks. Every outbound request body goes through
it, not only the samples.

Three more known-value sources: `Rollout.open()` records the client key and
credential-named header, harness, and task runtime variables as they are while
the harness runs (a key rotated before `--push` is still redacted); `known_secrets`
scans environment-like task-data fields (Harbor's `env`, `verifier_env`); and
`Runtime.secrets` lets a runtime expose credentials it minted — the Docker egress
proxy token — which the rollout records before the harness session opens.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a599d34932

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread verifiers/v1/utils/redact.py Outdated
`env_credentials` is now the one rule for what counts as a credential in an
environment-like mapping: values under credential-like names, and the password
(or bare user token) inside a `scheme://user:password@host` value whatever its
name — DATABASE_URL, an authenticated HTTP_PROXY. The rollout capture and the
push-time scan both use it, so the URL keeps its shape and only the secret goes.
Comment thread verifiers/v1/utils/redact.py Outdated
Comment thread verifiers/v1/utils/redact.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7a3efefd1a

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread verifiers/v1/rollout.py

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 409e33375b

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread verifiers/v1/utils/platform.py Outdated
Comment thread verifiers/v1/utils/platform.py Outdated
`env_mappings` walks the task-data dump so a nested `verifier.env` is scanned
like the top-level `env`; `url_credentials` is split out of `env_credentials`
so each client's base_url goes through the same userinfo rule.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0fa49ff4ad

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread verifiers/v1/rollout.py
…s behind

Agent and episode retries prepend the failed attempts' errors onto the final
trace or episode; those errors can quote that attempt's minted tokens, so the
attempts' upload_secrets now ride along. Episode.upload_secrets holds them at
the episode level, on the wire but off disk like the trace field.
Comment thread verifiers/v1/utils/redact.py Outdated

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 096bfa2. Configure here.

Comment thread verifiers/v1/utils/platform.py Outdated
Comment thread verifiers/v1/utils/platform.py

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bc4ed8ad7b

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread verifiers/v1/utils/platform.py
known_secrets now dumps config.env alongside the client, agent configs, and task
data, and treats `headers` mappings like `env` mappings, so a task config's
headers (NeMo Gym) or a seat's client headers are known values even though the
trace itself never carries them. The explicit client-headers term is subsumed.
Comment thread verifiers/v1/utils/platform.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e732474f25

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread verifiers/v1/utils/redact.py Outdated
url_credentials applies the SECRET_NAME rule to a URL's query string, so
`?token=…` authentication is a known value like userinfo is. Only values that
are URLs (scheme://host) are parsed, so prose containing `?token=` is left alone.
Comment thread verifiers/v1/utils/redact.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f47a72ad29

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread verifiers/v1/utils/redact.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7d416e12cd

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread verifiers/v1/utils/platform.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 18cac2cbdb

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread verifiers/v1/utils/redact.py

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9635b1530b

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread verifiers/v1/utils/redact.py Outdated
Comment thread verifiers/v1/utils/redact.py
…e PAT names

known_secrets returns only the run-wide set; build_samples adds each episode's
upload_secrets to a per-sample redactor, so the pattern every string is searched
with no longer grows with the number of rollouts. PAT joins the credential words
(GITHUB_PAT), with the segment boundary keeping PATH out.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8e85d7666a

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread verifiers/v1/utils/redact.py Outdated
Comment thread verifiers/v1/utils/redact.py

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 40cd0cb5f8

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread verifiers/v1/rollout.py Outdated
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