Skip to content

Escape single quotes in PowerShell login script inputs - #599

Open
MaddyMicrosoft wants to merge 2 commits into
Azure:masterfrom
MaddyMicrosoft:fix/ps-injection-escape-inputs
Open

Escape single quotes in PowerShell login script inputs#599
MaddyMicrosoft wants to merge 2 commits into
Azure:masterfrom
MaddyMicrosoft:fix/ps-injection-escape-inputs

Conversation

@MaddyMicrosoft

@MaddyMicrosoft MaddyMicrosoft commented Jul 30, 2026

Copy link
Copy Markdown
Member

What

Apply the same single-quote escape already used for servicePrincipalSecret to the remaining values interpolated into the generated Azure PowerShell login script: tenant-id, subscription-id, client-id, federated token, and (on the AzureStack path) resourceManagerEndpointUrl. Factor the escape into a shared helper (escapePSSingleQuoted) so every interpolation site uses the same treatment.

No behaviour change for legitimate inputs — real GUIDs, domain names, and https URLs contain no single quotes.

Why

AzPSScriptBuilder builds a PowerShell script by string-concatenating action inputs into single-quoted '...' literals, then hands the result to pwsh -Command. The clientSecret field already escaped single quotes; the other four fields did not. A value containing a single quote would break out of the string context and could execute as PowerShell.

This is a defense-in-depth patch. The Azure CLI path (which uses argv arrays via child_process.spawn) already blocks this class of attack for most auth flows, but the escape closes the remaining PS-side surface for consistency and to protect users whose workflow bypasses CLI validation (e.g. via AzureStack cloud registration).

Scope

Only AzPSScriptBuilder.ts and its test are touched. AzureCliLogin.ts, LoginConfig.ts, and the environment allowlist are unchanged — no other code paths were vulnerable.

Verification

  • 30/30 unit tests pass, including 8 new SECURITY: regression tests covering all four affected fields across every auth path (SP+secret, OIDC, user-assigned MI, system-assigned MI, AzureStack)
  • Direct script inspection: ran the compiled fix through LoginConfig + AzPSScriptBuilder with adversarial values in all four fields. Every interpolation site produced doubled single quotes (''), making the payload inert data inside the surrounding '...' string literals
  • Live Azure test: ran the compiled action with an adversarial subscription-id payload (abc' ; Set-Content ... ; $x='). The whole payload was transported as literal string data to Azure — Az CLI rejected the subscription with an "invalid subscription" error containing the exact string. No process execution, no side-effect file was created

Backport plan

The escape fix backports cleanly to releases/v2 — the affected file is nearly identical between v2 and master. A separate PR against releases/v2 will follow.

Apply the same single-quote escape already used for the service principal
secret to the remaining values interpolated into the generated PowerShell
login script: tenant-id, subscription-id, client-id, federated token,
and the AzureStack resourceManagerEndpointUrl.

Factor the escape into a shared helper (escapePSSingleQuoted) so every
interpolation site uses the same treatment, and add regression tests that
assert each field is escaped across all supported auth paths.

No behaviour change for valid inputs; legitimate values contain no single quotes.
@MaddyMicrosoft
MaddyMicrosoft requested a review from isra-fel July 31, 2026 00:12
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