tmatens/compose-lint · Security
compose-lint: Compose file text can issue GitHub Actions workflow commands through the compose-lint Action
- GHSA ID
- GHSA-6f4g-xm8v-pgv6
- CVE ID
- CVE-2026-123369
- Severity
- medium
- Published
- Updated
- CVSS
- 4.3 · CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N
- CVSS v3
- 4.3 · CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N
- CVSS v4
- 5.3 · CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:L/VA:N/SC:N/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Description
Impact
The GitHub Actions runner treats certain text in a step's output as commands. The legacy form, ##[command], is recognized anywhere in a line. compose-lint's text report prints service names, environment keys and lines of the Compose file, and it does not neutralize ##[. Inside the compose-lint Action, a Compose file from a pull request can therefore:
- create fake error or warning annotations on the pull request (
##[error],##[warning]) - fold the rest of the log, including the real verdict, out of sight (
##[group]) - blank out chosen strings for the rest of the log (
##[add-mask])
GitHub has postponed removing the deprecated set-output log command, so the runner still honors it. A test run of the Action on a GitHub-hosted runner confirmed that a ::set-output line from a Compose file is processed. Whether it can override the Action's own sarif-written output, which decides whether the SARIF upload step runs, has not been tested.
The exit code and the pass/fail result are not affected. Azure Pipelines parses the same ##[ syntax, so the pip package is listed for anyone printing the text report in other CI systems.
Found during an internal pre-1.0 security review.
Patches
Fixed in 0.31.0. The Action stops the runner from processing workflow commands while compose-lint's output is printed, using a random stop-commands token. The text report also escapes ##[, and :: at the start of a line, in anything taken from the Compose file.
Workarounds
- In your own workflow, wrap the compose-lint step in
::stop-commands::<random token>and::<random token>::. - Use
--format jsonor--format sarifrather than the text report when linting untrusted pull requests.
Reproduction
services:
web:
image: "nginx:1.25"
environment:
"##[error]DB_PASSWORD": placeholder
"##[group]svc":
image: "nginx:1.25"
privileged: true
Run through the Action, this produces a fake error annotation and folds the remaining log lines, including the FAIL verdict, into a collapsed group.
CWEs
- CWE-117 · Improper Output Neutralization for Logs
- CWE-150 · Improper Neutralization of Escape, Meta, or Control Sequences
References
- https://github.com/tmatens/compose-lint/security/advisories/GHSA-6f4g-xm8v-pgv6 ↗
- https://nvd.nist.gov/vuln/detail/CVE-2026-123369 ↗
- https://github.com/tmatens/compose-lint/pull/918 ↗
- https://github.com/tmatens/compose-lint/commit/672bd11145621f787c295fb11f3a859cdec1b38d ↗
- https://github.com/tmatens/compose-lint/releases/tag/v0.31.0 ↗
- https://github.com/advisories/GHSA-6f4g-xm8v-pgv6 ↗