CVE-2026-44972
GuardDog: Unsanitized human-readable scan output allows terminal escape injection from malicious package content
GuardDog is a CLI tool to identify malicious PyPI packages. From 2.6.0 to 2.9.0, GuardDog includes attacker-controlled filenames, file locations, messages, and code snippets in its default human-readable output without escaping terminal control characters. A malicious package can therefore inject ANSI or OSC escape sequences into analyst terminals or CI logs.
Attack profile
How easy it is to exploit
- Attack vector
- Local
- Complexity
- Low
- Privileges needed
- None
- User interaction
- Required
What an attacker can affect
- Confidentiality
- Low
- Integrity
- Low
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
5.0
GuardDog: Unsanitized human-readable scan output allows terminal escape injection from malicious package content
GuardDog is a CLI tool to identify malicious PyPI packages. From 2.6.0 to 2.9.0, GuardDog includes attacker-controlled filenames, file locations, messages, and code snippets in its default human-readable output without escaping terminal control characters. A malicious package can therefore inject ANSI or OSC escape sequences into analyst terminals or CI logs.
- Record
CVE-2026-44972- CVSS 3.1
- 5.0 Medium
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N - Weakness
- CWE-116
- Updated
- 2026-11-02
EUVDEUVD-2026-32534
5.0
GuardDog is a CLI tool to identify malicious PyPI packages. From 2.6.0 to 2.9.0, GuardDog includes attacker-controlled filenames, file locations, messages, and code snippets in its default human-readable output without escaping terminal control characters. A malicious package can therefore inject ANSI or OSC escape sequences into analyst terminals or CI logs.
- Record
EUVD-2026-32534- CVSS 3.1
- 5.0 Medium
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-m5p4-gvpx-4mvr
5.0
GuardDog: Unsanitized human-readable scan output allows terminal escape injection from malicious package content
Summary
GuardDog includes attacker-controlled filenames, file locations, messages, and code snippets in its default human-readable output without escaping terminal control characters. A malicious package can therefore inject ANSI or OSC escape sequences into analyst terminals or CI logs.
Description
The finding formatter stores file paths and snippets from scanned content:
location = file_path + ":" + str(start_line)
finding = {
"location": location,
"code": code,
"message": result["extra"]["message"],
}
The human-readable reporter later prints these values directly:
" * " + finding["message"] + " at " + finding["location"] + "\n " + _format_code_line_for_output(finding["code"])
No escaping is applied for control characters such as \x1b. A malicious package can therefore ship a filename like:
evil\x1b[2J.py
or matched source lines containing terminal escapes, which survive into the final CLI output.
Reproduction summary
- Create a file whose name contains
\x1b[2J. - Feed a semgrep-style result referencing that file into
Analyzer._format_semgrep_response(). - Render the result with
HumanReadableReporter.print_scan_results(). - The output string contains the raw escape bytes, which a terminal may interpret.
Key code paths
guarddog/analyzer/analyzer.py:377-392guarddog/reporters/human_readable.py:36-42guarddog/reporters/human_readable.py:84-91
Practical impact
This can be used to:
- clear or rewrite analyst terminal output
- inject misleading or spoofed log content in CI
- emit clickable OSC 8 hyperlinks or title changes in compatible terminals
Prior public disclosure check
As of 2026-03-18, no matching public GitHub advisory, CVE, or public repo issue was found for this specific bug.
Suggested fix
Escape or strip terminal control characters before rendering any attacker-controlled value in human-readable output. This should cover package names, file paths, messages, and code snippets.
- Record
GHSA-m5p4-gvpx-4mvr- CVSS 3.1
- 5.0 Medium
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N - Weakness
- CWE-116
- Updated
- 2026-11-02
NVD
5.0
GuardDog is a CLI tool to identify malicious PyPI packages. From 2.6.0 to 2.9.0, GuardDog includes attacker-controlled filenames, file locations, messages, and code snippets in its default human-readable output without escaping terminal control characters. A malicious package can therefore inject ANSI or OSC escape sequences into analyst terminals or CI logs.
- Record
CVE-2026-44972- CVSS 3.1
- 5.0 Medium
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N - Weakness
- CWE-116
- Updated
- 2026-11-02
OSV
5.0
GuardDog: Unsanitized human-readable scan output allows terminal escape injection from malicious package content
GuardDog is a CLI tool to identify malicious PyPI packages. From 2.6.0 to 2.9.0, GuardDog includes attacker-controlled filenames, file locations, messages, and code snippets in its default human-readable output without escaping terminal control characters. A malicious package can therefore inject ANSI or OSC escape sequences into analyst terminals or CI logs.
- Record
CVE-2026-44972- CVSS 3.1
- 5.0 Medium
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N - Weakness
- CWE-116
- Updated
- 2026-11-02
OSVGHSA-m5p4-gvpx-4mvr
5.0
GuardDog: Unsanitized human-readable scan output allows terminal escape injection from malicious package content
Summary
GuardDog includes attacker-controlled filenames, file locations, messages, and code snippets in its default human-readable output without escaping terminal control characters. A malicious package can therefore inject ANSI or OSC escape sequences into analyst terminals or CI logs.
Description
The finding formatter stores file paths and snippets from scanned content:
location = file_path + ":" + str(start_line)
finding = {
"location": location,
"code": code,
"message": result["extra"]["message"],
}
The human-readable reporter later prints these values directly:
" * " + finding["message"] + " at " + finding["location"] + "\n " + _format_code_line_for_output(finding["code"])
No escaping is applied for control characters such as \x1b. A malicious package can therefore ship a filename like:
evil\x1b[2J.py
or matched source lines containing terminal escapes, which survive into the final CLI output.
Reproduction summary
- Create a file whose name contains
\x1b[2J. - Feed a semgrep-style result referencing that file into
Analyzer._format_semgrep_response(). - Render the result with
HumanReadableReporter.print_scan_results(). - The output string contains the raw escape bytes, which a terminal may interpret.
Key code paths
guarddog/analyzer/analyzer.py:377-392guarddog/reporters/human_readable.py:36-42guarddog/reporters/human_readable.py:84-91
Practical impact
This can be used to:
- clear or rewrite analyst terminal output
- inject misleading or spoofed log content in CI
- emit clickable OSC 8 hyperlinks or title changes in compatible terminals
Prior public disclosure check
As of 2026-03-18, no matching public GitHub advisory, CVE, or public repo issue was found for this specific bug.
Suggested fix
Escape or strip terminal control characters before rendering any attacker-controlled value in human-readable output. This should cover package names, file paths, messages, and code snippets.
- Record
GHSA-m5p4-gvpx-4mvr- CVSS 3.1
- 5.0 Medium
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N - Weakness
- CWE-116
- Updated
- 2026-11-02
OSVPYSEC-2026-2506
5.0
GuardDog: Unsanitized human-readable scan output allows terminal escape injection from malicious package content
Summary
GuardDog includes attacker-controlled filenames, file locations, messages, and code snippets in its default human-readable output without escaping terminal control characters. A malicious package can therefore inject ANSI or OSC escape sequences into analyst terminals or CI logs.
Description
The finding formatter stores file paths and snippets from scanned content:
location = file_path + ":" + str(start_line)
finding = {
"location": location,
"code": code,
"message": result["extra"]["message"],
}
The human-readable reporter later prints these values directly:
" * " + finding["message"] + " at " + finding["location"] + "\n " + _format_code_line_for_output(finding["code"])
No escaping is applied for control characters such as \x1b. A malicious package can therefore ship a filename like:
evil\x1b[2J.py
or matched source lines containing terminal escapes, which survive into the final CLI output.
Reproduction summary
- Create a file whose name contains
\x1b[2J. - Feed a semgrep-style result referencing that file into
Analyzer._format_semgrep_response(). - Render the result with
HumanReadableReporter.print_scan_results(). - The output string contains the raw escape bytes, which a terminal may interpret.
Key code paths
guarddog/analyzer/analyzer.py:377-392guarddog/reporters/human_readable.py:36-42guarddog/reporters/human_readable.py:84-91
Practical impact
This can be used to:
- clear or rewrite analyst terminal output
- inject misleading or spoofed log content in CI
- emit clickable OSC 8 hyperlinks or title changes in compatible terminals
Prior public disclosure check
As of 2026-03-18, no matching public GitHub advisory, CVE, or public repo issue was found for this specific bug.
Suggested fix
Escape or strip terminal control characters before rendering any attacker-controlled value in human-readable output. This should cover package names, file paths, messages, and code snippets.
- Record
PYSEC-2026-2506- CVSS 3.1
- 5.0 Medium
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N - Updated
- 2026-11-02
Affected products
Affected packages
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-44972 is a medium vulnerability (CVSS 5.0) in Datadog Guarddog, published May 11, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.11%, the 1st percentile. No source names a fixed version.