Skip to content

Fix propagation of secrets#1573

Draft
SteveL-MSFT wants to merge 1 commit into
PowerShell:mainfrom
SteveL-MSFT:secret-securestring
Draft

Fix propagation of secrets#1573
SteveL-MSFT wants to merge 1 commit into
PowerShell:mainfrom
SteveL-MSFT:secret-securestring

Conversation

@SteveL-MSFT

Copy link
Copy Markdown
Member

PR Summary

Looking into the problem, it would seem that the solution is NOT to have secret extensions wrap their output as JSON. Instead, the problem is that the secret extension handler should be wrapping the output of an extension as a secureString and propagate that through the engine. This led to a few fixes to make this work end-to-end:

  1. The secret extension tests need to explicitly use showSecrets with the Echo resource
  2. The secret.ps1 test extension should ignore errors so that looking for a non-existing secret doesn't report an unnecessary PowerShell error
  3. The secret extension handler will now always wrap the raw output of a secret extension as a secureString object
  4. Fix parameter handling to differentiate secureString and secureObject from string and object so they are distinct
  5. Fix Echo resource to properly unwrap the secureString or secureObject when showSecrets is true

PR Context

Fix #1569

@SteveL-MSFT SteveL-MSFT force-pushed the secret-securestring branch from e78909b to 7a86ad9 Compare June 12, 2026 02:14

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

Pull request overview

This PR updates the secret-extension pipeline so secrets are propagated as secureString (and validated distinctly from string/object) through the DSC engine, and adjusts the Debug/Echo resource and tests to reveal/redact secrets based on showSecrets.

Changes:

  • Wrap secret-extension stdout as secureString in the extension handler, and have secret() return that secure JSON value instead of a plaintext string.
  • Tighten parameter validation/handling so secureString/secureObject are treated as distinct JSON shapes (not interchangeable with string/object).
  • Update Echo and secret-extension Pester tests to use showSecrets and validate expected secret visibility.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
resources/dscecho/src/main.rs Unwrap/redact secure outputs depending on showSecrets, including array/object handling changes.
lib/dsc-lib/src/functions/secret.rs Parse extension output as SecureString JSON and return as a JSON value instead of a plain string.
lib/dsc-lib/src/functions/parameters.rs Validate that secureString/secureObject parameters are in the expected secure JSON format.
lib/dsc-lib/src/extensions/secret.rs Wrap raw secret extension output as a serialized SecureString JSON object.
lib/dsc-lib/src/configure/mod.rs Validate parameter types with distinct checks for secureString and secureObject.
lib/dsc-lib/locales/en-us.toml Add localized error messages for secure-type validation and secret-format failures.
extensions/test/secret/secret.ps1 Adjust test secret extension behavior to suppress errors for missing secrets.
dsc/tests/dsc_extension_secret.tests.ps1 Update secret extension tests to set showSecrets: true and validate unwrapped secret output.
Comments suppressed due to low confidence (1)

lib/dsc-lib/src/functions/secret.rs:9

  • secret() now returns a JSON object ({"secureString": ...}), but its function metadata still advertises return_types: [String]. This makes dsc function list/schema outputs misleading for consumers. Update the metadata to report Object as the return type.
use crate::configure::{context::Context, parameters::SecureString};
use crate::extensions::dscextension::Capability;
use crate::functions::{FunctionArgKind, FunctionCategory, FunctionMetadata};
use rust_i18n::t;
use serde_json::Value;

Comment thread resources/dscecho/src/main.rs
Comment on lines +43 to 49
Output::Array(ref mut arr) => {
for item in arr.iter_mut() {
if echo.show_secrets == Some(true) {
*item = get_secure_contents(item).unwrap_or_else(|| redact(item));
} else {
*item = redact(item);
}
Comment on lines +52 to +55
Output::Object(ref mut obj) => {
obj.clone_from(redact(&Value::Object(obj.clone()))
.as_object()
.expect("Expected redact() to return a Value::Object")); },
Comment on lines +79 to +87
fn get_secure_contents(value: &Value) -> Option<Value> {
if let Ok(secure_string) = serde_json::from_value::<SecureString>(value.clone()) {
return Some(Value::String(secure_string.secure_string));
} else if let Ok(secure_object) = serde_json::from_value::<SecureObject>(value.clone()) {
return Some(Value::Object(secure_object.secure_object));
}

Some(value.clone())
}
@SteveL-MSFT SteveL-MSFT marked this pull request as draft June 12, 2026 02:34
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.

Add support for secureString and secureObject to secret extensions

2 participants