fix(windows-rdp): escape credentials and fix auto-connect on Gateway 2026.2.x - #1034
Open
matifali wants to merge 6 commits into
Open
fix(windows-rdp): escape credentials and fix auto-connect on Gateway 2026.2.x#1034matifali wants to merge 6 commits into
matifali wants to merge 6 commits into
Conversation
Contributor
Module Scorecard Check
|
| Theme | Before | After |
|---|---|---|
| Presentation & Onboarding | 17 / 25 | 17 / 25 |
| Integration | — | — |
| Credential Hygiene | 10 / 20 | 18 / 20 |
| Restricted-Environment | 0 / 20 | 0 / 20 |
| Engineering Quality | 7 / 10 | 8 / 10 |
| Overall | 45 / 100 | 57 / 100 |
Full scorecard for this PR
| Presentation & Onboarding | Credential Hygiene | Restricted-Environment Readiness | Engineering Quality | Overall |
|---|---|---|---|---|
| 17 / 25 | 18 / 20 | 0 / 20 | 8 / 10 | 57 / 100 |
Drilldown
Presentation & Onboarding — 17 / 25
| Criterion | Max | Score | Notes |
|---|---|---|---|
| Configuration-mode examples | 12 | 12 | Multiple provider examples (AWS, Google Cloud) with sensible defaults. Custom version example shows configuration flexibility. |
| Coder-context framing | 8 | 0 | README does not explain what the module adds on top of Coder or how Coder fits in the RDP flow. It states what it enables but not the Coder-specific value proposition. |
| Visual preview | 5 | 5 | Video thumbnail image embedded with link to video demonstration. |
Credential Hygiene — 18 / 20
| Criterion | Max | Score | Notes |
|---|---|---|---|
| Secrets marked sensitive | 16 | 16 | admin_password variable marked sensitive = true in main.tf. README examples do not inline secrets. |
| Non-hardcoded auth path | 4 | 2 | Module accepts admin credentials as variables but README does not document alternative authentication paths (e.g., Windows credential managers, SSO integration, or external auth mechanisms). Partial credit for parameterization. |
Restricted-Environment Readiness — 0 / 20
| Criterion | Max | Score | Notes |
|---|---|---|---|
| Mirrorable artifact source | 10 | 0 | No module variable overrides the PowerShell Gallery URL or Devolutions Gateway download source. The devolutions_gateway_version variable only controls version selection, not the artifact source URL. |
| Bring-your-own binary | 5 | 0 | No documented way to skip installation when Devolutions Gateway is pre-installed. The module always runs Install-Module and Install-DGatewayPackage. |
| Egress transparency | 3 | 0 | No dedicated README section enumerating external endpoints. PSGallery and Devolutions sources are inferable from code but not documented for restricted environments. |
| Runs without sudo | 2 | 0 | PowerShell script performs system-wide installation (Install-Module for all users), modifies HKLM registry keys, configures Windows services, and writes to Program Files. All require administrator privileges with no documented non-privileged fallback. |
Engineering Quality — 8 / 10
| Criterion | Max | Score | Notes |
|---|---|---|---|
| Input quality | 6 | 6 | Variables have clear descriptions and sensible defaults. share variable includes validation. admin_password properly marked sensitive. |
| Test coverage | 4 | 2 | TypeScript tests cover password injection and special character handling. No .tftest.hcl files present. Tests verify script generation but not end-to-end RDP functionality or Devolutions Gateway installation. |
Overall — 57 / 100
Raw 43 / 75 → round(43 / 75 × 100) = 57
Scored against SCORECARD.md with claude-sonnet-4-5. Language-model scores are advisory.
… for 2026.2.x The auto-fill script targeted PrimeNG class names and component names that no longer exist on Gateway 2026.2.4, so the form filled but never submitted, and the in-session toolbar was never found. - protocol: p-dropdown is now p-select, and RDP is already the default, so the explicit selection is dropped rather than driving a PrimeNG overlay - submit: select button[type=submit] inside the form instead of matching an exact p-element class list - toolbar: session-toolbar is now floating-session-toolbar, and the close button is an icon button with aria-label Close session - checkboxes: Unicode Keyboard Mode is gone, and dynamic resize moved onto the connection form as enableDisplayControl, already enabled by default - both polls are now bounded and reveal the form with a visible banner when auto-connect fails, instead of looping forever and logging to a console the user never opens - stop logging credential values to the browser console
matifali
marked this pull request as ready for review
August 11, 2026 15:51
bpmct
added a commit
that referenced
this pull request
Aug 11, 2026
… API (#1046) Fixes the Module Scorecard Check commenting on modules a PR never touched, reported on #1034 where a `windows-rdp` PR got a scorecard comparison for `coder/git-clone`. Linear: [REG-74](https://linear.app/codercom/issue/REG-74/unrelated-module-scorecards-on-pr-commnets) ## Root cause The workflow detected changed modules with `git diff "${BASE_SHA}"...HEAD`, where `BASE_SHA` is `github.event.pull_request.base.sha` and HEAD is GitHub's test merge commit (PR head merged into **current** main). `base.sha` is the base tip from when the PR was opened, so on PRs whose base has since moved, the diff includes every module merged to main after the PR branched. #1034 was opened July 29; `git-clone` changed on main afterwards (#1037), so a later synchronize run scored it, and score noise made it look like a regression. ## Change - Determine changed modules from `GET /repos/{owner}/{repo}/pulls/{n}/files` (paginated) instead of git plumbing. The PR files list is the source of truth for what a PR changes, regardless of how stale the branch is. - Drop `fetch-depth: 0` from checkout; it existed only for the diff. - Guard the `grep` so a PR with no module files doesn't fail the step under `pipefail`. ## Validation Against #1034 directly: the files API returns only `windows-rdp` paths, while the old `base.sha` diff on the same PR spans dozens of unrelated commits including the `git-clone` change. 🤖 Generated with [Coder Agents](https://coder.com/docs/ai-coder/agents)
DevelopmentCats
added a commit
that referenced
this pull request
Aug 18, 2026
## Problem
The password was interpolated into two places without escaping it for
the target syntax.
**1. PowerShell double-quoted string** — `configure-rdp.ps1`
```powershell
$password = "${password}"
```
`$`, backtick, and `"` are all interpreted there. Reproduced on a live
AWS Windows workspace with `password = "Te\st$Pa\"ss'w`ord&<>|1!"`: the
entire `Configure RDP`script aborts before doing anything, and the
workspace reports`start_error\`.
```
The string is missing the terminator: '.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
```
**2. Unencoded URL query parameter** — `main.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
<!-- linear:table-colwidths:400,400 -->
| 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. 🧑💻
---------
Co-authored-by: DevCats <christofer@coder.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Two separate defects made the Web RDP session fail, and they compound: the credentials were mangled in transit, and even correct credentials were never submitted.
1. Credentials were interpolated without escaping (#20)
devolutions-patch.jsembeds the password inside a double-quoted JS string literal (value: "${CODER_PASSWORD}"). JS parses the injected\mas an escape sequence and drops the backslash, soN;JVO*U\mL^a*PbecomesN;JVO*UmL^a*P. A"breaks the patch script entirely.powershell-installation-script.tftplpasses the password as a PowerShell double-quoted string (Set-AdminPassword -adminPassword "${admin_password}"), where$, backtick, and"are interpreted. The Windows account then gets a different password than Coder displays.Both paths end in
STATUS_LOGON_FAILURE [0xc000006d], and whether a user hits it depends on which characters their generated password happens to contain.2. The auto-fill selectors no longer match Gateway 2026.2.x (#1044)
The module defaults to
devolutions_gateway_version = "latest". On 2026.2.4 the form fills but never submits, and the in-session toolbar is never found, so the close-window listener never attaches and the poll loops forever.Changes
Credential escaping
jsonencode, outer quotes trimmed\,", control chars, and<>&as\u003cstyle escapes'doubled$, backtick,",\, and everything else literallyThe JS file keeps a real string literal, so it stays valid JavaScript for Prettier and
@ts-check.Selector updates
p-dropdown[id="protocol"]p-button[class="p-element"] buttonbutton[type="submit"]inside the formsession-toolbarfloating-session-toolbar, close button matched byaria-labelsetCheckbox("Unicode Keyboard Mode")setCheckbox("Dynamic Resize")input#enableDisplayControlon the connection form, corrected only when not already enabledBoth polls are now bounded. On failure the form is revealed with a visible banner instead of looping forever and logging to a console the user never opens. Credential values are no longer logged to the browser console.
Module bumped to
1.3.1.Validation
Provisioned a real AWS Windows workspace from a copy of
aws-windows-desktop, with the module sourced from this branch andadmin_password = "Te\st$Pa\"ss'word&<>|1!"`.Rendered output:
On the VM, the account password round-trips exactly:
In the browser, unattended, no clicks:
ironrdp web::session: Connected!, live Windows desktop, noSTATUS_LOGON_FAILURE.bun test main.test.tspasses (5/5);prettierandterraform fmtare clean.Note
The same escaping bug exists in
amazon-dcv-windows(#1035) andlocal-windows-rdp(#1043). Both are separate modules with separate releases, so they are filed rather than folded in here.Caution
devolutions_gateway_versionstill defaults tolatest, which is the root cause of the selector breakage: an upstream UI change silently breaks every workspace using this module. Worth deciding separately whether to pin a known-good default. Tracked in #1044.Closes #20
Closes #1044