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
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 activeterminal controls. The declarative
post_install_stepsrunpath instead usesspawnFencedwith inherited stdout and stderr. A formula controls theexecutable 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 mustremain after sanitization.
Affected code:
spawnFencedinsrc/core/post_install_steps.zig:1176-1208src/core/post_install_steps.zig:1189-1193.src/core/dsl/builtins/process.zig, wheresystemused the dual-streamfilter pump.
Regression test:
run strips terminal escapes a formula emits while preserving textHomebrew catalog reference
The official
fontconfigformula uses the declarative command:fc-cache --verboseprints font-directory names. In a controlled test, a localfont 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.
fontconfigis not malicious; itsverbose path shows how attacker-influenced filenames can reach child output.
The catalog contained 34 formulae with 36 declarative
runsteps, so otherformula-controlled commands also reach
spawnFenced.Expected behavior
Declarative
runstdout and stderr must use the same tested terminal sanitizeras the Ruby-like DSL. JSON and NDJSON stdout suppression must keep precedence.
The explicit
MALT_ALLOW_RAW_POST_INSTALL=1opt-out should keep its currentbehavior.
Fix: #846