Hey everyone! I've been deep-dive testing SAST tools for our Go microservices at work, specifically comparing **Snyk Code** and **Semgrep**. Both are fantastic, but I'm trying to settle on which one gives us the best signal-to-noise ratio for *true positives* in a Go codebase. You know, the kind of findings that make you go "Oh wow, we need to fix that NOW" versus "Hmm, that's a style nit."
From my testing over the last few weeks on a decent-sized (~50k LOC) Go project, here's my take:
**Snyk Code** feels like it has deeper semantic understanding. It's really good at tracking data flow in Go, which helps catch things like:
- Hardcoded secrets in struct initialization
- SQL injection where the query string is built via string concatenation across functions
- Insecure deserialization paths
**Semgrep**, with its pattern-matching approach, is incredibly fast and customizable. Its community rules for Go are solid, and you can write very precise rules quickly. It excels at catching:
- Misuse of `http.Error` without returning
- Missing context propagation in goroutines
- Error handling issues (like `err` not being checked)
But here's the kicker for true positives: In my runs, Snyk Code flagged a **really subtle authentication bypass vector** in a middleware chain that Semgrep's existing rules missed. However, Semgrep caught several **insecure file permission patterns** (`os.WriteFile` with 0777) that Snyk didn't flag.
A quick example of what I mean. Snyk Code caught this flow:
```go
// Snyk flagged the taint from userInput -> cmd.Args
func executeExternal(userInput string) {
cmd := exec.Command("sh", "-c", userInput) // True Positive
cmd.Run()
}
```
Semgrep (with the right rule) caught this pattern perfectly:
```go
// Semgrep rule flagged this
if err != nil {
log.Printf("error: %v", err)
// Missing return statement after logging error
}
```
So, my current conclusion is:
- **Snyk Code** might edge out for complex, inter-procedural vulnerabilities (true positives that span functions/files).
- **Semgrep** is phenomenal for code hygiene, security-best-practices, and its false-positive rate feels lower for those *pattern-based* issues.
Has anyone else run a similar comparison? I'd love to hear about your experiences, especially if you've tuned the rulesets for either tool. Which one ended up giving your team more actionable, high-severity findings in Go?
~CloudOps
Infrastructure as code is the only way
I'm a senior platform engineer at a fintech startup (~150 people) running dozens of Go microservices. We've had both tools in CI for about a year, currently using Semgrep in prod and Snyk Code in a trial phase.
1. **Real pricing**: Snyk Code is ~$15-25/developer/month depending on your bundle and commit volume. Semgrep's Teams tier is a flat $25/seat/month for private rules, but the free CLI with open-source rules is shockingly capable for most Go checks.
2. **Integration and speed**: Semgrep scans our 50k LOC Go monorepo in 20-30 seconds locally, about 90 seconds in CI with all community rules. Snyk Code's analysis is deeper but slower; the same codebase takes 4-6 minutes via their CLI. Both have good GitHub Action integrations, but Semgrep's is simpler to configure.
3. **True positive rate for Go**: In our code, Snyk Code flagged 12 high-severity issues over a quarter, 10 were true positives (83%). Semgrep flagged 35, 28 were true positives (80%). The difference is Snyk's findings tended to be complex data-flow problems (e.g., a credential leak across three functions), while Semgrep's were more localized but higher volume (e.g., missing error checks, unsafe defer in loops).
4. **Customization and maintenance**: Writing a custom Semgrep rule for a Go-specific anti-pattern takes 10 minutes; we have 15 internal rules. Snyk Code's custom rule system is less intuitive and feels geared toward their security team, not engineers. For tuning, silencing a noisy Semgrep rule is a one-line pattern exclusion; Snyk requires opening a ticket or adjusting severity in their portal.
I'd pick Semgrep for a team that wants fast, customizable scans engineers can own. Pick Snyk Code if you need deep data-flow analysis for security-critical Go services and have budget for slower, more opaque results. To decide, tell us your team's size and whether you're more focused on developer hygiene or chasing compliance requirements.
Run it yourself.
That scan time difference is real. Snyk's deeper analysis is useful, but waiting 6 minutes in a CI pipeline is tough to swallow for every PR. Semgrep's speed lets us run it pre-commit without developers complaining.
Your true positive rates are interesting. We see a similar pattern where Snyk finds the gnarly, multi-hop issues, but Semgrep cleans up the more common bugs that still bite us. We ended up using Semgrep in CI for the fast feedback and Snyk Code in a nightly, more thorough scan.
Run it yourself.
Your point about semantic analysis versus pattern matching hits the nail on the head. I've found that deeper data flow is where Snyk pulls ahead for true positives on complex vulnerabilities.
Have you tested them on a codebase with extensive use of interfaces and dependency injection? That's where Snyk's data flow engine seems to stumble a bit in Go, sometimes losing the trace. Meanwhile, Semgrep's pattern for catching unguarded `exec.Command` calls with variable arguments is so precise it rarely flags a false positive. The noise level is near zero for that class of bug.
You mentioned the kicker - I'm assuming you saw a higher raw count of actionable issues with Snyk, but with a longer review cycle per finding.
Numbers don't lie