Skip to content

fix(local-windows-rdp): escape special characters in credentials - #1056

Merged
DevelopmentCats merged 3 commits into
mainfrom
fix/local-windows-rdp-credential-escaping
Aug 18, 2026
Merged

fix(local-windows-rdp): escape special characters in credentials#1056
DevelopmentCats merged 3 commits into
mainfrom
fix/local-windows-rdp-credential-escaping

Conversation

@matifali

@matifali matifali commented Aug 18, 2026

Copy link
Copy Markdown
Member

Problem

The password was interpolated into two places without escaping it for the target syntax.

1. PowerShell double-quoted stringconfigure-rdp.ps1

$password = "${password}"

$, backtick, and " are all interpreted there. Reproduced on a live AWS Windows workspace with password = "Te\st$Pa\"ss'word&<>|1!": the entire Configure RDPscript aborts before doing anything, and the workspace reportsstart_error`.

The string is missing the terminator: '.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : TerminatorExpectedAtEndOfString

2. Unencoded URL query parametermain.tf

The same value went into the coder:// app URL raw, so the rendered URL on that workspace was:

coder://dev.coder.com/v0/open/ws/reg37-rdp/agent/main/rdp?username=Administrator&password=Te\st$Pa"ss'w`ord&<>|1!

Coder Desktop receives everything up to the first &. A # drops the remainder, + decodes as a space, and a bare % is an invalid escape.

Fix

Destination Encoding
PowerShell script single-quoted string, ' doubled
App URL query urlencode() on both username and password

Same approach as #1036 for amazon-dcv-windows and #1034 for windows-rdp.

Changes

  • configure-rdp.ps1: pass credentials as PowerShell single-quoted strings
  • main.tf: urlencode() both credentials in the app URL
  • add local-windows-rdp.tftest.hcl covering a password with \ " ' `` `` $ & < > | # % +`
  • update 4 assertions in main.test.ts that were pinning the old behavior, for example password=CustomPass123! unencoded

Module bumped to 1.0.5.

Validation

The new Terraform tests fail without the source fix and pass with it, so they are not vacuous:

run "plan_with_defaults"...           fail
  condition = strcontains(resource.coder_script.rdp_setup.script, "$password = 'coderRDP!'")
run "plan_with_special_characters"... fail

With the fix: 2 passed, 0 failed, bun test main.test.ts 10/10, prettier and terraform fmt clean.

Note

Third and last module in this bug class, after #20 / #1034 (windows-rdp) and #1035 / #1036 (amazon-dcv-windows). Found while dogfooding #1034 on a real AWS Windows workspace, where this module's script was the one that actually crashed.

Closes #1043

🤖 This PR was created with the help of Coder Agents, and needs a human review. 🧑‍💻

…ers in credentials

The password was interpolated into a PowerShell double-quoted string, where
$, backtick, and " are all interpreted, so the setup script aborted with a
parser error and never set the admin password. The same value went into the
coder:// app URL unencoded, where it truncates at the first &.

- pass credentials to the setup script as PowerShell single-quoted strings,
  with single quotes doubled
- urlencode both credentials in the app URL
- add a .tftest.hcl covering a password with backslash, quotes, backtick,
  dollar, ampersand, angle brackets, pipe, hash, percent and plus
@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Module Scorecard Check

coder/local-windows-rdp: 83 → 87

Score improvement: 83 → 87 (+4).

Theme Before After
Presentation & Onboarding 17.5 / 25 20 / 25
Integration
Credential Hygiene 18 / 20 18 / 20
Restricted-Environment N/A N/A
Engineering Quality 10 / 10 10 / 10
Overall 83 / 100 87 / 100
Full scorecard for this PR
Presentation & Onboarding Credential Hygiene Restricted-Environment Readiness Engineering Quality Overall
20 / 25 18 / 20 N/A 10 / 10 87 / 100
Drilldown

Presentation & Onboarding — 20 / 25

Criterion Max Score Notes
Configuration-mode examples 12 12 README provides three distinct examples: basic usage with defaults, custom display name with ordering, and generated credentials pattern. Each demonstrates a different configuration approach with sensible defaults.
Coder-context framing 8 8 README clearly explains this module "enables Remote Desktop Protocol (RDP) on Windows workspaces and adds a one-click button to launch RDP sessions directly through Coder Desktop." Names both Coder and RDP, explains the module eliminates manual configuration, and shows Coder Desktop as the entry point.
Visual preview 5 0 No image, GIF, or video present in README. Only an icon reference exists.

Credential Hygiene — 18 / 20

Criterion Max Score Notes
Secrets marked sensitive 16 16 The password variable is marked sensitive = true in main.tf. README examples avoid inline secrets: basic example uses the default (not a literal secret paste), custom example shows random_password.rdp.result reference rather than hardcoded value.
Non-hardcoded auth path 4 2 README shows random_password resource pattern to generate credentials per workspace, avoiding template-embedded secrets. However, this is still a credential management workaround rather than a true external auth mechanism like OAuth, IAM, or ServiceAccount integration. Earns half credit for the documented pattern.

Restricted-Environment Readiness — N/A

Criterion Max Score Notes
Mirrorable artifact source 10 N/A Module downloads nothing; it only configures Windows RDP via PowerShell script and creates a coder_app. No external artifacts are fetched.
Bring-your-own binary 5 N/A Module uses built-in Windows RDP functionality; no binary installation occurs.
Egress transparency 3 N/A Module makes no external network calls beyond Coder API interactions inherent to coder_app and coder_script resources.
Runs without sudo 2 N/A Module targets Windows and uses PowerShell; sudo is not applicable to Windows environments.

Engineering Quality — 10 / 10

Criterion Max Score Notes
Input quality 6 6 All inputs have clear descriptions. Sensible defaults provided (username="Administrator", display_name="RDP Desktop"). The password variable is marked sensitive. Variables include appropriate types and descriptions for agent_id, agent_name, username, password, display_name, order, and group.
Test coverage 4 4 Comprehensive testing story: .tftest.hcl covers password escaping and URL encoding logic with special characters. TypeScript tests in main.test.ts provide end-to-end coverage including app creation, script generation, custom values, credential handling, and URI format validation. Tests verify both business logic and integration behavior.

Overall — 87 / 100

Raw 48 / 55 → round(48 / 55 × 100) = 87

Track: Utility (RDP configuration module; not an AI agent or IDE)


Scored against SCORECARD.md with claude-sonnet-4-5. Language-model scores are advisory.

…edentials

Show the per-workspace random_password pattern so the credential never has
to live in the template, and note that special characters now survive.

Copy link
Copy Markdown
Member Author

On the scorecard regression: the Credential Hygiene drop is scoring noise, not something this PR introduced.

The only README change in the original diff was the version bump, 1.0.41.0.5, on three lines. The criterion the scorecard cites, the inline coderRDP! default in an example, is identical on main:

$ git show origin/main:registry/coder/modules/local-windows-rdp/README.md | grep -n coderRDP
54:Uses default credentials (Username: `Administrator`, Password: `coderRDP!`):

Presentation moved 17.5 → 20 in the same run with no README content change either, which is the same variance in the other direction. The footer notes these are advisory language-model scores.

That said, the underlying point about the non-hardcoded auth path is fair, so I've added a random_password example in 226133f. It's on-theme for this PR: generating a password is exactly the case that used to break, since a generated value is likely to contain \, &, or $.

The remaining criteria I'm deliberately not addressing here:

  • Visual preview (0/5): needs a screenshot or GIF, unrelated to a credential escaping fix.
  • Inline default in the example: documenting the module's actual default is legitimate, and removing it would make the README less useful.

🤖 This response was generated by Coder Agents.

@matifali
matifali requested a review from 35C4n0r August 18, 2026 10:01
@DevelopmentCats
DevelopmentCats merged commit 73147f2 into main Aug 18, 2026
5 checks passed
@DevelopmentCats
DevelopmentCats deleted the fix/local-windows-rdp-credential-escaping branch August 18, 2026 17:32
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.

bug: special characters in local-windows-rdp password break the setup script and app URL

2 participants