# Scan Docker Images for CVEs on Every Deploy

> Scan Docker images for CVEs with Trivy after every deploy and daily: severity triage, a SHA-pinned GitHub Actions setup, and alerts for critical findings.

David Viejo · Published 2026-03-12 · Updated 2026-10-20 · 12 min read

Canonical: https://temps.sh/blog/how-to-run-vulnerability-scanner-deployed-apps

The fastest way to scan a deployed app for known vulnerabilities is to run an open-source scanner such as [Trivy](https://trivy.dev/) against your Docker image after every build, either in CI or through a platform that does it for you. Temps does the latter: it runs a pinned Trivy image (`aquasec/trivy:0.58.1`) against your Docker images immediately after each deploy, with no CI/CD configuration or external API keys.

According to Verizon's [2025 Data Breach Investigations Report](https://www.verizon.com/business/resources/reports/dbir/), exploitation of vulnerabilities as the initial access vector rose another 34% and now accounts for 20% of breaches, and only about half of vulnerable edge devices were fully patched within the year, with a median of 32 days to patch. Your deployed app — the one running right now — has attack surface you've never inspected.

This guide covers what vulnerability scanners actually check, which tools are worth your time, how to automate scanning in CI/CD, and how Temps handles the whole process without adding operational overhead.

> **TL;DR:** Most web app breaches exploit known, patchable CVEs. Trivy scans your Docker images for vulnerable OS packages and language dependencies in under 10 minutes. Temps runs Trivy automatically on every deployment and daily at midnight UTC, sends email alerts for critical and high findings, and provides a full CVE breakdown in the project dashboard. Exploitation of vulnerabilities as the initial access vector rose 34% and now accounts for 20% of breaches according to the [Verizon DBIR](https://www.verizon.com/business/resources/reports/dbir/).

---

## How Do You Run a Vulnerability Scanner on Deployed Apps?

The most effective approach is scanning your Docker images — the actual artifacts you deploy — rather than running external web probes against a live URL. Image scanning catches CVEs in OS packages (Alpine, Debian, Ubuntu) and language dependencies (npm, pip, Go modules, Rust crates) before or immediately after deployment, while the image is still fresh.

Trivy is the standard tool for this. It pulls the image layers, analyzes them against its CVE database, and returns a structured report with vulnerability IDs, affected packages, installed versions, fixed versions, severity levels, and CVSS scores — in under 10 minutes for most images.

**The three practical approaches:**

1. **CI/CD gate:** Run Trivy in your pipeline before deployment and fail the build on critical findings
2. **Post-deploy scan:** Deploy first, then scan asynchronously and alert the team if critical CVEs are found
3. **Platform-managed:** Use a deployment platform that runs scans automatically without any pipeline changes

Each approach has tradeoffs. CI gating catches issues before they reach production but adds pipeline latency. Post-deploy scanning is non-blocking but requires you to act quickly on findings. Platform-managed scanning is lowest-friction because there's nothing to configure.

---

## What Does Trivy Actually Check?

Trivy scans Docker images at the layer level and reports findings across four categories:

### OS Packages

Alpine, Debian, Ubuntu, CentOS, and other Linux distributions include hundreds of packages in a base image. Each package has a version, and each version has a known CVE status. Trivy checks every installed package against its vulnerability database (sourced from NVD, GitHub Advisory Database, and OS vendor advisories) and reports which ones have known CVEs with available fixes.

### Language Packages

Application dependencies bundled into the image — `node_modules`, Python packages, Go modules, Ruby gems, Rust dependencies — are scanned against language-specific advisory databases. A vulnerability in a transitive npm dependency three levels deep will appear in the report.

### Severity Levels

Trivy classifies each finding into one of five severity levels:

| Severity     | Meaning                                                          | Recommended action        |
| ------------ | ---------------------------------------------------------------- | ------------------------- |
| **Critical** | Trivially exploitable, severe impact (e.g., unauthenticated RCE) | Fix immediately           |
| **High**     | Exploitable with significant impact                              | Fix as soon as possible   |
| **Medium**   | Requires specific conditions or limited impact                   | Fix in next release cycle |
| **Low**      | Minimal impact or very difficult to exploit                      | Fix when convenient       |
| **Unknown**  | Insufficient data to classify                                    | Review manually           |

### What Trivy Skips

Trivy deliberately excludes compiled binary results (Go binaries, Rust binaries embedded in the image) from reports. These produce noisy findings from binaries baked into Docker images — for example, Go stdlib CVEs from a Hugo binary — that are unrelated to your project's own code. Temps uses the same filtering.

---

## How Does Platform-Level Scanning Compare to CI/CD Integration?

| Aspect               | Temps (platform-managed)                                                                | Trivy in GitHub Actions             | Snyk Container                         |
| -------------------- | --------------------------------------------------------------------------------------- | ----------------------------------- | -------------------------------------- |
| **Setup required**   | None — runs automatically                                                               | Workflow YAML + token               | Account + CLI setup                    |
| **Scan timing**      | After every deploy + daily at midnight UTC                                              | On push/PR (configurable)           | On push/PR (configurable)              |
| **Results location** | Project dashboard (same place as deploy logs)                                           | Pipeline logs / GitHub Security tab | Snyk dashboard                         |
| **Email alerts**     | Built-in for Critical/High findings                                                     | Via external notification step      | Built-in (paid plans)                  |
| **Cost**             | Free to self-host, or the server you already run it on (Temps Cloud add-on coming soon) | Free within GitHub Actions minutes  | Free tier limited; see snyk.io/pricing |
| **Scanner**          | Trivy, pinned image (`aquasec/trivy:0.58.1`)                                            | Trivy (configurable version)        | Snyk proprietary                       |
| **CVE database**     | NVD + OS vendor advisories                                                              | NVD + OS vendor advisories          | Snyk Intel (proprietary)               |

The main advantage of platform-managed scanning is that results are co-located with deployment history, so you can see exactly which commit introduced a new vulnerability without switching tools.

---

## How to Set Up Trivy in a GitHub Actions Pipeline

If you're not using Temps, here's how to add container scanning to an existing CI/CD pipeline:

### Post-Deploy Scan Workflow

```yaml
# .github/workflows/security-scan.yml
name: Post-Deploy Security Scan
on:
  workflow_run:
    workflows: ["Deploy"]
    types: [completed]

jobs:
  scan:
    runs-on: ubuntu-latest
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    steps:
      - name: Run Trivy vulnerability scanner
        # Pin to a full commit SHA, not a tag or branch (see the note below)
        uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
        with:
          image-ref: 'your-registry/your-app:latest'
          format: 'sarif'
          output: 'trivy-results.sarif'
          severity: 'CRITICAL,HIGH'
          exit-code: '1'

      - name: Upload Trivy scan results to GitHub Security tab
        uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
        if: always()
        with:
          sarif_file: 'trivy-results.sarif'
```

Setting `exit-code: '1'` causes the workflow to fail when Critical or High CVEs are found. Remove it if you want non-blocking scans that alert without failing.

**Pin actions to commit SHAs.** On 19 March 2026 an attacker with stolen credentials force-pushed 76 of 77 version tags in `aquasecurity/trivy-action` (and every tag in `setup-trivy`) to credential-stealing code, tracked as CVE-2026-33634. Any workflow that referenced a tag or `@master` that day ran it. Aqua's guidance is to pin to a full commit SHA; the SHAs above are the v0.36.0 and v4.38.2 releases as of October 2026 — verify them against each repository's releases page before you copy them, and let Dependabot or Renovate bump them.

### Scheduled Weekly Scan

```yaml
on:
  schedule:
    - cron: '0 6 * * 1'  # Every Monday at 6 AM UTC
```

### Filtering False Positives

Go binary and Rust binary results from embedded binaries in Docker images are typically false positives for your own code:

```yaml
- name: Run Trivy vulnerability scanner
  uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
  with:
    image-ref: 'your-registry/your-app:latest'
    vuln-type: 'os,library'
    skip-files: '/usr/local/bin/hugo,/usr/bin/some-go-binary'
    severity: 'CRITICAL,HIGH,MEDIUM'
```

---

## How Does Temps Handle Vulnerability Scanning?

Temps includes a built-in vulnerability scanner as part of its deployment platform. It runs Trivy from a pinned image (`aquasec/trivy:0.58.1` in the current source) as a Docker container on your Temps server.

### Automatic Scans on Every Deployment

When you push code and Temps builds and deploys your application, a vulnerability scan runs automatically as a post-deploy step — alongside screenshot capture and source map upload. No configuration required.

### Daily Scheduled Scans

A background service runs daily at midnight UTC, scanning every environment that has a current deployment. New CVEs are published constantly; yesterday's clean image can have a known vulnerability today. Daily scans catch this drift.

### Triggering a Manual Scan

```bash
# Trigger a scan via the Temps CLI
bunx @temps-sdk/cli scans trigger --project-id <id> --environment-id <env_id>

# List recent scans
bunx @temps-sdk/cli scans list --project-id <id>
```

Or via the REST API:

```bash
# Trigger a scan
curl -X POST "https://your-temps-instance.com/api/projects/{project_id}/vulnerability-scans" \
  -H "Authorization: Bearer YOUR_TOKEN"

# View latest scan results
curl "https://your-temps-instance.com/api/projects/{project_id}/vulnerability-scans/latest" \
  -H "Authorization: Bearer YOUR_TOKEN"

# View vulnerabilities for a specific scan (not nested under the project)
curl "https://your-temps-instance.com/api/vulnerability-scans/{scan_id}/vulnerabilities" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

### Scan Results

Each scan returns a structured breakdown: total vulnerability count, and per-severity counts (critical, high, medium, low, unknown). Click into any scan to see individual CVEs with:

- CVE identifier (e.g., `CVE-2024-12345`)
- Affected package name and installed version
- Fixed version (if available)
- Severity classification
- CVSS score
- References and primary advisory URL

### Email Alerts for Critical and High Findings

Temps sends email notifications automatically when a scan finds Critical or High severity vulnerabilities. The email includes the project name, a summary of critical/high/total counts, scanner type and version, branch and commit hash, and a direct link to the full vulnerability report in the dashboard.

Low and Medium findings are recorded and visible in the dashboard but do not trigger email alerts — reducing noise while ensuring high-severity issues are acted on immediately.

### What Temps Does Not Scan

Temps scans Docker image contents — OS packages and language dependencies bundled into the image. It does not perform DAST (web application scanning against a live URL), so it will not check HTTP headers, probe for exposed paths, or test API endpoints for injection vulnerabilities. Use Nuclei or OWASP ZAP for DAST alongside image scanning.

### Self-Host: No Data Leaves Your Server

On a self-hosted Temps instance, scans run entirely on your infrastructure. Trivy runs as a Docker container with the Docker socket bind-mounted read-only and all Linux capabilities dropped. (A read-only bind mount doesn't stop API calls over the socket, so the scanner image itself must be trusted — one reason it is pinned to a version rather than `latest`.) Trivy downloads its vulnerability database, but your image contents and scan results never leave your server: no scan quotas, no third-party data handling.

Temps is licensed MIT / Apache 2.0 and free to self-host. Image scanning is one layer, and the [vulnerability scanning reference](https://temps.sh/docs/security-settings#vulnerability-scanning) documents how to trigger a scan and read its results; the [security overview](https://temps.sh/security) lists the platform's other controls, and the [security hardening guide](https://temps.sh/docs/security) covers the server it runs on. For the secrets your images read at runtime, see [how to encrypt environment variables at rest](https://temps.sh/blog/how-to-encrypt-environment-variables-at-rest).

---

## Which Open-Source Web Scanning Tools Are Worth Using?

Image scanning and web application scanning are complementary. Image scanning catches CVEs in dependencies before attackers can exploit them. Web application scanning tests your live app from the outside for misconfigurations and injection points.

### Trivy (Image Scanning)

[Trivy](https://github.com/aquasecurity/trivy) is the standard for container image scanning. It scans OS packages, language packages, infrastructure-as-code files, and Kubernetes manifests. Fast, low resource usage, and accurate.

**Best for:** Docker image CVE detection in CI/CD and on every deployment.

### Nuclei (Web App Scanning)

[Nuclei](https://github.com/projectdiscovery/nuclei) from ProjectDiscovery runs community-maintained YAML templates — over 9,000 of them — that check for specific, known issues in live HTTP endpoints.

**Best for:** Fast, repeatable checks in CI/CD pipelines immediately after deployment.

### OWASP ZAP (Dynamic App Scanning)

[OWASP ZAP](https://github.com/zaproxy/zaproxy) is the most comprehensive open-source DAST tool. It runs as a proxy between your browser and the target app, intercepting and analyzing every request. Resource-heavy — plan for 1–2 GB RAM — but thorough for staging environment scans.

**Best for:** Deep, thorough scans of staging environments before production deployment.

### Mozilla Observatory (Header Check)

Not a scanner you install — it's a free web service that grades your site's security headers and TLS configuration. Focused entirely on HTTP response headers with letter grades and specific fix recommendations.

**Best for:** Quick header audit on any public URL.

### Scanner Comparison

| Tool                | Type             | GitHub Stars      | Resource Use  | CI/CD Ready    |
| ------------------- | ---------------- | ----------------- | ------------- | -------------- |
| Trivy               | Image / IaC      | 25,000+           | Low (\~150MB) | Excellent      |
| Nuclei              | DAST (templates) | 22,000+           | Low (\~100MB) | Excellent      |
| OWASP ZAP           | DAST (full)      | 13,000+           | High (1–2GB)  | Yes (headless) |
| Mozilla Observatory | Header check     | N/A (web service) | None          | API available  |

---

## How Do You Integrate Scanning into Your Deploy Pipeline?

### The Recommended Stack

1. **Trivy in CI** — scan your Docker image before pushing to registry, fail on Critical findings
2. **Nuclei post-deploy** — run template checks against the live URL after deployment
3. **Scheduled weekly scans** — catch newly disclosed CVEs in your deployed images

### Alert on Regression, Not Every Finding

The critical pattern: track your security baseline. If Monday's scan found 3 issues and Tuesday's found 5, something regressed. Store results, diff them, and alert only on new findings. Alerting on every finding on every scan causes teams to ignore the scanner after the first week.

### Preview Environment Scanning

If you deploy preview environments for pull requests, scan those too. Catching a security regression before it hits production is far cheaper than patching it after. Run a lightweight Nuclei template check — headers and exposed paths — on every preview deployment. Save the full image scan for the main branch.

---

## Frequently Asked Questions

### How often should you run vulnerability scans on production apps?

Run image scans after every deployment and at least daily on a schedule. New CVEs are published constantly; a clean image today can have a known exploit tomorrow. Temps runs scans daily at midnight UTC automatically. According to Qualys, exploitable vulnerabilities remain [unpatched for an average of 30.6 days](https://www.qualys.com/research/) — daily scanning shortens that window significantly.

### Do vulnerability scanners cause downtime or break production?

Image scanning (Trivy) is entirely offline — it analyzes image layers without sending any traffic to your running application, so there is zero production impact. DAST tools like OWASP ZAP in active scan mode can cause issues by sending malicious payloads to form inputs and API endpoints. Run active DAST scans against staging environments, not production.

### Are free scanners good enough or do you need paid tools?

Free tools cover the essentials well. Trivy is used by major cloud providers and security teams worldwide. Paid tools like Snyk Container and Qualys Web Application Scanning add compliance reporting, SLA-backed support, and proprietary intelligence. For most teams, Trivy plus scheduled automation provides solid baseline coverage at zero cost.

### What's the difference between SAST, DAST, and SCA?

SAST (Static Application Security Testing) analyzes source code before deployment. DAST (Dynamic Application Security Testing) tests running applications — tools like Nuclei and ZAP. SCA (Software Composition Analysis) checks your dependencies for known CVEs — Trivy and Snyk do this. For deployed apps, SCA via image scanning gives you the most immediate value because it tests what an attacker would actually exploit.

### Does Temps scan automatically or do I need to configure it?

Temps scans automatically — there is nothing to configure. Every deployment triggers a post-deploy Trivy scan. A background service also runs daily at midnight UTC against all deployed environments. Manual scans can be triggered from the dashboard or via the CLI and REST API. Email alerts are sent automatically for Critical and High findings.

---

## Start Scanning Before Attackers Do

The gap between "deployed" and "secure" is where breaches happen: exploited vulnerabilities were the initial access vector in 20% of breaches in the [2025 Verizon DBIR](https://www.verizon.com/business/resources/reports/dbir/).

The minimal viable setup: add Trivy to your CI pipeline, fail on Critical findings, and run a weekly scheduled scan. That alone closes the window on the most commonly exploited CVEs.

If you want scanning built into your deployment workflow — running automatically on every push, reporting in the same dashboard as your deploy logs, with email alerts for high-severity findings — Temps includes it out of the box, free to self-host (MIT / Apache 2.0 license). Temps Cloud, a hosted control plane for your own servers, is coming soon from $29/month.

---

Source: https://temps.sh/blog/how-to-run-vulnerability-scanner-deployed-apps · Index of all pages: https://temps.sh/llms.txt
