Version
v22.22.3 (also reproduces on main)
Platform
Any (logic bug in a bundled regex, not platform-specific)
Subsystem
util
What steps will reproduce the bug?
import {stripVTControlCharacters} from 'node:util';
// OSC 8 hyperlink whose URI contains `(`, a character RFC 3986 allows unencoded.
const link = '\u001B]8;;https://example.com/(foo\u0007label\u001B]8;;\u0007';
console.log(stripVTControlCharacters(link));
How often does it reproduce? Is there a required condition?
Always, whenever an OSC 8 hyperlink URI contains one of: !, $, ', (, ), *, +, ,, [, ].
What is the expected behavior? Why is that the expected behavior?
The visible label with all escape sequences removed:
What do you see instead?
The hyperlink is not stripped and most of the URI (plus the BEL terminator) leaks into the output. The returned string is:
'ttps://example.com/(foo\u0007label'
Additional information
stripVTControlCharacters() uses a bundled copy of chalk/ansi-regex in lib/internal/util/inspect.js, pinned to ansi-regex f338e18 (v6.1.0). That version matches OSC parameter/URI bytes with the restricted class [-a-zA-Z\d/#&.:=?%@~_], which omits ten characters RFC 3986 permits unencoded in a URI: !, $, ', (, ), *, +, ,, [, ]. When the URI contains any of them, the OSC branch never reaches the string terminator, so the sequence is left largely intact.
ansi-regex fixed this in v6.2.0 (72bc570) by matching OSC sequences generically as ESC ] … ST (non-greedy up to the first string terminator) instead of enumerating allowed URI bytes. Syncing the bundled regex to ansi-regex >=6.2.0 resolves it.
Version
v22.22.3 (also reproduces on
main)Platform
Any (logic bug in a bundled regex, not platform-specific)
Subsystem
util
What steps will reproduce the bug?
How often does it reproduce? Is there a required condition?
Always, whenever an OSC 8 hyperlink URI contains one of:
!,$,',(,),*,+,,,[,].What is the expected behavior? Why is that the expected behavior?
The visible label with all escape sequences removed:
What do you see instead?
The hyperlink is not stripped and most of the URI (plus the BEL terminator) leaks into the output. The returned string is:
Additional information
stripVTControlCharacters()uses a bundled copy ofchalk/ansi-regexinlib/internal/util/inspect.js, pinned to ansi-regexf338e18(v6.1.0). That version matches OSC parameter/URI bytes with the restricted class[-a-zA-Z\d/#&.:=?%@~_], which omits ten characters RFC 3986 permits unencoded in a URI:!,$,',(,),*,+,,,[,]. When the URI contains any of them, the OSC branch never reaches the string terminator, so the sequence is left largely intact.ansi-regex fixed this in v6.2.0 (
72bc570) by matching OSC sequences generically asESC ] … ST(non-greedy up to the first string terminator) instead of enumerating allowed URI bytes. Syncing the bundled regex to ansi-regex >=6.2.0 resolves it.