Skip to content

AI-382: keep sandbox credentials out of workflow history - #1745

Open
xumaple wants to merge 2 commits into
mainfrom
maplexu/AI-382-sandbox-secret-refs
Open

AI-382: keep sandbox credentials out of workflow history#1745
xumaple wants to merge 2 commits into
mainfrom
maplexu/AI-382-sandbox-secret-refs

Conversation

@xumaple

@xumaple xumaple commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Environment variables given to a sandbox are written into workflow history, which is durable and visible in the Web UI. A literal credential is recorded again on every sandbox activity, and stays there after you rotate it.

SecretRef records the variable's name instead of its value. The worker reads the value from its own environment when the sandbox needs it, so it has to be set on every worker that runs sandbox activities.

Note: two related leaks are fixed alongside. Host paths bound through extra_path_grants were also written to history in plaintext and are now refused, at the point the manifest crosses into an activity payload so that grants added by a capability are covered too. Separately, run_config accepts a dict upstream while this plugin read attributes off it directly, so passing one raised AttributeError before reaching sandbox validation.

Requires openai-agents >= 0.19.2 for the discriminator that lets the reference survive serialization, capped below 0.20 where nine tests currently fail.

@xumaple
xumaple force-pushed the maplexu/AI-382-sandbox-secret-refs branch 2 times, most recently from e7ac375 to dcc4035 Compare August 12, 2026 17:17
@xumaple
xumaple marked this pull request as ready for review August 12, 2026 18:33
@xumaple
xumaple requested review from a team as code owners August 12, 2026 18:33
A sandbox manifest's environment values are serialized into workflow
history, which is durable, replayed, and visible in the Web UI. Because
the manifest rides inside the session state passed to and returned from
every sandbox activity, a literal credential is recorded repeatedly for
the life of the session and survives rotation.

Add SecretRef, an EnvValue subclass carrying a lookup key rather than a
value. Upstream resolves it worker-side at the point the environment is
needed and never rewrites the manifest, so only the reference persists.

Two related fixes ride along. Host-path bindings in extra_path_grants
were written to history in plaintext; they are now refused at the point
the manifest crosses into a Temporal payload, which is the only place
that sees grants added by a capability. And run_config accepts a dict
upstream, which this plugin read attributes off directly, so a dict
raised AttributeError before reaching sandbox validation.

Requires openai-agents >= 0.19.2 for the EnvValue discriminator, capped
below 0.20 where nine tests currently fail.
# the WorkflowExecutionFailed event.
bound = [g.path for g in manifest.extra_path_grants if g.host_path is not None]
if bound:
raise AgentsWorkflowError(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Note that this is a breaking change that could cause a workflow to start failing if dependencies are bumped automatically

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes, added to changelog

Copilot AI 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.

Pull request overview

Adds durable sandbox secret references while blocking other sensitive manifest data from workflow history.

Changes:

  • Adds SecretRef with worker-side environment resolution.
  • Rejects host-path grants and live sandbox sessions.
  • Normalizes dictionary run configurations and expands tests/documentation.

Reviewed changes

Copilot reviewed 8 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
.gitignore Ignores mypy cache files.
pyproject.toml Updates OpenAI Agents dependency bounds.
temporalio/contrib/openai_agents/__init__.py Exports SecretRef.
temporalio/contrib/openai_agents/_openai_runner.py Normalizes run configuration and rejects live sessions.
temporalio/contrib/openai_agents/README.md Documents secret handling and unsupported inputs.
temporalio/contrib/openai_agents/sandbox/_secret_ref.py Implements worker-resolved secret references.
temporalio/contrib/openai_agents/sandbox/_temporal_sandbox_client.py Rejects host-bound path grants.
tests/contrib/openai_agents/test_openai_sandbox.py Adds workflow and activity boundary coverage.
tests/contrib/openai_agents/test_openai_sandbox_secrets.py Tests serialization and secret resolution behavior.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread temporalio/contrib/openai_agents/__init__.py
Comment thread pyproject.toml
@xumaple
xumaple force-pushed the maplexu/AI-382-sandbox-secret-refs branch from dcc4035 to 80fd8cf Compare August 12, 2026 19:15
manifest = Manifest(
environment=Environment(
value={
"OPENAI_API_KEY": SecretRef(key="OPENAI_API_KEY"),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is SecretRef only used in the Workflow? Maybe it belongs in .workflow

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Also, is there any use case for someone using this for a non-secret environment variable?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

How does rotation work, and might you want to rotate a non-secret?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Is `SecretRef only used in the Workflow?

It's also used by the worker because the worker needs it to deserialize properly.

Is there any use case for someone using this for a non-secret environment variable?

It's pretty generic, so any user could use it for whatever env var they don't want to show up in history

How does rotation work

I think this should be agnostic to all credential rotations? the cert is abstracted at the environment level, and whatever is currently on the worker will be resolved and sent to sandbox. The workflow isn't saving any secret-related state, so we shouldn't really care if/when people want to rotate.

Covers the new SecretRef API and the host-path grant rejection, which is
breaking for workflows already running against openai-agents 0.19.2 or
later -- the release where SandboxPathGrant.host_path was added.
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.

3 participants