Skip to content

feat(task_step): pass per-run secrets by reference, and keep raw ones out of the run index - #235

Open
AlexS-scale wants to merge 2 commits into
mainfrom
AlexS/secret-override-refs
Open

AlexS-scale wants to merge 2 commits into
mainfrom
AlexS/secret-override-refs

Conversation

@AlexS-scale

@AlexS-scale AlexS-scale commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

What and why

Two problems with per-run secrets (litellm_api_key, judge_litellm_api_key in context.metadata["user_overrides"]).

A step on another host never sees them. Redaction strips them from every persisted context, which is right. But a [runner] whose steps run in a different process from the submitter can only rebuild the context from storage, so the key is gone. LocalRunner is unaffected only because it holds the live context in memory.

The run index stored them in plaintext. insert_run wrote RunRecord.overrides verbatim. A key sent through the explorer's overrides (or smuggled through metadata.user_overrides) landed in the runs collection and came back from GET /tasks/{id}/runs.

Changes:

  • _is_redacted(key, value): a bare secret:KEY or env:NAME reference names a secret rather than holding it, so to_safe_dict() and the context-ops diff keep it. A reference with a ?default may carry the secret itself, so it is still stripped.
  • Config.resolve_reference(value) resolves an env: / secret: reference (the latter through [stores.secret]) and passes anything else through. The five places that read a per-run key use it:
    • deploy_agent
    • deploy_env
    • install_agent
    • both judge paths in rubrics_verifier
  • insert_run strips _REDACTED_KEYS from the overrides it persists. LocalRunner seeds the run from its in-memory record, so the run still gets the key.
  • --litellm-api-key and --judge-litellm-api-key on task run / task run-batch say they take a reference, which also keeps a key out of shell history.
  • AGENTS.md documents the contract.

Trust boundary. A reference resolves against the environment and secret store of the host running the step. In this repository every run submitter (CLI user, loopback explorer user) already has that access, so nothing is newly exposed. A runner that takes runs from callers who may not read those must refuse references it did not create; AGENTS.md says so.

How it was tested

  • pytest tst/unit -n auto: 7899 passed. The 2 test_mcp_cli_builder.py failures are environmental: they pass with the venv on PATH (13 passed).
  • New tests:
    • install_agent installs with the value a secret: reference names in the secret store.
    • A bare reference survives to_safe_dict() and the journal; one with a ?default does not.
    • The run index keeps a reference but not a raw key, and the in-memory record keeps the key.
    • Config.resolve_reference resolves env: and passes other values and None through.
  • ruff check passes.
  • check_plugin_api.py --base origin/main: no break.

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; the previous install failure is fixed.

Summary

The PR keeps bare secret references in saved contexts and removes raw per-run keys from the run index.

  • Task steps can carry per-run key references across hosts.
  • The run index keeps key references but drops raw key values.

Reviews (2) · Last reviewed commit: "fix(install_agent): resolve the per-run ..." · Reviewed by Greptile

… out of the run index

A per-run key in user_overrides is stripped from every persisted context, so a step
that runs on another host than the one the run was submitted from never sees it. A
bare secret:KEY or env:NAME reference names a secret rather than holding it, so
redaction now keeps it, and the steps that read a per-run key resolve it with
Config.resolve_reference(). A reference with a ?default may carry the secret, so it
is still stripped.

The run index stored a run's overrides verbatim, so a key sent in the explorer's
overrides or metadata reached the runs collection and its list endpoint. insert_run
strips the redacted keys; LocalRunner seeds the run from its in-memory record, so
the run still gets the key.
@AlexS-scale
AlexS-scale requested a review from a team as a code owner October 16, 2026 18:59
Comment thread src/agent_env/task_step/task_steps/install_agent.py Outdated
…s for it

An install whose required_params do not name litellm_api_key no longer depends on
the per-run key's reference resolving on this host.

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant