Skip to content

Commit 8a63773

Browse files
committed
fix(macos): mask sensitive wizard cli prompts
1 parent 727398f commit 8a63773

2 files changed

Lines changed: 32 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Docs: https://docs.openclaw.ai
2525
### Fixes
2626

2727
- Agents/models: forward model `maxTokens` as the default output-token limit for OpenAI-compatible Responses and Completions transports when no runtime override is provided, preventing provider defaults from silently truncating larger outputs. (#76645) Thanks @joeyfrasier.
28+
- macOS CLI/onboarding: honor sensitive wizard text steps in `openclaw-mac wizard` with termios no-echo input, suppressing saved credential previews while preserving long API keys and gateway tokens. Fixes #76698. Thanks @anurag-bg-neu and @sallyom.
2829
- Control UI/Skills: fix skill detail modal silently failing to open in all browsers by deferring `showModal()` until the dialog element is connected to the DOM; the Lit `ref` callback fired before connection causing a `DOMException: HTMLDialogElement.showModal: Dialog element is not connected` on every skill click. Thanks @nickmopen.
2930
- Gateway/update: run `doctor --non-interactive --fix` after Control UI global package updates before reporting success, so legacy config is migrated before the gateway restart. Thanks @stevenchouai.
3031
- Gateway/cron: stop a lazy cron startup that loses a hot-reload race, preventing the old cron service from starting after reload has already replaced cron state.

apps/macos/Sources/OpenClawMacCLI/WizardCommand.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,12 @@ private func promptAnswer(for step: WizardStep) throws -> Any {
445445
case "text":
446446
let initial = anyCodableString(step.initialvalue)
447447
let prompt = step.placeholder ?? "Value"
448+
if step.sensitive == true {
449+
let sensitivePrompt = initial.isEmpty ? prompt : "\(prompt) (leave blank to keep existing)"
450+
let value = try readSensitiveLineWithPrompt(sensitivePrompt)
451+
let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines)
452+
return trimmed.isEmpty ? initial : trimmed
453+
}
448454
let value = try readLineWithPrompt("\(prompt)\(initial.isEmpty ? "" : " [\(initial)]")")
449455
let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines)
450456
return trimmed.isEmpty ? initial : trimmed
@@ -524,3 +530,28 @@ private func readLineWithPrompt(_ prompt: String) throws -> String {
524530
}
525531
return line
526532
}
533+
534+
private func readSensitiveLineWithPrompt(_ prompt: String) throws -> String {
535+
print("\(prompt): ", terminator: "")
536+
fflush(stdout)
537+
538+
var original = termios()
539+
guard tcgetattr(STDIN_FILENO, &original) == 0 else {
540+
throw WizardCliError.gatewayError("Could not configure hidden terminal input.")
541+
}
542+
543+
var hidden = original
544+
hidden.c_lflag &= ~tcflag_t(ECHO)
545+
guard tcsetattr(STDIN_FILENO, TCSANOW, &hidden) == 0 else {
546+
throw WizardCliError.gatewayError("Could not configure hidden terminal input.")
547+
}
548+
defer {
549+
_ = tcsetattr(STDIN_FILENO, TCSANOW, &original)
550+
print("")
551+
}
552+
553+
guard let line = readLine() else {
554+
throw WizardCliError.cancelled
555+
}
556+
return line
557+
}

0 commit comments

Comments
 (0)