CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-FWJX-9P69-H25H

GHSA-FWJX-9P69-H25H: Terminal Escape Sequence Injection in Oh My Posh

Amit Schendel
Amit Schendel
Senior Security Researcher

Jul 25, 2026·8 min read·44 visits

Executive Summary (TL;DR)

Oh My Posh rendered raw control characters from untrusted sources like directory names and Git commit logs, allowing attackers to hijack system clipboards or execute arbitrary commands upon terminal directory navigation.

Oh My Posh prior to version 29.35.1 is vulnerable to terminal escape sequence injection. Dynamic strings from directory names or Git repository metadata are written to the prompt output without neutralization, enabling unauthenticated remote code execution, clipboard hijacking, or terminal DoS when users navigate to malicious folders.

Vulnerability Overview

Oh My Posh is a popular, highly customizable prompt engine used across multiple shells (such as Bash, Zsh, Fish, PowerShell, Command Prompt, and NuShell) to render rich CLI themes. To display context-aware metadata, the engine queries the operating system and Version Control Systems (VCS) to extract active directory paths, Git branch details, and environment status. This dynamic prompt generation operates by formatting and writing text segments directly to standard output (stdout), which is subsequently parsed and rendered by the host terminal emulator.\n\nA terminal escape sequence injection vulnerability (tracked as GHSA-FWJX-9P69-H25H) exists in Oh My Posh prior to version 29.35.1. The flaw stems from the engine writing dynamic strings retrieved from untrusted external sources directly into the prompt rendering buffer without neutralizing raw control characters. An attacker who controls one of these data sources—such as by creating a folder with a malicious name or distributing a Git repository containing an engineered commit subject—can inject arbitrary ANSI or Operating System Command (OSC) control sequences.\n\nWhen a victim navigates to a directory containing the malicious payload or performs standard shell interactions inside an affected folder, Oh My Posh automatically processes the untrusted string. The terminal emulator receives the raw escape sequences, parses them as control directives, and performs automated actions on behalf of the user. This breaks the boundary between dynamic console text and terminal process control, allowing attackers to perform silent clipboard modifications, screen spoofing, or terminal denial-of-service.

Root Cause Analysis

The root cause of this vulnerability lies in the character-by-character rendering loop implemented within the terminal writer subsystem of Oh My Posh. In command-line environments, prompt engines write styled text using terminal control codes like ANSI escape sequences. Terminal emulators continually scan the standard output stream for special initiator bytes (such as the C0 Escape character \x1b or C1 control bytes) to alter text color, change the window title, or access advanced host integration protocols.\n\nPrior to the security patch, the character-writing routine did not inspect, sanitize, or filter dynamic text parsed from external context providers before printing to the stdout stream. This processing flow took place within the write(s rune) function in src/terminal/writer.go. While Oh My Posh's internal formatting sequences bypassed this routine through dedicated high-level styling helpers, any text representing the dynamic data of active prompt segments—such as path components, Git log responses, and command outputs—passed straight through to the lower-level writer verbatim.\n\nBecause the host terminal emulator's parsing engine cannot distinguish between layout styling emitted intentionally by Oh My Posh and rogue control sequences embedded in untrusted text fields, the stream became a direct vector for command execution. By placing control codes like the Escape character (\x1b) and the Bell character (\x07) inside directory names or Git metadata, an attacker can bypass the layout constraints and direct the terminal to parse and execute internal commands.\n\nmermaid\ngraph LR\n A["Untrusted Source (Git Log / Folder Name)"] --> B["Oh My Posh Rendering Loop (write())"]\n B --> C["Raw standard output (stdout) with unchecked C0/C1 runes"]\n C --> D["Terminal Emulator Stream Parser"]\n D --> E["Action Trigger (Clipboard Injection / Window Title Spoof)"]\n

Code Analysis

To understand the implementation flaw, consider the vulnerable logic within the character writer in src/terminal/writer.go. Prior to the patch, the write function processed character runes without performing sanitization checks on control characters, appending them directly to the active prompt string builder.\n\ngo\n// Vulnerable code in src/terminal/writer.go\nfunc write(s rune) {\n\tif isInvisible {\n\t\t// ...\n\t\treturn\n\t}\n\n\tif isHyperlink {\n\t\tbuilder.WriteRune(s) // Vulnerable write of untrusted link data\n\t\treturn\n\t}\n\n\t// ...\n\tbuilder.WriteRune(s) // Vulnerable write of raw segment runes\n}\n\n\nBecause builder.WriteRune(s) executes on all runes parsed from segment strings, any raw control bytes like \x1b (ESC) or \x07 (BEL) were stored inside the output stream. The security patch introduced in commit edcf3c88f3fb582e84358b385c49d33d04c04224 mitigates this vulnerability by adding an inline sanitization check, isControlRune(s), to drop dangerous character classes before they can reach the builder.\n\ngo\n// Patched code in src/terminal/writer.go\nfunc write(s rune) {\n\tif isInvisible {\n\t\treturn\n\t}\n\n\t// segment content (directory names, git metadata, environment variables,\n\t// command output) is potentially attacker-controlled and never passes through\n\t// this function when it's Oh My Posh's own styling; drop C0/C1 control runes\n\t// (ESC, BEL, CSI, OSC, ...) so they can't be interpreted as escape sequences\n\t// by the terminal, including inside a hyperlink target.\n\tif isControlRune(s) {\n\t\treturn\n\t}\n\n\tif isHyperlink {\n\t\tbuilder.WriteRune(s)\n\t\treturn\n\t}\n\n\tbuilder.WriteRune(s)\n}\n\n// isControlRune reports whether s is a C0 (0x00-0x1F), DEL (0x7F), or C1\n// (0x80-0x9F) control character. These are the bytes a terminal can interpret\n// as the start of an escape sequence; no legitimate rendered segment content needs them.\nfunc isControlRune(s rune) bool {\n\tif s == '\\n' {\n\t\treturn false\n\t}\n\n\treturn s <= 0x1f || (s >= 0x7f && s <= 0x9f)\n}\n\n\nThis boundary check drops all control characters within the C0 range (0x00 - 0x1F), the delete character (0x7F), and the C1 range (0x80 - 0x9F). These control character sets are responsible for initiating terminal instructions like CSI (Control Sequence Introducer) and OSC (Operating System Command). By stripping these bytes, the emulator parses the remaining string as safe, literal text.

Exploitation Methodology

Exploitation of GHSA-FWJX-9P69-H25H is highly reliable and can be achieved through two primary vectors: Git metadata poisoning and directory name injection. In a typical scenario, an attacker designs a payload that leverages Operating System Command 52 (OSC 52), which allows standard terminal programs to write to the system clipboard.\n\nTo craft a malicious Git repository, an attacker creates an empty repository and structures a commit subject with the necessary terminal command escape sequences. The sequence uses \033] to open an OSC control channel, 52;c; to direct a clipboard copy, a base64-encoded command string, and the \007 (BEL) byte to close the channel.\n\nbash\n# Construct a malicious commit payload\n# OSC 0 sets the terminal title to "HACKED"\n# OSC 52 writes "echo PWNED" into the clipboard buffer\nprintf 'feat: \033]0;HACKED\007\033]52;c;ZWNobyBQV05FRA==\007 update' > msg.txt\n\ngit commit --allow-empty -F msg.txt\n\n\nWhen a victim navigates to this directory, Oh My Posh executes internal commands to build the Git status segment (such as extracting the last commit title via git log). This output is fed into the rendering engine, passing the raw control bytes to stdout. As the terminal emulator processes the stream, the OSC 52 sequence executes, instantly writing the command echo PWNED to the host's system clipboard. If the user subsequently performs a paste operation, the payload executes inside their active shell.\n\nA secondary attack vector targets the file system directly on Unix-based systems. Because macOS and Linux filesystems permit the use of raw control characters within directory names, an attacker can create nested directories containing injection sequences. When the victim navigates into the compromised folder structure using the cd command, the path rendering segment processes the raw escape sequences, triggering the payload execution.

Impact Assessment

The security implications of GHSA-FWJX-9P69-H25H are significant due to the scope change (S:C in CVSS metrics) inherent to terminal escape sequence injections. Because the execution transitions from the prompt layout parser to the host terminal emulator, the attack bypasses shell boundaries and impacts the underlying operating system. The vulnerability has been assigned a CVSS v3.1 score of 6.3.\n\nThe primary operational risk is silent clipboard manipulation. Attackers can overwrite the victim's host clipboard with complex, malicious shell scripts. Given that developers and system administrators frequently paste commands, configuration snippets, and credentials, an attacker can reliably achieve arbitrary command execution. This technique does not require user validation beyond standard navigation or paste actions.\n\nAdditionally, attackers can execute terminal-based denial of service (DoS) and visual spoofing. By sending terminal control sequences that manipulate terminal windows (such as OSC 0 or OSC 2), attackers can change window titles to spoof running programs. They can also use ANSI sequence loops to corrupt terminal buffers, rendering the command line unresponsive and forcing the victim to terminate their session, potentially losing unsaved work.

Remediation & Fix Completeness

To remediate this vulnerability, users must update Oh My Posh immediately to version 29.35.1 or newer. Updates can be applied via major package managers across supported environments. For systems where binary updates cannot be executed immediately, administrators should implement defensive configuration changes to limit the impact.\n\nbash\n# Update via Homebrew (macOS/Linux)\nbrew update && brew upgrade oh-my-posh\n\n# Update via winget (Windows)\nwinget upgrade JanDeDobbeleer.OhMyPosh\n\n\nIf upgrading is not immediately possible, users can apply configuration-level workarounds. Modifying active Oh My Posh configuration JSON templates to remove dynamic segments—specifically the git and path blocks—removes the primary attack surfaces. Additionally, terminal emulators should be configured to disable clipboard integration. In tmux, this can be done by adding set -s set-clipboard off to the .tmux.conf file, and in iTerm2, by disabling the option 'Applications in terminal may access clipboard'.\n\nAn evaluation of the fix implemented in version 29.35.1 indicates that while it successfully blocks the execution of dangerous control sequences, some structural limitations remain. Specifically, the newline character \\n is explicitly exempted in isControlRune. An attacker can exploit this exception to inject line breaks into directory names or Git logs. This allows for prompt-spoofing attacks, where a modified output pushes the authentic prompt out of view and displays a fake console layout to capture input or credentials. Security teams should remain aware of these residual layout manipulation vectors.

Official Patches

JanDeDobbeleerOfficial Security Advisory and Remediation Guide
JanDeDobbeleerCommit of the official patch
JanDeDobbeleerv29.35.1 Release Page
JanDeDobbeleerv29.36.0 Release Page

Fix Analysis (1)

Technical Appendix

CVSS Score
6.3/ 10
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:L

Affected Systems

Oh My Posh on Windows, macOS, and Linux

Affected Versions Detail

Product
Affected Versions
Fixed Version
oh-my-posh
JanDeDobbeleer
< 29.35.129.35.1
AttributeDetail
CWE IDCWE-150
Attack VectorLocal
CVSS Score6.3
EPSS ScoreN/A (No associated CVE)
ImpactScope Change, Clipboard Hijacking, Potential Code Execution
Exploit StatusProof-of-Concept (PoC)
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1204.002User Execution: Malicious File
Execution
T1204User Execution
Execution
CWE-150
Improper Neutralization of Escape, Meta, or Control Characters

The application processes inputs containing control sequences and outputs them to a terminal stream without proper neutralization, allowing arbitrary terminal command execution.

Known Exploits & Detection

GitHub Security AdvisoryDetails and PoC commands for replicating the OSC 52 clipboard modification.

Vulnerability Timeline

Vulnerability patched in commit edcf3c88f3fb582e84358b385c49d33d04c04224
2026-07-23
Oh My Posh version 29.35.1 released containing the fix
2026-07-23
GitHub Security Advisory GHSA-FWJX-9P69-H25H published
2026-07-24

References & Sources

  • [1]GHSA-fwjx-9p69-h25h Advisory
  • [2]Security Patch Commit
  • [3]Oh My Posh Repository
  • [4]Release v29.35.1
  • [5]Release v29.36.0

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•1 day ago•CVE-2026-107844
5.3

CVE-2026-107844: Path Traversal Vulnerability in Contao ImagesController

A path traversal vulnerability (CWE-22) in Contao CMS allows unauthenticated remote attackers to bypass directory boundary restrictions in ImagesController and access files within the project directory.

Amit Schendel
Amit Schendel
8 views•5 min read
•1 day ago•CVE-2026-107848
3.5

CVE-2026-107848: Cross-Site Request Forgery (CSRF) in Contao Backend Actions via GET Requests

Contao Open Source CMS versions 4.0.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 contain a Cross-Site Request Forgery (CSRF) vulnerability in backend parameter handling. The `RequestTokenListener` component validates anti-CSRF tokens solely for HTTP POST requests, while GET-based declarative guards run only when an `act` parameter is present in the query string. Consequently, custom backend actions dispatched via alternative parameters such as `key=` can execute without CSRF token verification when triggered by an authenticated user.

Amit Schendel
Amit Schendel
7 views•5 min read
•1 day ago•CVE-2026-107843
5.3

CVE-2026-107843: Unthrottled Activation Email Resend and Account Enumeration in Contao CMS

Contao CMS versions 4.1.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 fail to validate form submission tokens and enforce rate limiting when processing activation email resend requests via HTTP POST, enabling resource exhaustion and account state enumeration.

Amit Schendel
Amit Schendel
8 views•4 min read
•1 day ago•CVE-2026-107842
5.3

CVE-2026-107842: Information Disclosure via Stale Indexing in Contao Search Module

An information disclosure vulnerability in Contao CMS allows unauthenticated site visitors to view protected page titles, URLs, and text excerpts through search queries when protected page indexing is disabled after previously being enabled.

Amit Schendel
Amit Schendel
10 views•4 min read
•1 day ago•GHSA-G38J-7V97-X298
6.5

GHSA-G38J-7V97-X298: Missing Authorization Check in Vikunja CalDAV Task Relation Creation

In Vikunja prior to version 2.6.0, relation creation via the CalDAV endpoint fails to invoke the TaskRelation.CanCreate authorization check. This missing access control allows an authenticated user to establish unauthorized relationships and perform write operations against any task, provided its unique identifier (UID) is known.

Alon Barad
Alon Barad
12 views•5 min read
•1 day ago•GHSA-3HC7-R24J-RPWC
6.8

GHSA-3hc7-r24j-rpwc: Cross-Project Task Disclosure via Subtask Expansion in Vikunja

A cross-project information disclosure vulnerability in Vikunja allows authenticated users with read access to one project to view private task details from unauthorized projects via subtask expansion parameters.

Alon Barad
Alon Barad
9 views•5 min read