Skip to content

Commit 382921d

Browse files
AaronDDMclaude
andcommitted
fix(dashboard): never print API keys to terminal
Remove the "print to terminal" option from API key delivery to prevent keys from leaking in terminal scrollback, shell history, or CI logs. Replace with "save to file" which writes to a temp file with 0600 permissions. The three options are now: 1. Activate in CLI keyring (key never leaves the process) 2. Copy to clipboard (key never appears in terminal output) 3. Save to temp file (restrictive permissions, user deletes after) Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
1 parent 7bf588b commit 382921d

1 file changed

Lines changed: 11 additions & 5 deletions

File tree

internal/cli/dashboard/keys.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package dashboard
22

33
import (
44
"fmt"
5+
"os"
6+
"path/filepath"
57
"time"
68

79
"github.com/spf13/cobra"
@@ -178,12 +180,13 @@ Set an active app with: nylas dashboard apps use <app-id> --region <region>`,
178180
}
179181

180182
// handleAPIKeyDelivery prompts the user to choose how to handle the newly created key.
183+
// The API key is never printed to stdout to prevent leaking it in terminal history or logs.
181184
func handleAPIKeyDelivery(apiKey, appID, region string) error {
182185
fmt.Println("\nWhat would you like to do with this API key?")
183186
fmt.Println()
184187
_, _ = common.Cyan.Println(" [1] Activate for this CLI (recommended)")
185188
fmt.Println(" [2] Copy to clipboard")
186-
fmt.Println(" [3] Print to terminal")
189+
fmt.Println(" [3] Save to file")
187190
fmt.Println()
188191

189192
choice, err := readLine("Choose [1-3]: ")
@@ -203,15 +206,18 @@ func handleAPIKeyDelivery(apiKey, appID, region string) error {
203206
case "2":
204207
if err := common.CopyToClipboard(apiKey); err != nil {
205208
_, _ = common.Yellow.Printf(" Clipboard unavailable: %v\n", err)
206-
fmt.Println(" Falling back to print:")
207-
fmt.Printf(" %s\n", apiKey)
209+
_, _ = common.Dim.Println(" Try option [3] to save to a file instead")
208210
return nil
209211
}
210212
_, _ = common.Green.Println("✓ API key copied to clipboard")
211213

212214
case "3":
213-
fmt.Println()
214-
fmt.Println(apiKey)
215+
keyFile := filepath.Join(os.TempDir(), "nylas-api-key.txt")
216+
if err := os.WriteFile(keyFile, []byte(apiKey+"\n"), 0o600); err != nil { // #nosec G306
217+
return wrapDashboardError(fmt.Errorf("failed to write key file: %w", err))
218+
}
219+
_, _ = common.Green.Printf("✓ API key saved to: %s\n", keyFile)
220+
_, _ = common.Dim.Println(" Read it, then delete the file")
215221

216222
default:
217223
return dashboardError("invalid selection", "Choose 1-3")

0 commit comments

Comments
 (0)