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:

  1. Aqua scanner not installed on the runner:

    • Diagnosis: Check your workflow file. If you don’t see a step that installs aquasec/aqua-scanner-action or downloads the trivy binary (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.
  2. 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.
  3. Incorrect image name or tag:

    • Diagnosis: The image_name parameter in your scan step doesn’t precisely match the image that was built and pushed. This is common if you’re using dynamic tags (like latest or commit SHAs) and they aren’t correctly propagated.
    • Fix: Ensure the image_name variable 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.
  4. Aqua credentials not configured or invalid:

    • Diagnosis: The aqua_user and aqua_key secrets 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.
  5. 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.com on port 443. 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.
  6. Incorrect severity_threshold or fail_on configuration:

    • Diagnosis: The scanner is running and finding vulnerabilities, but they are all below the configured severity_threshold or the fail_on setting 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_threshold or fail_on parameters in your aqua-scanner-action step. 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.

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:

  1. checkout@v3 fetches your repository’s code.
  2. setup-buildx-action@v2 configures Docker’s build capabilities.
  3. login-action@v2 authenticates you with Docker Hub using secrets stored in your GitHub repository.
  4. docker/build-push-action@v2 builds your Dockerfile and pushes the resulting image to Docker Hub, tagging it with the commit SHA for traceability. The id: docker_build allows us to reference outputs from this step.
  5. The first aquasec/aqua-scanner-action@v2.0.0 step (without an image_name) is crucial. When run without an image_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 provided aqua_user and aqua_key.
  6. The second aquasec/aqua-scanner-action@v2.0.0 step is where the actual scanning happens. We provide the image_name that was just pushed. The fail_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.

Want structured learning?

Take the full Aqua course →