Secure Your Go Projects in 5 Minutes with Trivy — Full Walkthrough A security researcher warns that AI-generated Go code often pulls outdated, vulnerable dependencies from training data, exposing projects to real CVEs. The fix is Trivy, an open-source scanner that identifies problematic lines in go.mod and can be integrated into CI to block merges on critical vulnerabilities. The article provides a 5-minute walkthrough for installing Trivy, scanning a Go project, and automating the check in GitHub Actions. I want to start with a confession about the story I almost told you. I was about to open this article with a specific anecdote: a Cursor-generated PR, a 400-line diff, a security researcher DM’ing me three days later about an unauthenticated admin endpoint exposed by github.com/gorilla/handlers@v1.5.1. I had the CVE number. I had the timeline. I had the dollar amount. Then I went and checked the CVE database. The specific CVE I was about to cite doesn’t exist. The version string I picked is real, but the vulnerability I attached to it is fabricated. The story is a composite — a plausible-sounding illustration of a real problem, not a real incident. I almost shipped that to you. I almost hit publish. Here’s why that matters: the threat model is real, even if the anecdote isn’t. When an LLM writes a Go backend, it pulls the most commonly repeated version strings from its training data. That data lags by a year or two. The model picks gorilla/handlers@v1.5.1 because that's the version it saw most often in 2023, not because it checked whether that version is safe in 2026. The result is a dependency tree full of outdated packages, some of which have known CVEs, some of which have been abandoned entirely. This happens constantly in production environments. The specific CVE and SSRF claims in my made-up story are invented. The pattern — AI pulling an outdated, vulnerable package version that exposes an enterprise endpoint — is not. I tell you this because the fix for the made-up story is the same as the fix for the real pattern. It’s a single open-source binary called Trivy , run against your repo, that tells you exactly which line of go.mod is the problem. I had heard of Trivy. I had not used it. That was the mistake. This article is the 5-minute version of what I wish someone had handed me on day one. No 200-line config files. No YAML. No “in this tutorial we will.” Just the install command, the scan command, the fix, and the CI hook so it never happens again. By the end, you’ll have a Go project that scans itself on every pull request and blocks the merge if a critical CVE shows up. The whole thing fits in one shell script and one GitHub Actions file. Two years ago, you wrote your own code. You knew every dependency because you typed go get yourself. You read the README. You skimmed the source. The blast radius of a mistake was the code you could see. That era is over. Today, a typical Go service has 60–80% of its code generated by an LLM. Copilot suggests the imports. Cursor writes the handler. Claude writes the test. The dependency tree is no longer something you curated — it’s something an AI assembled from a prompt you wrote at 2 a.m. This is not a complaint. AI-generated code is faster, cheaper, and often better than what I would have written. But it has one property that changes the security calculus: you didn’t choose the dependencies, the model did. When an LLM writes import "github.com/old-vendor/logger", it does so because that library was common in its training data. It does not check whether that library has been deprecated, abandoned, or has 14 unpatched CVEs. It does not check whether the maintainer walked away in 2023. It just writes the import, because that's what the pattern looked like. This is why a scanner is no longer optional. In the era of AI-generated code, the scanner is the only thing standing between your repo and a CVE you didn’t write, didn’t review, and can’t recognize by reading the code. Trivy is the scanner I trust for this. Here’s why. There are four reasons I think Trivy is the right default for Go security scanning right now. I’ll defend each in one sentence, then we’ll move on to the code. If you’re a Go developer reading this in 2026, the bar to ship a secure service is shockingly low. The demand curve for “I scanned my repo before pushing” is vertical, and almost nobody is doing it. This is the gap. Before we run anything, here’s the entire shape of Trivy, expressed as three commands. We’re going to teach this contract before we use it, because once you see it, you can scan anything you can imagine. trivy fs . scan a local foldertrivy image myapp scan a Docker imagetrivy repo myorg/myrepo scan a remote repo Three verbs. That’s the whole abstraction. Let me explain what each one returns, because the output is the only thing that matters. trivy fs — scans your filesystem. It reads go.mod, walks your go.sum, and reports every CVE in your dependency tree. This is the one you'll run 90% of the time. Run it on every AI-generated PR before you merge. trivy image — scans a Docker image. It unpacks the layers, reads the binaries inside, and reports CVEs in both the OS packages and the Go binary itself. Use this before pushing to a registry. AI-generated Dockerfiles are especially prone to using outdated base images. trivy repo — scans a remote Git repository. Useful for auditing third-party code before you depend on it. If your AI assistant suggests a library, scan the repo before you import it. For this article, we’re going to focus on trivy fs. I’m going to break this into four small steps instead of one giant code block. Each step is something you can run, see the output of, and understand before moving on. macOS / Linuxbrew install trivy That’s the install. If you’re on Windows or you don’t use Homebrew, the binary is a single download from the GitHub releases page https://github.com/aquasecurity/trivy/releases . Drop it in your $PATH and you're done. From your Go repo root: trivy fs . What you’ll see is a table that looks like this: go.mod gomod ==================Total: 2 HIGH: 1, CRITICAL: 1 ┌─────────────────────────────────┬──────────────┬──────────┐│ LIBRARY │ VULNERABILITY│ SEVERITY │├─────────────────────────────────┼──────────────┼──────────┤│ github.com/gorilla/handlers │ CVE-2024-... │ CRITICAL ││ github.com/golang-jwt/jwt │ CVE-2024-... │ HIGH │└─────────────────────────────────┴──────────────┴──────────┘ No config files. No learning curve. The scanner reads your go.mod, walks the graph, and tells you what's broken. This is the part that catches the CVE your AI assistant didn't know about. Open your go.mod, find the bad version, bump it: go get github.com/gorilla/handlers@v1.5.2go mod tidy Re-run the scan: trivy fs . If the bump isn’t ready, you have two safe options. Pin to a known-good pseudo-version, or add a require override in go.mod that forces the patched version. Both are documented in the Trivy Go docs https://trivy.dev/docs/latest/coverage/language/golang/ . Add a GitHub Action so every PR gets scanned: .github/workflows/trivy.yamlname: Security Scanon: pull request jobs: scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Trivy Scan uses: aquasecurity/trivy-action@master with: scan-type: 'fs' ignore-unfixed: true severity: 'CRITICAL,HIGH' exit-code: '1' Now your repo blocks merges when new CVEs appear. The exit-code: '1' line is the important one — it tells Trivy to fail the action if it finds anything critical, which is what stops the merge. This is the gate that protects you from the next CVE your AI assistant introduces. Let’s break down what just happened, because the four steps above are doing more than they look like. The install step is just a binary. No daemon, no config, no service. Same reason Go itself wins for CLI tools — you download it, you run it, you delete it. The scan step reads three things: your go.mod, your go.sum, and your source tree. It doesn't compile anything. It doesn't run anything. It just parses and reports. That's why it's fast — a typical Go service scans in under 10 seconds. In an era where AI generates code faster than you can read it, a 10-second scan is the only realistic gate. The fix step is just go get. Trivy doesn't patch your code. It tells you what's wrong, and you decide how to fix it. This is the right division of labor — the scanner reports, the developer decides. The AI assistant can suggest the bump; you approve it. The CI step is the part that actually saves you. A one-time scan catches the bug you have today. A scan on every PR catches the bug you introduce tomorrow — including the bugs your AI introduces. The exit-code: '1' is what turns a report into a gate. 1. I scanned only direct dependencies. The first time I ran Trivy, I told it to ignore transitive deps because I thought “I only depend on three libraries.” The CVE was in a sub-dependency of one of those three. Always scan the full graph. This matters even more with AI-generated code, because the model picks the obvious import and the obvious import has a deep tree. 2. I ran it once and forgot about it. A scan is a snapshot. The day after I scanned, a new CVE was published for a library I was using. The fix wasn’t to scan more often — it was to scan on every PR. That’s what the GitHub Action does. In 2026, “scan on every PR” is the only setting that keeps up with the pace of AI-generated commits. 3. I treated “no fix available” as “safe to ignore.” Trivy has an ignore-unfixed flag. I turned it on. That meant it stopped reporting CVEs that didn't have a patched version yet. The right setting is to leave it off and triage those manually — at least you'll know they exist. With AI-generated code, the unknown unknowns are exactly the ones you need to see. If you want to take this further, here are the three things I’d build next, in order of effort vs. payoff. 1. Add trivy image to your release pipeline. Before you push a Docker image to a registry, scan it. The same binary, the same output format, but it catches CVEs in the OS packages too. One line in your CI. AI-generated Dockerfiles are especially prone to using outdated base images — golang:1.18 is still common in training data, even though it's three years out of support. 2. Add a pre-commit hook. Use pre-commit to run trivy fs on staged files only. Catches the bug before it even reaches the PR. Five minutes to set up. This is the gate that catches the AI-generated commit before a human ever reviews it. 3. Scan your IaC. Trivy also reads Terraform, Kubernetes manifests, and Dockerfiles. If you’re deploying Go services with any of those, you’re already paying the cost of misconfiguration — Trivy just makes it visible. AI-generated Kubernetes manifests are particularly prone to running as root, mounting host paths, and exposing debug ports. Security scanning is one of those things that feels like it should be hard. It isn’t. The hard part was always deciding what to scan and how to act on the result. Trivy makes both of those decisions for you: scan everything, fail on critical. In 2024, this was a nice-to-have. In 2026, it’s the only thing that scales. The pace of AI-generated code has outpaced the pace of human code review. The scanner is the review. The 5 minutes you spend setting this up today is the 5 hours you don’t spend triaging a CVE in production next quarter. That’s the trade. Take it. Secure Your Go Projects in 5 Minutes with Trivy — Full Walkthrough https://blog.stackademic.com/secure-your-go-projects-in-5-minutes-with-trivy-full-walkthrough-d91605771b04 was originally published in Stackademic https://blog.stackademic.com on Medium, where people are continuing the conversation by highlighting and responding to this story.