# Log and terminal escape injection

Attacker-controlled strings reaching logs or terminals without stripping control/escape sequences

_Area: Web infrastructure and server-side requests. Seen in 2 disclosed reports; latest 2026-10-20. Updated 2026-11-02._

## How it works
A log sink writes attacker-controlled bytes to a terminal or log file without escaping. The assumption that breaks is that logged data is inert text: a terminal interprets bytes, so an ANSI escape sequence in a username, path or header is executed by the operator's terminal, not displayed. The same class covers a security filter built as a regex whose escaper misses metacharacters, so the filter silently fails to match [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-8r9p-f939-6h3c.md).

## Where it shows up
- Auth-failure logging that echoes the supplied username verbatim (BasicAuth) [E3](https://bugbountylibrary.com/r/h1%3A223363.md)
- 404 paths, request headers, or any request field written to a console/log tailed by an operator [E3](https://bugbountylibrary.com/r/h1%3A223363.md)
- Security controls implemented as dynamically built regexes: check the escaper's character class against the full metacharacter set [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-8r9p-f939-6h3c.md)
- Filters built once at construction from a declared list, so a bad entry is never re-checked [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-8r9p-f939-6h3c.md)
- WAF response-body rules matching plain alphanumeric strings with no special characters [E1](https://bugbountylibrary.com/r/blog%3Ablog-sicuranext-com-response-filter-denial-of-service-a-new-way-to-shutdown-a-website.md)

## How to review
For each log sink, trace every attacker-influenced value to the write call and confirm control/escape bytes are stripped or encoded before output. The invariant: no byte from a request reaches a terminal or log unescaped. For regex-based filters, generate the pattern from each declared value and test it against itself; every declared sensitive value must match its own pattern. For WAF response rules, any rule matching a plain string lacking special characters is reflectable and therefore a DoS primitive [E1](https://bugbountylibrary.com/r/blog%3Ablog-sicuranext-com-response-filter-denial-of-service-a-new-way-to-shutdown-a-website.md).

## How finders spotted it
- Recognized a previously fixed 2010 WEBrick escape-sequence bug and checked whether BasicAuth's failure logging still emitted raw usernames [E3](https://bugbountylibrary.com/r/h1%3A223363.md)
- Read the new sensitiveHeaders filter construction, noticed escapeRegex's character class omitted `^ | [ { }`, reasoned `^` becomes a mid-pattern anchor and `|` splits alternation, then verified with a pure-regex harness and a two-server redirect PoC, using metacharacter-free names as controls to prove the strip branch ran [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-8r9p-f939-6h3c.md)
- Read OWASP CRS RESPONSE-951-DATA-LEAKAGES-SQL.conf and noticed rules match plain alphanumeric strings (ORA- followed by digits) with no special characters, making them trivially reflectable; validated by comparing `?s=ORA-1` (200) vs `?s=ORA-1234` (403) across 15M WordPress sites from Common Crawl [E1](https://bugbountylibrary.com/r/blog%3Ablog-sicuranext-com-response-filter-denial-of-service-a-new-way-to-shutdown-a-website.md)

## Variants seen
- Terminal escape injection via logged username [E3](https://bugbountylibrary.com/r/h1%3A223363.md)
- Regex-escaper omission causing a header-stripping filter to silently not match [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-8r9p-f939-6h3c.md)
- WAF response-body rule triggered by reflected plain-string input, blocking the page [E1](https://bugbountylibrary.com/r/blog%3Ablog-sicuranext-com-response-filter-denial-of-service-a-new-way-to-shutdown-a-website.md)

## Impact and severity
E3 altered the operator's terminal window title only. E2 leaked declared credential headers across cross-origin redirects, worsened by protocol downgrade exposing them in cleartext and by downstream wrappers like axios inheriting the bypass. E1 turned any stored-input page into a DoS: mass-submitting the trigger string to all products/reviews shut down an entire catalog, and HTTP Range requests bypassed the block to read content. Impact scales with how many endpoints reflect the trigger [E1](https://bugbountylibrary.com/r/blog%3Ablog-sicuranext-com-response-filter-denial-of-service-a-new-way-to-shutdown-a-website.md) and how many stacks delegate to the flawed filter [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-8r9p-f939-6h3c.md).

## Seen in real software
Open-source packages and projects, and products, where this pattern was found. If the target runs one, compare the version it runs with the fix.
- **follow-redirects (npm)** >= 1.16.0, < 1.16.1, fixed in 1.16.1: follow-redirects sensitiveHeaders regex escaping can expose credential headers (CVE-2026-111755). Report: https://bugbountylibrary.com/r/ghsa%3AGHSA-8r9p-f939-6h3c.md. Fix: https://github.com/follow-redirects/follow-redirects/commit/080a76d0e125b37bf81717368a61d5dc37aa56c8
- **Ruby**: Escape sequence injection vulnerability in WEBrick BasicAuth (CVE-2017-10784). Report: https://bugbountylibrary.com/r/h1%3A223363.md

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Ablog-sicuranext-com-response-filter-denial-of-service-a-new-way-to-shutdown-a-website.md
- E2: https://bugbountylibrary.com/r/ghsa%3AGHSA-8r9p-f939-6h3c.md
- E3: https://bugbountylibrary.com/r/h1%3A223363.md
