Aqua Security’s scanner is failing to report vulnerabilities in images built and pushed within GitHub Actions.
This is happening because the GitHub Actions runner, by default, doesn’t have the Aqua scanner installed or configured to access the image registry. The scanner needs to be explicitly invoked and pointed to the image that was just built and pushed.
Here are the most common reasons and their fixes:
-
Aqua scanner not installed on the runner:
- Diagnosis: Check your workflow file. If you don’t see a step that installs
aquasec/aqua-scanner-actionor downloads thetrivybinary (Aqua’s underlying scanner), this is likely the issue. - Fix: Add a step to install the Aqua scanner action.
- name: Install Aqua Scanner uses: aquasec/aqua-scanner-action@v2.0.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} aqua_user: ${{ secrets.AQUA_USER }} aqua_key: ${{ secrets.AQUA_KEY }} # Optional: Specify a particular version if needed # version: "v2.0.0" - Why it works: This action downloads and sets up the Aqua scanner binary and its dependencies on the GitHub Actions runner, making it available for subsequent steps.
- Diagnosis: Check your workflow file. If you don’t see a step that installs
-
Scanner not invoked after image push:
- Diagnosis: Examine your workflow. You might have steps to build and push an image, but no subsequent step that runs the scanner against that specific image.
- Fix: After your image build and push steps, add a step to scan the image.
- name: Scan Image with Aqua uses: aquasec/aqua-scanner-action@v2.0.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} aqua_user: ${{ secrets.AQUA_USER }} aqua_key: ${{ secrets.AQUA_KEY }} image_name: "your-dockerhub-username/your-repo:${{ github.sha }}" # Replace with your image name # Optional: Specify severity threshold. Vulnerabilities above this will fail the build. # severity_threshold: "MEDIUM" - Why it works: This explicitly tells the installed Aqua scanner to analyze the image identified by
image_name.
-
Incorrect image name or tag:
- Diagnosis: The
image_nameparameter in your scan step doesn’t precisely match the image that was built and pushed. This is common if you’re using dynamic tags (likelatestor commit SHAs) and they aren’t correctly propagated. - Fix: Ensure the
image_namevariable in your scan step accurately reflects the image pushed in the preceding step. Use environment variables or output from previous steps if necessary.# Example if your build step outputs the image name - name: Build and Push Docker Image id: docker_build uses: docker/build-push-action@v2 with: # ... build and push config ... push: true tags: your-dockerhub-username/your-repo:${{ github.sha }} - name: Scan Image with Aqua uses: aquasec/aqua-scanner-action@v2.0.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} aqua_user: ${{ secrets.AQUA_USER }} aqua_key: ${{ secrets.AQUA_KEY }} image_name: "${{ steps.docker_build.outputs.digest }}" # Or use the tag if digest isn't available - Why it works: The scanner needs the exact identifier (tag or digest) of the image to pull and scan it. Mismatches mean it’s looking for an image that doesn’t exist or is the wrong version.
- Diagnosis: The
-
Aqua credentials not configured or invalid:
- Diagnosis: The
aqua_userandaqua_keysecrets are missing from your GitHub repository’s settings, or the provided credentials are for an account that doesn’t have the necessary permissions or is expired. - Fix: Go to your GitHub repository’s "Settings" -> "Secrets and variables" -> "Actions". Add two repository secrets:
AQUA_USER: Your Aqua Security username.AQUA_KEY: Your Aqua Security API key. Ensure these are correctly copied from your Aqua account.
- Why it works: The Aqua scanner requires authentication to communicate with the Aqua Security platform for scanning and reporting. These secrets provide that authentication.
- Diagnosis: The
-
Network issues or firewall blocking access to Aqua Security API:
- Diagnosis: If your GitHub Actions runner is on a network with strict egress rules, it might be unable to reach the Aqua Security API endpoints (e.g.,
api.cloud.aquasec.com). - Fix: Ensure that the GitHub Actions runner environment allows outbound connections to
api.cloud.aquasec.comon port443. If you are using self-hosted runners, this is a network configuration task for your infrastructure. For GitHub-hosted runners, this is less common but can occur with very restrictive network policies if you’re routing traffic through a proxy. - Why it works: The Aqua scanner, even when run locally, often needs to communicate with the Aqua backend for license checks, policy evaluation, and reporting, so network connectivity is essential.
- Diagnosis: If your GitHub Actions runner is on a network with strict egress rules, it might be unable to reach the Aqua Security API endpoints (e.g.,
-
Incorrect
severity_thresholdorfail_onconfiguration:- Diagnosis: The scanner is running and finding vulnerabilities, but they are all below the configured
severity_thresholdor thefail_onsetting is not set to trigger a failure. The action might complete successfully without reporting any issues that would fail the build. - Fix: Adjust the
severity_thresholdorfail_onparameters in youraqua-scanner-actionstep. For example, to fail on any vulnerability of "LOW" severity or higher:- name: Scan Image with Aqua uses: aquasec/aqua-scanner-action@v2.0.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} aqua_user: ${{ secrets.AQUA_USER }} aqua_key: ${{ secrets.AQUA_KEY }} image_name: "your-dockerhub-username/your-repo:${{ github.sha }}" fail_on: "low" # This will fail the action if any low, medium, high, critical vulnerabilities are found. # Alternatively, set a threshold: # severity_threshold: "MEDIUM" # This will fail if vulnerabilities of MEDIUM or HIGHER are found. - Why it works: These parameters control the exit code of the scanner action. By setting them appropriately, you ensure that the workflow fails when vulnerabilities meeting your criteria are detected, making the scanner’s output actionable.
- Diagnosis: The scanner is running and finding vulnerabilities, but they are all below the configured
After fixing these, the next error you might encounter is related to resource limits on the GitHub Actions runner, such as running out of memory or disk space during the image scanning process for very large images.
The most surprising thing about Aqua’s image scanning in GitHub Actions is that it’s not just a simple "scan this image" command; it’s a sophisticated integration that leverages the Aqua Security platform for policy enforcement, vulnerability intelligence, and compliance checks, often in ways that are not immediately obvious from the basic configuration.
Let’s look at a typical workflow. Imagine you have a microservice written in Go, and you want to ensure its container image is secure before deploying it.
Here’s a snippet of a GitHub Actions workflow that builds a Docker image, pushes it to Docker Hub, and then scans it with Aqua:
name: Build, Push, and Scan Image
on:
push:
branches: [ main ]
jobs:
build-and-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push Docker image
id: docker_build
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: your-dockerhub-username/my-go-app:${{ github.sha }}
# This will output the digest of the image, which is a reliable identifier
outputs: type=image,name=your-dockerhub-username/my-go-app:${{ github.sha }}
- name: Install Aqua Scanner
uses: aquasec/aqua-scanner-action@v2.0.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
aqua_user: ${{ secrets.AQUA_USER }}
aqua_key: ${{ secrets.AQUA_KEY }}
# Optional: Specify a particular version if needed
# version: "v2.0.0"
- name: Scan Image with Aqua
uses: aquasec/aqua-scanner-action@v2.0.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
aqua_user: ${{ secrets.AQUA_USER }}
aqua_key: ${{ secrets.AQUA_KEY }}
# Use the image name/tag that was just pushed
image_name: "your-dockerhub-username/my-go-app:${{ github.sha }}"
# Fail the build if any critical or high vulnerabilities are found
fail_on: "high"
# Optional: Set a threshold for reporting severity
# severity_threshold: "MEDIUM"
In this workflow:
checkout@v3fetches your repository’s code.setup-buildx-action@v2configures Docker’s build capabilities.login-action@v2authenticates you with Docker Hub using secrets stored in your GitHub repository.docker/build-push-action@v2builds your Dockerfile and pushes the resulting image to Docker Hub, tagging it with the commit SHA for traceability. Theid: docker_buildallows us to reference outputs from this step.- The first
aquasec/aqua-scanner-action@v2.0.0step (without animage_name) is crucial. When run without animage_name, this action downloads and installs the Aqua scanner binary and its dependencies onto the runner. It also performs initial authentication with your Aqua account using the providedaqua_userandaqua_key. - The second
aquasec/aqua-scanner-action@v2.0.0step is where the actual scanning happens. We provide theimage_namethat was just pushed. Thefail_on: "high"parameter tells the scanner to exit with a non-zero status code (thus failing the GitHub Actions job) if it detects any vulnerabilities classified as "high" or "critical".
The mental model here is that the aquasec/aqua-scanner-action acts as a wrapper. The first invocation sets up the environment and authenticates. Subsequent invocations, specifying an image_name, use that established environment to perform the scan against your container image. The scan results are then sent to your Aqua Security platform account for further analysis, reporting, and policy enforcement. You control the strictness of the scan by adjusting fail_on and severity_threshold, and you can define custom policies within the Aqua Security platform itself that will be applied during the scan.
What most people don’t realize is that the aqua_user and aqua_key aren’t just for authentication; they also tie the scan results back to your specific Aqua subscription, enabling features like license management, advanced reporting, and the application of your organization’s specific security policies defined within the Aqua console. Without these, the scanner would be operating in a limited, unauthenticated mode, likely unable to provide comprehensive results or enforce custom rules.
The next concept you’ll likely explore is integrating Aqua’s runtime security features or using Aqua to scan Kubernetes deployments directly, moving beyond just static image scanning.