Redact secret parameter values from environment variables sent over the backchannel#18089
Conversation
…he backchannel aspire describe --format json emitted the plaintext value of secret parameters whenever the parameter was consumed by another resource via WithEnvironment. The parameter resource's own Value property is already redacted (IsSensitive), but the resolved value flowing into dependent resources' environment dictionaries was not. The auxiliary backchannel RPC target now collects the resolved values of secret parameters (peeking at already-resolved values only, never triggering resolution) and redacts matching environment variable values before snapshots leave the AppHost. Fixes microsoft#17616 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 18089Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 18089" |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR adds redaction of secret parameter values from environment variables when resource snapshots are sent through the backchannel RPC, preventing secrets from leaking through clients like aspire describe --format json.
Changes:
- Adds
GetResolvedSecretParameterValues()to collect resolved secret parameter values from the application model. - Modifies environment variable mapping in snapshot building to null out values that match any resolved secret parameter value.
- Adds a test verifying that secret parameter values are redacted while non-secret values remain visible.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/Aspire.Hosting/Backchannel/AuxiliaryBackchannelRpcTarget.cs |
Adds value-based redaction of secret parameters in environment variable snapshots |
tests/Aspire.Hosting.Tests/Backchannel/AuxiliaryBackchannelRpcTargetTests.cs |
Adds test for secret parameter value redaction |
| // Build environment variables | ||
| // Build environment variables. Values that match a secret parameter's value are | ||
| // redacted so secrets don't leak through clients (e.g. aspire describe --format json). | ||
| var secretParameterValues = GetResolvedSecretParameterValues(); |
| { | ||
| Name = e.Name, | ||
| Value = e.Value, | ||
| Value = e.Value is not null && secretParameterValues.Contains(e.Value) ? null : e.Value, |
| EnvironmentVariables = [ | ||
| new EnvironmentVariableSnapshot("DB_PASSWORD", "s3cr3t-value", true), | ||
| new EnvironmentVariableSnapshot("REGION", "public-value", true), | ||
| new EnvironmentVariableSnapshot("PLAIN_VAR", "plain-value", true) | ||
| ] |
@shauryalowkeygotaura Take a look at the coding agents section in the contributing guide https://github.com/microsoft/aspire/blob/main/docs/contributing.md#coding-agents. The skills defined here https://github.com/microsoft/aspire/tree/main/.agents/skills (I know claude doesn't read the .agents folder). We typically will run the code-review skill and pr-testing skill. Did you verify this change works e2e with a manual test? |
Description
Fixes #17616
aspire describe --format json(and other CLI surfaces fed by the auxiliary backchannel, including the MCP resource tools) emitted the plaintext value of aParameterResourcemarkedsecret: truewhenever that parameter was consumed by another resource viaWithEnvironment(name, secretParam). The parameter resource's ownValueproperty is already redacted at the producer (IsSensitive→null), but the resolved value flowing into dependent resources'environmentdictionaries was not.AuxiliaryBackchannelRpcTargetnow collects the resolved values of secret parameters in the application model and redacts (nulls) any environment variable value that matches one of them, before snapshots leave the AppHost. This means every backchannel consumer is covered, not justdescribe.Notes on the approach:
WaitForValueTcs.Task.IsCompletedSuccessfully); it never triggers parameter resolution, so it cannot block on an interaction prompt. If a secret value hasn't been resolved yet, it also cannot have flowed into anyone's environment.nullis consistent with the existing handling of sensitive resource properties andSecretTextcommand arguments.ReferenceExpression) are not caught by exact-value matching. That likely needs provenance tracking onEnvironmentVariableSnapshotand could be a follow-up.Testing
GetResourceSnapshotsAsync_RedactsSecretParameterValuesInEnvironmentVariablestoAuxiliaryBackchannelRpcTargetTests, modeled on the existingGetResourceSnapshotsAsync_MapsSnapshotDatatest: secret parameter value is redacted, a non-secret parameter's value and unrelated values pass through unchanged.Aspire.Hostingbuilds clean locally with the change. I wasn't able to run the fullAspire.Hosting.Testsproject in my environment (unrelated test-asset build issue inTestProject.IntegrationServiceA), so relying on CI for the test run.🤖 Generated with Claude Code