Skip to content

[PRODENG-3917] Escape MSR bootstrapper credentials and host-reported facts - #675

Open
james-nesbitt wants to merge 1 commit into
mainfrom
PRODENG-3917-escape-msr-facts
Open

james-nesbitt wants to merge 1 commit into
mainfrom
PRODENG-3917-escape-msr-facts

Conversation

@james-nesbitt

@james-nesbitt james-nesbitt commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

What

Shell-quote the MSR bootstrapper credentials and validate/quote the host-reported MSR facts.

Why

BuildMKEFlags wrapped the MKE admin credentials in literal double quotes, which do not suppress $(...), backticks or $VAR in the remote shell; host-reported MSR facts (hostname, ReplicaID from settable container labels) reached bootstrapper flags unvalidated and unquoted.

How

  • BuildMKEFlags emits shellescape.Quote'd values; Destroy recovers raw values with shellescape.Unquote before DockerCmd().Arg() re-quotes — fixes a double-quoting bug where an already-quoted value was re-quoted.
  • gather_facts rejects hostnames not matching ^[a-zA-Z0-9.-]+$, mirroring the net.ParseIP check on internal address.
  • ReplicaID quoted at every bootstrapper sink: install_msr, join_msr_replicas, remove_nodes, upgrade_msr; hostname quoted at --ucp-node sinks.

Testing

  • make unit-test: pass; make lint: 0 issues.
  • TestBuildMKEFlagsQuotesCredentials: password with $(...), backticks, quotes roundtrips through quote/unquote as a single shell-safe word.
  • TestDestroyQuotesCredentials: DockerCmd quoting is reversible without payload loss.
  • Existing TestBuildMKEFlags updated from the double-quoted to the shell-quoted format.

Links

Checklist

  • Tests added or updated
  • Docs updated if user-visible behaviour changed
  • No debug output or dead code left in

Written by AI: claude-opus-5

@james-nesbitt james-nesbitt added the smoke-modern Run modern smoke test label Oct 22, 2026
@james-nesbitt
james-nesbitt requested a balanced review from Copilot October 22, 2026 12:47

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.

🟡 Changes recommended

The destroy command’s credential-decoding path can alter literal backslash escapes, causing authentication and cleanup to fail.

1 open issue
What changed in this PR

This PR hardens Launchpad’s MSR bootstrapper commands against shell injection through credentials and host-reported facts.

Changes:

  • Shell-quotes MKE credentials and decodes them before building the destroy command.
  • Validates hostnames and quotes hostname and replica ID arguments.
  • Updates credential-quoting tests.
File Description
pkg/​product/​mke/​phase/​upgrade_msr.go Quotes the existing replica ID during upgrades.
pkg/​product/​mke/​phase/​remove_nodes.go Quotes replica IDs during node removal.
pkg/​product/​mke/​phase/​join_msr_replicas.go Quotes hostname and replica IDs during joins.
pkg/​product/​mke/​phase/​install_msr.go Quotes hostname and replica ID during installation.
pkg/​product/​mke/​phase/​gather_facts.go Validates host-reported hostname characters.
pkg/​msr/​msr.go Quotes credentials and adds decoding for destroy commands.
pkg/​msr/​msr_test.go Updates flag expectations and adds quoting checks.

Review effort: Balanced

Comment thread pkg/msr/msr.go
Comment on lines +157 to +163
unquote := func(flag string) string {
if raw, err := shellescape.Unquote(mkeFlags.GetValue(flag)); err == nil {
return raw
}

return mkeFlags.GetValue(flag)
}
…facts

BuildMKEFlags wrapped the MKE admin username, password and URL in literal
double quotes, which do not suppress $(...), backticks or $VAR in the
remote shell, and Flags.GetValue runs strconv.Unquote, so msr.Destroy
spliced the recovered password straight into a DockerCmd.Arg call -
re-quoting an already-quoted value and breaking on values with quotes.

BuildMKEFlags now emits shellescape.Quote'd values; Destroy recovers the
raw value with shellescape.Unquote before handing it to DockerCmd, which
applies its own quoting. Verified the roundtrip for values containing
$(...), backticks, single and double quotes.

Host-reported facts: gather_facts records the hostname with no
validation; it is now rejected unless it matches ^[a-zA-Z0-9.-]+$
(RFC 1123 shape), mirroring the existing net.ParseIP check on the
internal address. ReplicaID - settable via host container labels - is
quoted at every bootstrapper sink: install_msr, join_msr_replicas,
remove_nodes and upgrade_msr. The hostname is quoted at the --ucp-node
sinks.

TestBuildMKEFlags pinned the old double-quoted flag format; updated to
the shell-quoted form. TestBuildMKEFlagsQuotesCredentials and
TestDestroyQuotesCredentials pin the credential roundtrip; the
single-word property of every flag value is asserted for the payload
password. make lint 0 issues, make unit-test clean.

Covers secf_50a05cbd0de6b8b5bd2f0b93, secf_e38dc9e2e6b75d24ab91e08e.

Written by AI: claude-opus-5

Signed-off-by: James Nesbitt <jnesbitt@mirantis.com>
@james-nesbitt
james-nesbitt force-pushed the PRODENG-3917-escape-msr-facts branch from 157d8db to 7d81ed5 Compare October 22, 2026 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

smoke-modern Run modern smoke test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants