Describe the bug
containerImageMustNotUseForbiddenTags reports the raw template string as an unpinned image when a job's container is an expression instead of a literal. The finding shows the expression itself:
HIGH [ISSUE-103] job "release/build-local-artifacts" uses image without digest pinning: ${{ matrix.container && matrix.container.image || null }}
There is no tag to pin in the workflow text: the concrete images live in the matrix include list in the same file (and most matrix rows have no container at all). cargo-dist generates exactly this shape for every Rust project using it, so the control self-flags across that ecosystem and users disable it entirely to silence one templated line, losing coverage on real image refs.
To Reproduce
- A workflow with a matrix strategy where some include entries set
container: {image: ...} and others do not.
- The job declares
container: ${{ matrix.container && matrix.container.image || null }} (cargo-dist's generated release.yml does this).
- Run
plumber analyze on the repo: ISSUE-103 reports the expression string as the image.
Expected behavior
Resolve the expression against the statically-known matrix include list and evaluate each concrete image; when the expression cannot be resolved statically, skip with a note or emit a distinct informational finding ("unresolved image expression"), instead of treating the template text as a floating tag.
Screenshots
n/a, finding text above.
Relevant versions and configuration files
- OS: Windows (also reproduces on Linux)
- Plumber version: v0.4.29
- GitHub provider, no config file (built-in defaults)
Relevant logs
Finding line quoted above.
Additional context
Today's workaround is containerImageMustNotUseForbiddenTags: enabled: false in an overlay, which is a blunt instrument for a single templated line.
Describe the bug
containerImageMustNotUseForbiddenTagsreports the raw template string as an unpinned image when a job'scontaineris an expression instead of a literal. The finding shows the expression itself:There is no tag to pin in the workflow text: the concrete images live in the matrix include list in the same file (and most matrix rows have no container at all). cargo-dist generates exactly this shape for every Rust project using it, so the control self-flags across that ecosystem and users disable it entirely to silence one templated line, losing coverage on real image refs.
To Reproduce
container: {image: ...}and others do not.container: ${{ matrix.container && matrix.container.image || null }}(cargo-dist's generated release.yml does this).plumber analyzeon the repo: ISSUE-103 reports the expression string as the image.Expected behavior
Resolve the expression against the statically-known matrix include list and evaluate each concrete image; when the expression cannot be resolved statically, skip with a note or emit a distinct informational finding ("unresolved image expression"), instead of treating the template text as a floating tag.
Screenshots
n/a, finding text above.
Relevant versions and configuration files
Relevant logs
Finding line quoted above.
Additional context
Today's workaround is
containerImageMustNotUseForbiddenTags: enabled: falsein an overlay, which is a blunt instrument for a single templated line.