{"id":"CVE-2026-44972","aliases":["EUVD-2026-32534","GHSA-m5p4-gvpx-4mvr","PYSEC-2026-2506"],"status":"published","title":"GuardDog: Unsanitized human-readable scan output allows terminal escape injection from malicious package content","description":"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.","severity":{"version":"3.1","score":5,"vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00113,"percentile":0.0141,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":false},"cwes":["CWE-116"],"published":"2026-05-11T14:43:43Z","modified":"2026-10-28T02:30:42Z","affected":[{"source":"ghsa","ecosystem":"PyPI","package":"guarddog","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.6.0"},{"last_affected":"2.9.0"}]}]},{"source":"osv","ecosystem":"PyPI","package":"guarddog","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.6.0"},{"last_affected":"2.9.0"}]}],"versions":["2.6.0","2.7.0","2.7.1","2.8.4","2.9.0"]},{"source":"osv","ecosystem":"PyPI","package":"guarddog","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.6.0"},{"last_affected":"2.9.0"}]}],"versions":["2.6.0","2.7.0","2.7.1","2.8.4","2.9.0"]}],"products":[{"vendor":"datadog","product":"guarddog"}],"references":[{"url":"https://github.com/DataDog/guarddog/security/advisories/GHSA-m5p4-gvpx-4mvr","tags":["x_refsource_CONFIRM","advisory","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-44972","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-m5p4-gvpx-4mvr","tags":["advisory"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/44xxx/CVE-2026-44972.json","tags":["advisory"]},{"url":"https://github.com/DataDog/guarddog","tags":["package"]},{"url":"https://pypi.org/project/guarddog","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-44972","title":"GuardDog: Unsanitized human-readable scan output allows terminal escape injection from malicious package content","description":"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.","status":"published","published":"2026-05-27T14:42:00.807Z","modified":"2026-05-27T15:34:32.271Z","cvss":[{"version":"3.1","score":5,"vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N","level":"medium","assessor":"cna"}],"cwes":["CWE-116"],"updated_at":"2026-11-02T13:43:00.288193Z"}],"euvd":[{"id":"EUVD-2026-32534","description":"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.","status":"published","published":"2026-05-27T14:42:00Z","modified":"2026-05-27T15:34:32Z","cvss":[{"version":"3.1","score":5,"vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N","level":"medium"}],"updated_at":"2026-11-02T18:21:04.415835Z"}],"ghsa":[{"id":"GHSA-m5p4-gvpx-4mvr","title":"GuardDog: Unsanitized human-readable scan output allows terminal escape injection from malicious package content","description":"# Summary\nGuardDog 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.\n\n# Description\nThe finding formatter stores file paths and snippets from scanned content:\n\n```python\nlocation = file_path + \":\" + str(start_line)\nfinding = {\n    \"location\": location,\n    \"code\": code,\n    \"message\": result[\"extra\"][\"message\"],\n}\n```\n\nThe human-readable reporter later prints these values directly:\n\n```python\n\"  * \" + finding[\"message\"] + \" at \" + finding[\"location\"] + \"\\n    \" + _format_code_line_for_output(finding[\"code\"])\n```\n\nNo escaping is applied for control characters such as `\\x1b`. A malicious package can therefore ship a filename like:\n\n```text\nevil\\x1b[2J.py\n```\n\nor matched source lines containing terminal escapes, which survive into the final CLI output.\n\n# Reproduction summary\n1. Create a file whose name contains `\\x1b[2J`.\n2. Feed a semgrep-style result referencing that file into `Analyzer._format_semgrep_response()`.\n3. Render the result with `HumanReadableReporter.print_scan_results()`.\n4. The output string contains the raw escape bytes, which a terminal may interpret.\n\n# Key code paths\n- `guarddog/analyzer/analyzer.py:377-392`\n- `guarddog/reporters/human_readable.py:36-42`\n- `guarddog/reporters/human_readable.py:84-91`\n\n# Practical impact\nThis can be used to:\n- clear or rewrite analyst terminal output\n- inject misleading or spoofed log content in CI\n- emit clickable OSC 8 hyperlinks or title changes in compatible terminals\n\n# Prior public disclosure check\nAs of 2026-03-18, no matching public GitHub advisory, CVE, or public repo issue was found for this specific bug.\n\n# Suggested fix\nEscape 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.","status":"published","published":"2026-05-11T14:43:43Z","modified":"2026-06-08T23:42:21Z","cvss":[{"version":"3.1","score":5,"vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-116"],"updated_at":"2026-11-02T14:40:21.48274Z"}],"nvd":[{"id":"CVE-2026-44972","description":"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.","status":"published","published":"2026-05-27T15:16:29.69Z","modified":"2026-10-26T11:10:00.157Z","cvss":[{"version":"3.1","score":5,"vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N","level":"medium","assessor":"secondary"}],"cwes":["CWE-116"],"updated_at":"2026-11-02T14:12:20.885865Z"}],"osv":[{"id":"CVE-2026-44972","title":"GuardDog: Unsanitized human-readable scan output allows terminal escape injection from malicious package content","description":"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.","status":"published","published":"2026-05-27T14:42:00.807Z","modified":"2026-10-28T02:30:42.470859436Z","cvss":[{"version":"3.1","score":5,"vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-116"],"updated_at":"2026-11-02T15:45:05.172514Z"},{"id":"GHSA-m5p4-gvpx-4mvr","title":"GuardDog: Unsanitized human-readable scan output allows terminal escape injection from malicious package content","description":"# Summary\nGuardDog 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.\n\n# Description\nThe finding formatter stores file paths and snippets from scanned content:\n\n```python\nlocation = file_path + \":\" + str(start_line)\nfinding = {\n    \"location\": location,\n    \"code\": code,\n    \"message\": result[\"extra\"][\"message\"],\n}\n```\n\nThe human-readable reporter later prints these values directly:\n\n```python\n\"  * \" + finding[\"message\"] + \" at \" + finding[\"location\"] + \"\\n    \" + _format_code_line_for_output(finding[\"code\"])\n```\n\nNo escaping is applied for control characters such as `\\x1b`. A malicious package can therefore ship a filename like:\n\n```text\nevil\\x1b[2J.py\n```\n\nor matched source lines containing terminal escapes, which survive into the final CLI output.\n\n# Reproduction summary\n1. Create a file whose name contains `\\x1b[2J`.\n2. Feed a semgrep-style result referencing that file into `Analyzer._format_semgrep_response()`.\n3. Render the result with `HumanReadableReporter.print_scan_results()`.\n4. The output string contains the raw escape bytes, which a terminal may interpret.\n\n# Key code paths\n- `guarddog/analyzer/analyzer.py:377-392`\n- `guarddog/reporters/human_readable.py:36-42`\n- `guarddog/reporters/human_readable.py:84-91`\n\n# Practical impact\nThis can be used to:\n- clear or rewrite analyst terminal output\n- inject misleading or spoofed log content in CI\n- emit clickable OSC 8 hyperlinks or title changes in compatible terminals\n\n# Prior public disclosure check\nAs of 2026-03-18, no matching public GitHub advisory, CVE, or public repo issue was found for this specific bug.\n\n# Suggested fix\nEscape 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.","status":"published","published":"2026-05-11T14:43:43Z","modified":"2026-07-13T16:42:37.969733554Z","cvss":[{"version":"3.1","score":5,"vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-116"],"updated_at":"2026-11-02T15:46:51.463834Z"},{"id":"PYSEC-2026-2506","title":"GuardDog: Unsanitized human-readable scan output allows terminal escape injection from malicious package content","description":"# Summary\nGuardDog 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.\n\n# Description\nThe finding formatter stores file paths and snippets from scanned content:\n\n```python\nlocation = file_path + \":\" + str(start_line)\nfinding = {\n    \"location\": location,\n    \"code\": code,\n    \"message\": result[\"extra\"][\"message\"],\n}\n```\n\nThe human-readable reporter later prints these values directly:\n\n```python\n\"  * \" + finding[\"message\"] + \" at \" + finding[\"location\"] + \"\\n    \" + _format_code_line_for_output(finding[\"code\"])\n```\n\nNo escaping is applied for control characters such as `\\x1b`. A malicious package can therefore ship a filename like:\n\n```text\nevil\\x1b[2J.py\n```\n\nor matched source lines containing terminal escapes, which survive into the final CLI output.\n\n# Reproduction summary\n1. Create a file whose name contains `\\x1b[2J`.\n2. Feed a semgrep-style result referencing that file into `Analyzer._format_semgrep_response()`.\n3. Render the result with `HumanReadableReporter.print_scan_results()`.\n4. The output string contains the raw escape bytes, which a terminal may interpret.\n\n# Key code paths\n- `guarddog/analyzer/analyzer.py:377-392`\n- `guarddog/reporters/human_readable.py:36-42`\n- `guarddog/reporters/human_readable.py:84-91`\n\n# Practical impact\nThis can be used to:\n- clear or rewrite analyst terminal output\n- inject misleading or spoofed log content in CI\n- emit clickable OSC 8 hyperlinks or title changes in compatible terminals\n\n# Prior public disclosure check\nAs of 2026-03-18, no matching public GitHub advisory, CVE, or public repo issue was found for this specific bug.\n\n# Suggested fix\nEscape 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.","status":"published","published":"2026-07-13T15:15:44.270436Z","modified":"2026-07-13T16:31:56.153094929Z","cvss":[{"version":"3.1","score":5,"vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N","level":"medium"}],"updated_at":"2026-11-02T15:52:55.961245Z"}]}}
