Skip to content

Commit 3a2957a

Browse files
authored
Chore: [AEA-0000] - another update to trivyignore (#23)
## Summary - Routine Change ### Details - another update to trivyignore
1 parent 228a6e2 commit 3a2957a

File tree

3 files changed

+206
-0
lines changed

3 files changed

+206
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ You can run it manually using the following. Using the `dry-run` flag just shows
303303

304304
```
305305
make github-login
306+
# or gh auth login --scopes read:packages,delete:packages if you want to be able to delete images
306307
bash .github/scripts/delete_unused_images.sh --delete-pr --dry-run
307308
bash .github/scripts/delete_unused_images.sh --delete-ci --dry-run
308309
bash .github/scripts/delete_unused_images.sh --delete-pr --delete-ci
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Script to interactively review and delete old container package versions from GitHub Packages.
5+
# By default, it will review all container packages based on the folder structure in src/.
6+
# You can specify a single container to review with --container <name>.
7+
# Use --dry-run to see what would be deleted without actually performing deletions.
8+
# To use it, you must have authenticated with github using this command
9+
# gh auth login --scopes read:packages,delete:packages
10+
#
11+
12+
DRY_RUN=false
13+
TARGET_CONTAINER=""
14+
15+
while [[ $# -gt 0 ]]; do
16+
case "$1" in
17+
--dry-run|-n)
18+
DRY_RUN=true
19+
shift
20+
;;
21+
--container)
22+
if [[ $# -lt 2 || -z "$2" ]]; then
23+
echo "--container requires a value" >&2
24+
echo "Usage: $0 [--dry-run] [--container <name>]" >&2
25+
exit 1
26+
fi
27+
TARGET_CONTAINER="$2"
28+
shift 2
29+
;;
30+
--help|-h)
31+
echo "Usage: $0 [--dry-run] [--container <name>]"
32+
echo "Interactively review every container package version and delete selected versions."
33+
exit 0
34+
;;
35+
*)
36+
echo "Unknown option: $1" >&2
37+
echo "Usage: $0 [--dry-run] [--container <name>]" >&2
38+
exit 1
39+
;;
40+
esac
41+
done
42+
43+
if ! command -v gh >/dev/null 2>&1; then
44+
echo "gh CLI is required" >&2
45+
exit 1
46+
fi
47+
48+
if ! command -v jq >/dev/null 2>&1; then
49+
echo "jq is required" >&2
50+
exit 1
51+
fi
52+
53+
get_container_package_name() {
54+
local container_name=$1
55+
56+
if [[ -z "${container_name}" ]]; then
57+
echo "Container name is required" >&2
58+
return 1
59+
fi
60+
61+
printf 'eps-devcontainers/%s' "${container_name}" | jq -sRr @uri
62+
}
63+
64+
get_container_versions_json() {
65+
local container_name=$1
66+
local package_name
67+
68+
package_name=$(get_container_package_name "${container_name}")
69+
70+
gh api \
71+
-H "Accept: application/vnd.github+json" \
72+
"/orgs/nhsdigital/packages/container/${package_name}/versions" \
73+
--paginate
74+
}
75+
76+
confirm_delete() {
77+
local prompt=$1
78+
local reply
79+
80+
if [[ -r /dev/tty ]]; then
81+
read -r -p "${prompt} [y/N]: " reply < /dev/tty
82+
else
83+
echo "No interactive terminal available; defaulting to 'No'."
84+
return 1
85+
fi
86+
[[ "${reply}" == "y" || "${reply}" == "Y" ]]
87+
}
88+
89+
review_and_delete_container_versions() {
90+
local container_name=$1
91+
local package_name
92+
local versions_json
93+
local version_count
94+
95+
package_name=$(get_container_package_name "${container_name}")
96+
versions_json=$(get_container_versions_json "${container_name}")
97+
version_count=$(jq 'length' <<<"${versions_json}")
98+
99+
echo ""
100+
echo "=== Container: ${container_name} (${version_count} versions) ==="
101+
102+
if [[ "${version_count}" -eq 0 ]]; then
103+
echo "No versions found, skipping."
104+
return 0
105+
fi
106+
107+
while IFS= read -r version; do
108+
local version_id
109+
local created_at
110+
local updated_at
111+
local tags
112+
local is_untagged
113+
local has_sha256_tag
114+
local keep_without_prompt
115+
116+
version_id=$(jq -r '.id' <<<"${version}")
117+
created_at=$(jq -r '.created_at // "unknown"' <<<"${version}")
118+
updated_at=$(jq -r '.updated_at // "unknown"' <<<"${version}")
119+
tags=$(jq -r '(.metadata.container.tags // []) | if length == 0 then "<untagged>" else join(", ") end' <<<"${version}")
120+
is_untagged=$(jq -r '((.metadata.container.tags // []) | length) == 0' <<<"${version}")
121+
has_sha256_tag=$(jq -r 'any((.metadata.container.tags // [])[]?; test("^sha256-.+"))' <<<"${version}")
122+
keep_without_prompt=$(jq -r '
123+
any((.metadata.container.tags // [])[]?;
124+
test("^githubactions-ci-.+") or
125+
test("^ci-.+") or
126+
test("^githubactions-latest$") or
127+
test("^latest$") or
128+
test("^githubactions-v.+") or
129+
test("^v.+")
130+
)
131+
' <<<"${version}")
132+
133+
echo ""
134+
echo "Container: ${container_name}"
135+
echo "Version ID: ${version_id}"
136+
echo "Created: ${created_at}"
137+
echo "Updated: ${updated_at}"
138+
echo "Tags: ${tags}"
139+
140+
if [[ "${is_untagged}" == "true" ]]; then
141+
if [[ "${DRY_RUN}" == "true" ]]; then
142+
echo "[DRY RUN] Would auto-delete untagged version ID ${version_id} from ${container_name}."
143+
else
144+
echo "Auto-deleting untagged version ID ${version_id} from ${container_name}..."
145+
gh api \
146+
-H "Accept: application/vnd.github+json" \
147+
-X DELETE \
148+
"/orgs/nhsdigital/packages/container/${package_name}/versions/${version_id}"
149+
fi
150+
elif [[ "${has_sha256_tag}" == "true" ]]; then
151+
if [[ "${DRY_RUN}" == "true" ]]; then
152+
echo "[DRY RUN] Would auto-delete sha256-tagged version ID ${version_id} from ${container_name}."
153+
else
154+
echo "Auto-deleting sha256-tagged version ID ${version_id} from ${container_name}..."
155+
gh api \
156+
-H "Accept: application/vnd.github+json" \
157+
-X DELETE \
158+
"/orgs/nhsdigital/packages/container/${package_name}/versions/${version_id}"
159+
fi
160+
elif [[ "${keep_without_prompt}" == "true" ]]; then
161+
echo "Keeping protected version ID ${version_id} (matching keep-tag rule)."
162+
elif confirm_delete "Delete this version?"; then
163+
if [[ "${DRY_RUN}" == "true" ]]; then
164+
echo "[DRY RUN] Would delete version ID ${version_id} from ${container_name}."
165+
else
166+
echo "Deleting version ID ${version_id} from ${container_name}..."
167+
gh api \
168+
-H "Accept: application/vnd.github+json" \
169+
-X DELETE \
170+
"/orgs/nhsdigital/packages/container/${package_name}/versions/${version_id}"
171+
fi
172+
else
173+
echo "Skipping version ID ${version_id}."
174+
fi
175+
done < <(jq -c '.[]' <<<"${versions_json}")
176+
}
177+
178+
base_node_folders=$(find src/base_node -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | jq -R -s -c 'split("\n")[:-1]')
179+
language_folders=$(find src/languages -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | jq -R -s -c 'split("\n")[:-1]')
180+
project_folders=$(find src/projects -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | jq -R -s -c 'split("\n")[:-1]')
181+
182+
if [[ -n "${TARGET_CONTAINER}" ]]; then
183+
review_and_delete_container_versions "${TARGET_CONTAINER}"
184+
exit 0
185+
fi
186+
187+
for container_name in $(jq -r '.[]' <<<"${project_folders}"); do
188+
review_and_delete_container_versions "${container_name}"
189+
done
190+
191+
for container_name in $(jq -r '.[]' <<<"${base_node_folders}"); do
192+
review_and_delete_container_versions "${container_name}"
193+
done
194+
195+
for container_name in $(jq -r '.[]' <<<"${language_folders}"); do
196+
review_and_delete_container_versions "${container_name}"
197+
done
198+
199+
review_and_delete_container_versions "base"

src/common_node_24/.trivyignore.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,9 @@ vulnerabilities:
3535
purls:
3636
- "pkg:npm/tar@7.5.1"
3737
expired_at: 2026-08-18
38+
- id: CVE-2026-26996
39+
statement: "minimatch has a ReDoS via repeated wildcards with non-matching literal in pattern"
40+
purls:
41+
- "pkg:npm/minimatch@10.0.3"
42+
- "pkg:npm/minimatch@9.0.5"
43+
expired_at: 2026-08-19

0 commit comments

Comments
 (0)