Skip to content

util.stripVTControlCharacters() fails to strip OSC 8 hyperlinks whose URI contains characters like "(" #64313

Description

@sindresorhus

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:

label

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions