Skip to content

Commit e41235d

Browse files
committed
Prevent infinite rebuild loop in periodic Trivy scan
Restructure trivy_periodic_scan.yml so the git tag is only created after a successful rebuild (not before). If the rebuild still has vulnerabilities, a GitHub issue is opened for manual triage instead of looping endlessly. - Rename bump-tag → compute-next-version (dry_run: true) - Add create-tag job gated on update-image success - Add alert-on-failure job that opens a GitHub issue with duplicate prevention when remediation fails
1 parent 1d63fa1 commit e41235d

1 file changed

Lines changed: 79 additions & 9 deletions

File tree

.github/workflows/trivy_periodic_scan.yml

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,21 @@ jobs:
4747
deployments: write
4848
security-events: write
4949

50-
# If scan failed, bump tag and rebuild the image
51-
bump-tag:
50+
# If scan failed, compute next version (dry run) and attempt a rebuild.
51+
# The tag is only created after a successful rebuild to prevent
52+
# infinite bump loops when a CVE fix requires a major version upgrade
53+
# that a simple rebuild cannot provide.
54+
compute-next-version:
5255
needs: periodic-scan
5356
runs-on: ubuntu-latest
5457
if: ${{ !cancelled() && needs.periodic-scan.outputs.trivy_conclusion == 'failure' }}
5558
steps:
56-
- name: Bump version and push tag
59+
- name: Compute next version (dry run — no tag created)
5760
id: tag_version
5861
uses: mathieudutour/github-tag-action@a22cf08638b34d5badda920f9daf6e72c477b07b # v6.2
5962
with:
6063
github_token: ${{ secrets.GITHUB_TOKEN }}
64+
dry_run: true
6165
- name: Parse new version
6266
id: parsed
6367
uses: booxmedialtd/ws-action-parse-semver@7784200024d6b3fc01253e617ec0168daf603de3 # v1.4.7
@@ -68,19 +72,85 @@ jobs:
6872
new_version: ${{ steps.tag_version.outputs.new_version }}
6973
new_major_minor: ${{ steps.parsed.outputs.major }}.${{ steps.parsed.outputs.minor }}
7074
permissions:
71-
contents: write
72-
deployments: write
73-
security-events: write
75+
contents: read
7476

7577
update-image:
76-
needs: [get-image-reference, periodic-scan, bump-tag]
78+
needs: [get-image-reference, periodic-scan, compute-next-version]
7779
if: ${{ !cancelled() && needs.periodic-scan.outputs.trivy_conclusion == 'failure' }}
7880
uses: "./.github/workflows/docker_build.yml"
7981
with:
80-
REF_TO_CHECKOUT: ${{ needs.bump-tag.outputs.new_tag }}
81-
IMAGE_REFERENCES: "${{ needs.get-image-reference.outputs.image_repo }}:${{ needs.bump-tag.outputs.new_version }},${{ needs.get-image-reference.outputs.image_repo }}:${{ needs.bump-tag.outputs.new_major_minor }}"
82+
REF_TO_CHECKOUT: ${{ needs.get-image-reference.outputs.image_tag }}
83+
IMAGE_REFERENCES: "${{ needs.get-image-reference.outputs.image_repo }}:${{ needs.compute-next-version.outputs.new_version }},${{ needs.get-image-reference.outputs.image_repo }}:${{ needs.compute-next-version.outputs.new_major_minor }}"
8284
permissions:
8385
contents: read
8486
deployments: write
8587
security-events: write
8688
packages: write
89+
90+
# Only create the git tag after the rebuilt image passes Trivy and is pushed
91+
create-tag:
92+
needs: [periodic-scan, update-image]
93+
runs-on: ubuntu-latest
94+
if: ${{ !cancelled() && needs.periodic-scan.outputs.trivy_conclusion == 'failure' && needs.update-image.result == 'success' }}
95+
steps:
96+
- name: Bump version and push tag
97+
uses: mathieudutour/github-tag-action@a22cf08638b34d5badda920f9daf6e72c477b07b # v6.2
98+
with:
99+
github_token: ${{ secrets.GITHUB_TOKEN }}
100+
permissions:
101+
contents: write
102+
103+
# If the rebuild still has vulnerabilities, open a GitHub issue for manual triage
104+
# instead of looping endlessly
105+
alert-on-failure:
106+
needs: [periodic-scan, update-image]
107+
runs-on: ubuntu-latest
108+
if: ${{ !cancelled() && needs.periodic-scan.outputs.trivy_conclusion == 'failure' && needs.update-image.result == 'failure' }}
109+
permissions:
110+
issues: write
111+
steps:
112+
- name: Check for existing open issue
113+
id: check_issue
114+
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
115+
with:
116+
script: |
117+
const issues = await github.rest.issues.listForRepo({
118+
owner: context.repo.owner,
119+
repo: context.repo.repo,
120+
state: 'open',
121+
labels: 'trivy,security',
122+
per_page: 1
123+
});
124+
return issues.data.length > 0 ? 'true' : 'false';
125+
result-encoding: string
126+
127+
- name: Create GitHub issue for unresolved vulnerabilities
128+
if: steps.check_issue.outputs.result == 'false'
129+
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
130+
with:
131+
script: |
132+
await github.rest.issues.create({
133+
owner: context.repo.owner,
134+
repo: context.repo.repo,
135+
title: 'Trivy: unresolved container vulnerabilities after rebuild',
136+
body: [
137+
'## Summary',
138+
'',
139+
'The daily Trivy periodic scan found Critical/High vulnerabilities in the latest published Docker image.',
140+
'An automated rebuild was attempted but the rebuilt image **still has vulnerabilities**,',
141+
'indicating the fix requires a manual dependency update rather than a base image refresh.',
142+
'',
143+
'## Next steps',
144+
'',
145+
'- Review findings in the [Security tab](../security/code-scanning)',
146+
'- Update the affected dependencies to a version that includes the fix',
147+
'- Or add the CVE ID(s) to a `.trivyignore` file if the risk is accepted',
148+
'',
149+
'## Details',
150+
'',
151+
`- **Workflow run:** ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
152+
`- **Triggered at:** ${new Date().toISOString()}`,
153+
].join('\n'),
154+
labels: ['trivy', 'security']
155+
});
156+

0 commit comments

Comments
 (0)