Is your feature request related to a problem? Please describe.
The extension has no way to set a certificate password. winapp.certGenerate passes no --password, so every certificate it produces uses the winapp CLI's documented development default (password). winapp.certInstall likewise passes no --password, so it can only install certificates that use that default. The only password handling anywhere in the extension is winapp.certInfo, which prompts for one in order to read an existing certificate.
Consequences:
- A user who generates a certificate outside the extension with a non-default password cannot install it via
winapp.certInstall — the command fails and the extension surfaces no way to supply the password.
- A user who wants a generated certificate to have anything other than the well-known default password has to drop to a terminal and run the CLI by hand.
This was split out of the winapp cert generate command-surface work so that command could land without also settling the password design, which spans several commands and has a security prerequisite (below).
Describe the solution you'd like
Support a custom password consistently across the cert commands, and settle the design once rather than per command:
cert generate --password — opt-in, not a prompt on the default path. The CLI default (password) is appropriate for a self-signed local test certificate, so a mandatory prompt in a dev-loop command would be friction for no real threat reduction.
cert install --password — needed to install certificates the extension did not generate.
- The equivalent question for
winapp.sign and winapp.pack --cert, which are being looked at separately but would inherit the same transport concerns.
Constraints the implementation should respect:
- No password in
settings.json. Settings are synced, are frequently committed as .vscode/settings.json, and are rendered in plaintext in the Settings UI. If a password is persisted at all it belongs in context.secrets (SecretStorage).
- Pass passwords via
spawn with an args array and shell: false, following the precedent already set by winapp.certInfo, not by interpolating into a command string for Terminal.sendText.
- Redact in output.
runWinappCapture echoes > winapp ${args.join(' ')} to the output channel, and separately the CLI's own --json output includes a "password" field — so even a correct args-array transport re-leaks the value if raw CLI output is streamed to the channel. Both points need masking.
Additional context
Security prerequisite — the elevated path. runWinappCommandElevated / buildElevatedTerminalCommand compose a PowerShell string and sendText it into a non-elevated terminal, which then re-launches via Start-Process -Verb RunAs. A password routed through that construct is exposed in at least four places: the visible terminal buffer, PSReadLine's on-disk ConsoleHost_history.txt, the launcher process command line, and the elevated powershell.exe command line (readable by any process running as that user via Get-CimInstance Win32_Process).
There is no safe way to escape a secret through that path, so custom password support for anything that installs to the machine store should depend on the planned restructure of "Generate and install": generate un-elevated with --export-cer, then elevate only cert install <the .cer>, which carries no private key and needs no password at all. Where a .pfx install with a non-default password is genuinely unavoidable, the extension should decline to inline the secret and explain the alternative rather than silently leaking it.
Related unsurfaced cert generate options. The extension's command surface was built against winappcli ~0.3.1 while scripts/download-cli.ps1 downloads latest (now 0.6.x), so several options are unreachable from the UI. --publisher, --manifest, --output, --valid-days, --export-cer, and --if-exists are being addressed in the in-flight cert generate work; --password is tracked here. The underlying version drift — a 0.6.x CLI shipping behind a 0.3.x UI — is worth addressing separately, e.g. by pinning the downloaded CLI version or asserting a minimum version at activation using the CLI's --cli-schema self-description.
Is your feature request related to a problem? Please describe.
The extension has no way to set a certificate password.
winapp.certGeneratepasses no--password, so every certificate it produces uses the winapp CLI's documented development default (password).winapp.certInstalllikewise passes no--password, so it can only install certificates that use that default. The only password handling anywhere in the extension iswinapp.certInfo, which prompts for one in order to read an existing certificate.Consequences:
winapp.certInstall— the command fails and the extension surfaces no way to supply the password.This was split out of the
winapp cert generatecommand-surface work so that command could land without also settling the password design, which spans several commands and has a security prerequisite (below).Describe the solution you'd like
Support a custom password consistently across the
certcommands, and settle the design once rather than per command:cert generate --password— opt-in, not a prompt on the default path. The CLI default (password) is appropriate for a self-signed local test certificate, so a mandatory prompt in a dev-loop command would be friction for no real threat reduction.cert install --password— needed to install certificates the extension did not generate.winapp.signandwinapp.pack --cert, which are being looked at separately but would inherit the same transport concerns.Constraints the implementation should respect:
settings.json. Settings are synced, are frequently committed as.vscode/settings.json, and are rendered in plaintext in the Settings UI. If a password is persisted at all it belongs incontext.secrets(SecretStorage).spawnwith an args array andshell: false, following the precedent already set bywinapp.certInfo, not by interpolating into a command string forTerminal.sendText.runWinappCaptureechoes> winapp ${args.join(' ')}to the output channel, and separately the CLI's own--jsonoutput includes a"password"field — so even a correct args-array transport re-leaks the value if raw CLI output is streamed to the channel. Both points need masking.Additional context
Security prerequisite — the elevated path.
runWinappCommandElevated/buildElevatedTerminalCommandcompose a PowerShell string andsendTextit into a non-elevated terminal, which then re-launches viaStart-Process -Verb RunAs. A password routed through that construct is exposed in at least four places: the visible terminal buffer, PSReadLine's on-diskConsoleHost_history.txt, the launcher process command line, and the elevatedpowershell.execommand line (readable by any process running as that user viaGet-CimInstance Win32_Process).There is no safe way to escape a secret through that path, so custom password support for anything that installs to the machine store should depend on the planned restructure of "Generate and install": generate un-elevated with
--export-cer, then elevate onlycert install <the .cer>, which carries no private key and needs no password at all. Where a.pfxinstall with a non-default password is genuinely unavoidable, the extension should decline to inline the secret and explain the alternative rather than silently leaking it.Related unsurfaced
cert generateoptions. The extension's command surface was built against winappcli ~0.3.1 whilescripts/download-cli.ps1downloadslatest(now 0.6.x), so several options are unreachable from the UI.--publisher,--manifest,--output,--valid-days,--export-cer, and--if-existsare being addressed in the in-flightcert generatework;--passwordis tracked here. The underlying version drift — a 0.6.x CLI shipping behind a 0.3.x UI — is worth addressing separately, e.g. by pinning the downloaded CLI version or asserting a minimum version at activation using the CLI's--cli-schemaself-description.