Skip to content

Security: declarative post-install output can inject terminal control sequences #848

Description

@rustytrees

Bug description

The native Ruby-like DSL and system-Ruby fallback send child output through
term_sanitize, which removes OSC 52 clipboard writes and other active
terminal controls. The declarative post_install_steps run path instead uses
spawnFenced with inherited stdout and stderr. A formula controls the
executable and arguments, so it can write active escape sequences directly to
the user's terminal.

The PoC runs a keg-local helper with an OSC 52 payload. Before the fix, the
captured output still contained byte 0x1b. The surrounding visible text must
remain after sanitization.

Affected code:

Regression test:

  • run strips terminal escapes a formula emits while preserving text

Homebrew catalog reference

The official fontconfig formula uses the declarative command:

run "fc-cache", args: ["--force", "--really-force", "--verbose"], base: :bin

fc-cache --verbose prints font-directory names. In a controlled test, a local
font directory whose name contained an OSC 52 sequence caused the real command
to emit that raw sequence three times. The test captured output to a file and
did not send the payload to a terminal. fontconfig is not malicious; its
verbose path shows how attacker-influenced filenames can reach child output.

The catalog contained 34 formulae with 36 declarative run steps, so other
formula-controlled commands also reach spawnFenced.

Expected behavior

Declarative run stdout and stderr must use the same tested terminal sanitizer
as the Ruby-like DSL. JSON and NDJSON stdout suppression must keep precedence.
The explicit MALT_ALLOW_RAW_POST_INSTALL=1 opt-out should keep its current
behavior.

Fix: #846

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions