Skip to content

Commit 3f5d0f3

Browse files
feat: upgrade AWS SDK and switch to AWS native basic scanning
Migrate from deprecated Clair-based ECR scanning to AWS native basic scanning, which became the default after Clair deprecation on Feb 2, 2026. Core changes: - Upgrade AWS SDK Go v2 (v1.16.7 -> v1.41.1, ECR service v1.17.8 -> v1.55.1) - Upgrade Go from 1.14 to 1.24 - Add retry logic for ScanNotFoundException to handle scan initiation delay with AWS native scanning (up to 5 min with 15s intervals) - Add pagination for DescribeImageScanFindings to collect all findings - Handle both Clair UnsupportedImageError and AWS native ScanNotFoundException for unscannable images (e.g. scratch) Dependency upgrades (cascading from Go/SDK bump): - Docker client library v20.10.17 -> v28.5.2 (new type import paths) - distribution/reference extracted to github.com/distribution/reference - urfave/cli v2.10.3 -> v2.27.7 - tablewriter v0.0.5 -> v1.1.3 (new API: Header, Append, Render) CI and tooling: - GitHub Actions: checkout v4, setup-go v5, goreleaser v6, golangci-lint v6, codeql v3 - golangci-lint v1.46.2 -> v2.9.0, fix errcheck findings - goreleaser --rm-dist -> --clean (renamed flag) - Workflows trigger on both master and main branches Test suite: - Replace deprecated resin/scratch with locally built scratch image - Switch from old Alpine to python:3.13 (Debian-based) for CVE tests - Fix negative tests to properly exit 1 on unexpected pass Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 7e9fd2a commit 3f5d0f3

File tree

11 files changed

+353
-230
lines changed

11 files changed

+353
-230
lines changed

.github/workflows/ci.yml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ name: CI
33
on:
44
push:
55
tags: [ v* ]
6-
branches: [ master ]
6+
branches: [ master, main ]
77
pull_request:
8-
branches: [ master ]
8+
branches: [ master, main ]
99

1010
jobs:
1111

@@ -14,37 +14,37 @@ jobs:
1414
runs-on: ubuntu-latest
1515
steps:
1616

17-
- name: Set up Go 1.x
18-
uses: actions/setup-go@v3
17+
- name: Set up Go
18+
uses: actions/setup-go@v5
1919
with:
20-
go-version: ^1.13
20+
go-version: '1.24'
2121
id: go
2222

2323
- name: Check out code into the Go module directory
24-
uses: actions/checkout@v3
24+
uses: actions/checkout@v4
2525
with:
2626
fetch-depth: 0
2727

2828
- name: golangci-lint
29-
uses: golangci/golangci-lint-action@v3.2.0
29+
uses: golangci/golangci-lint-action@v6
3030
with:
31-
version: v1.48
31+
version: latest
3232

3333
- name: Prepare a snapshot release
3434
if: "!startsWith(github.ref, 'refs/tags/v')"
35-
uses: goreleaser/goreleaser-action@v3
35+
uses: goreleaser/goreleaser-action@v6
3636
with:
3737
version: latest
38-
args: release --rm-dist --snapshot
38+
args: release --clean --snapshot
3939
env:
4040
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4141

4242
- name: Release a new version
4343
if: startsWith(github.ref, 'refs/tags/v')
44-
uses: goreleaser/goreleaser-action@v3
44+
uses: goreleaser/goreleaser-action@v6
4545
with:
4646
version: latest
47-
args: release --rm-dist
47+
args: release --clean
4848
env:
4949
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5050

.github/workflows/codeql-analysis.yml

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@ name: "CodeQL"
1313

1414
on:
1515
push:
16-
branches: [ master ]
16+
branches: [ master, main ]
1717
pull_request:
18-
# The branches below must be a subset of the branches above
19-
branches: [ master ]
18+
branches: [ master, main ]
2019
schedule:
2120
- cron: '26 4 * * 4'
2221

@@ -33,38 +32,26 @@ jobs:
3332
fail-fast: false
3433
matrix:
3534
language: [ 'go' ]
36-
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37-
# Learn more about CodeQL language support at https://git.io/codeql-language-support
3835

3936
steps:
37+
- name: Set up Go
38+
uses: actions/setup-go@v5
39+
with:
40+
go-version: '1.24'
41+
4042
- name: Checkout repository
41-
uses: actions/checkout@v3
43+
uses: actions/checkout@v4
4244

4345
# Initializes the CodeQL tools for scanning.
4446
- name: Initialize CodeQL
45-
uses: github/codeql-action/init@v2
47+
uses: github/codeql-action/init@v3
4648
with:
4749
languages: ${{ matrix.language }}
48-
# If you wish to specify custom queries, you can do so here or in a config file.
49-
# By default, queries listed here will override any specified in a config file.
50-
# Prefix the list here with "+" to use these queries and those in the config file.
51-
# queries: ./path/to/local/query, your-org/your-repo/queries@main
5250

5351
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
5452
# If this step fails, then you should remove it and run the build manually (see below)
5553
- name: Autobuild
56-
uses: github/codeql-action/autobuild@v2
57-
58-
# ℹ️ Command-line programs to run using the OS shell.
59-
# 📚 https://git.io/JvXDl
60-
61-
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
62-
# and modify them (or add more) to build your code if your project
63-
# uses a compiled language
64-
65-
#- run: |
66-
# make bootstrap
67-
# make release
54+
uses: github/codeql-action/autobuild@v3
6855

6956
- name: Perform CodeQL Analysis
70-
uses: github/codeql-action/analyze@v2
57+
uses: github/codeql-action/analyze@v3

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
### v0.7.0
2+
3+
* Switch to AWS native basic scanning (Clair was deprecated on Feb 2, 2026)
4+
* Add retry logic for scan initiation delay with AWS native scanning (handles ScanNotFoundException)
5+
* Add pagination for DescribeImageScanFindings to collect all findings across multiple pages
6+
* Upgrade AWS SDK Go v2 (v1.16.7 -> v1.41.1, ECR service v1.17.8 -> v1.55.1)
7+
* Upgrade Go from 1.14 to 1.24
8+
* Upgrade Docker client library (v20.10.17 -> v28.5.2)
9+
* Upgrade distribution/reference, urfave/cli (v2.10.3 -> v2.27.7), tablewriter (v0.0.5 -> v1.1.3)
10+
* Update CI: GitHub Actions (checkout v4, setup-go v5, goreleaser v6, golangci-lint v6, codeql v3)
11+
* Update golangci-lint (v1.46.2 -> v2.9.0) and fix errcheck findings
12+
* Update test suite to use python:3.13 (Debian-based) instead of old Alpine for CVE tests
13+
* Replace deprecated resin/scratch with locally built scratch image in tests
14+
115
### v0.6.0
216

317
**IMPORTANT: This release includes breaking changes!** Please check the migration guide: [MIGRATION-v0.6.md](./MIGRATION-v0.6.md)

README.md

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
# aws-ecr-client
44

5-
AWS ECR client for automated push to ECR and handling of vulnerability scanning results
5+
AWS ECR client for automated push to ECR and handling of vulnerability scanning results.
6+
7+
Supports **AWS native basic scanning** (the default since Feb 2, 2026, replacing the deprecated Clair-based scanning).
68

79
Features:
810
* Automatically gets authorization token for ECR repo
@@ -11,6 +13,8 @@ Features:
1113
* Can ignore all CVE's of certain severity level (not recommended but useful when you have to deal with docker image over which you have no control)
1214
* Can ignore individual CVE's (not recommended but useful when you might really really need to unblock that pipeline)
1315
* Can output CVE scan report in Junit format so you can feed to to Jenkins or some other system for visibility
16+
* Handles scan initiation delays with AWS native scanning (automatic retries)
17+
* Paginates through all scan findings for complete results
1418

1519
See examples below for more details
1620

@@ -19,7 +23,7 @@ See examples below for more details
1923
```
2024
NAME:
2125
aws-ecr-client-golang - AWS ECR client to automated push to ECR and handling of vulnerability.
22-
Version v0.6.0
26+
Version v0.7.0
2327
2428
USAGE:
2529
aws-ecr-client-golang [global options] command [command options] [arguments...]
@@ -49,19 +53,19 @@ Download official builds from [here](https://releases.fivexl.io/aws-ecr-client-g
4953
### Push of the real tag is stopped because of CVE
5054

5155
```
52-
$ aws-ecr-client-golang --images XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/alpine:3.12.12
53-
aws-ecr-client, version v0.6.0
56+
$ aws-ecr-client-golang --images XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/myimage:latest
57+
aws-ecr-client, version v0.7.0
5458
Note: Stage repo is not specified - will use the the repo of the first given image as a scanning silo
55-
Push image to the scanning repo as XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/alpine:ecs-client-scan-1662393883
56-
Checking scan result for the image XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/alpine:ecs-client-scan-1662393883
59+
Push image to the scanning repo as XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/myimage:ecs-client-scan-1770898008
60+
Checking scan result for the image XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/myimage:ecs-client-scan-1770898008
5761
5862
Image scan status: COMPLETE
5963
6064
Found the following CVEs
6165
+----------------+-----------+----------+-------------+---------------------------------------------------------------+
6266
| CVE | SEVERITY | IGNORED? | DESCRIPTION | URI |
6367
+----------------+-----------+----------+-------------+---------------------------------------------------------------+
64-
| CVE-2022-37434 | UNDEFINED | No | | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-37434 |
68+
| CVE-2024-58015 | HIGH | No | | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-58015 |
6569
+----------------+-----------+----------+-------------+---------------------------------------------------------------+
6670
6771
Ignored CVE severity levels:
@@ -74,27 +78,26 @@ Error: there are CVEs found! Please, fix them first. Will not proceed with pushi
7478
### Push of the real tag with ignored CVE
7579

7680
```
77-
$ AWS_ECR_CLIENT_IGNORE_CVE=CVE-2022-37434 aws-ecr-client-golang --images XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/alpine:3.12.12
78-
aws-ecr-client, version v0.6.0
81+
$ AWS_ECR_CLIENT_IGNORE_CVE=CVE-2024-58015 aws-ecr-client-golang --images XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/myimage:latest
82+
aws-ecr-client, version v0.7.0
7983
Note: Stage repo is not specified - will use the the repo of the first given image as a scanning silo
80-
Push image to the scanning repo as XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/alpine:ecs-client-scan-1662393948
81-
Checking scan result for the image XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/alpine:ecs-client-scan-1662393948
84+
Push image to the scanning repo as XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/myimage:ecs-client-scan-1770898062
85+
Checking scan result for the image XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/myimage:ecs-client-scan-1770898062
8286
8387
Image scan status: COMPLETE
8488
8589
Found the following CVEs
8690
+----------------+-----------+------------------------------+-------------+---------------------------------------------------------------+
8791
| CVE | SEVERITY | IGNORED? | DESCRIPTION | URI |
8892
+----------------+-----------+------------------------------+-------------+---------------------------------------------------------------+
89-
| CVE-2022-37434 | UNDEFINED | Yes (Ignored individual CVE) | | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-37434 |
93+
| CVE-2024-58015 | HIGH | Yes (Ignored individual CVE) | | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-58015 |
9094
+----------------+-----------+------------------------------+-------------+---------------------------------------------------------------+
9195
9296
Ignored CVE severity levels:
93-
Ignored CVE's: CVE-2022-37434
97+
Ignored CVE's: CVE-2024-58015
9498
9599
Final scan result: Passed
96-
Pushing: XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/alpine:3.12.12
97-
Done
100+
Pushing: XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/myimage:latest
98101
```
99102

100103
### GitLab Workflow Example
@@ -108,8 +111,8 @@ Done
108111
APP: dts_all_batch
109112
PATH_DOCKERFILE: /
110113
DOCKER_TLS_CERTDIR: ""
111-
ECR_CLIENT_VERSION: 0.6.0
112-
AWS_ECR_CLIENT_IGNORE_CVE: CVE-2022-37434
114+
ECR_CLIENT_VERSION: 0.7.0
115+
AWS_ECR_CLIENT_IGNORE_CVE: CVE-2024-58015
113116
AWS_ECR_CLIENT_IGNORE_CVE_LEVEL: LOW INFORMATIONAL UNDEFINED
114117
services:
115118
- docker:dind
@@ -138,7 +141,7 @@ Done
138141
<testsuites>
139142
<testsuite tests="6" failures="1" time="6.000" name="Container Image CVE scan">
140143
<properties>
141-
<property name="go.version" value="go1.14.4"></property>
144+
<property name="go.version" value="go1.24.0"></property>
142145
<property name="coverage.statements.pct" value="100"></property>
143146
</properties>
144147
<testcase classname="Container Image CVE scan" name="CRITICAL" time="1.000"></testcase>
@@ -159,20 +162,18 @@ The client handles unsupported images error (for example scratch) as another fin
159162
ignoring `ECR_ERROR_UNSUPPORTED_IMAGE`
160163

161164
```
162-
aws-ecr-client, version v0.6.0
165+
aws-ecr-client, version v0.7.0
163166
Note: Stage repo is not specified - will use the the repo of the first given image as a scanning silo
164-
Push image to the scanning repo as XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/alpine:ecs-client-scan-1662392380
165-
Checking scan result for the image XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/alpine:ecs-client-scan-1662392380
167+
Push image to the scanning repo as XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/alpine:ecs-client-scan-1770897999
168+
Checking scan result for the image XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/alpine:ecs-client-scan-1770897999
166169
167170
Found the following CVEs
168-
+-----------------------------+---------------+------------------------------+--------------------------------+-----+
169-
| CVE | SEVERITY | IGNORED? | DESCRIPTION | URI |
170-
+-----------------------------+---------------+------------------------------+--------------------------------+-----+
171-
| ECR_ERROR_UNSUPPORTED_IMAGE | INFORMATIONAL | Yes (Ignored individual CVE) | UnsupportedImageError: The | |
172-
| | | | operating system and/or | |
173-
| | | | package manager are not | |
174-
| | | | supported. | |
175-
+-----------------------------+---------------+------------------------------+--------------------------------+-----+
171+
+-----------------------------+---------------+------------------------------+-----------------------------------------------------------+-----+
172+
| CVE | SEVERITY | IGNORED? | DESCRIPTION | URI |
173+
+-----------------------------+---------------+------------------------------+-----------------------------------------------------------+-----+
174+
| ECR_ERROR_UNSUPPORTED_IMAGE | INFORMATIONAL | Yes (Ignored individual CVE) | UnsupportedImageError: The operating system and/or | |
175+
| | | | package manager are not supported. | |
176+
+-----------------------------+---------------+------------------------------+-----------------------------------------------------------+-----+
176177
177178
Ignored CVE severity levels:
178179
Ignored CVE's: ECR_ERROR_UNSUPPORTED_IMAGE

docker.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import (
2626
"io"
2727

2828
dockerTypes "github.com/docker/docker/api/types"
29+
dockerImageTypes "github.com/docker/docker/api/types/image"
30+
dockerRegistry "github.com/docker/docker/api/types/registry"
2931
dockerClient "github.com/docker/docker/client"
3032
"github.com/docker/docker/pkg/jsonmessage"
3133
)
@@ -39,17 +41,17 @@ func getDockerClient() (*dockerClient.Client, error) {
3941
return dockerClient.NewClientWithOpts(dockerClient.FromEnv, dockerClient.WithAPIVersionNegotiation())
4042
}
4143

42-
func imagePush(client *dockerClient.Client, authConfig dockerTypes.AuthConfig, imageRef string) (ImageId, error) {
44+
func imagePush(client *dockerClient.Client, authConfig dockerRegistry.AuthConfig, imageRef string) (ImageId, error) {
4345

4446
authConfigBytes, _ := json.Marshal(authConfig)
4547
authConfigEncoded := base64.URLEncoding.EncodeToString(authConfigBytes)
4648

47-
opts := dockerTypes.ImagePushOptions{RegistryAuth: authConfigEncoded}
49+
opts := dockerImageTypes.PushOptions{RegistryAuth: authConfigEncoded}
4850
rd, err := client.ImagePush(context.Background(), imageRef, opts)
4951
if err != nil {
5052
return ImageId{}, err
5153
}
52-
defer rd.Close()
54+
defer func() { _ = rd.Close() }()
5355

5456
buf := new(bytes.Buffer)
5557
_, err = buf.ReadFrom(rd)

0 commit comments

Comments
 (0)