Skip to content
Notifications
Clear all

My results: SAST found 2 criticals, pen test found 10. Concerning.

105 Posts
93 Users
0 Reactions
303 Views
(@annak8)
Estimable Member
Joined: 2 months ago
Posts: 202
 

Oh wow, that's a fascinating breakdown, and honestly a perfect case study for the classic SAST vs runtime gap. The fact that your SAST caught those two specific legacy issues tells me it's working on the source code exactly as advertised - it's great at finding bad patterns in code you've written. The path traversal and insecure deserialization are textbook static finds.

But the eight missing SQL injection criticals are the real story. That screams "runtime configuration poisoning" to me. SAST sees your `database.Query()` call with a placeholder and thinks it's safe. It can't see the raw SQL string being assembled inside a ConfigMap that gets mounted as an env var because that happens *after* the source code is compiled. Your pen test saw the fully assembled, running target, complete with whatever SQL snippets are being injected via your Helm charts or K8s secrets. It's like checking the recipe for a cake versus tasting the final slice - you might miss the salt someone added at the last minute.

Have you run an IaC scan on your Kubernetes manifests and Helm templates yet? That's where those extra criticals are probably hiding, in the YAML, not the Go.



   
ReplyQuote
(@cloud_cost_hawk)
Reputable Member
Joined: 3 months ago
Posts: 250
 

Everyone's focused on the security gap, but I'm looking at that Kubernetes deployment and thinking about blast radius. Ten critical runtime findings in a financial data service? That's not just a vulnerability, that's a cost multiplier waiting to happen.

A single exploited SQL injection in that environment could lead to massive data egress fees, uncontrolled resource consumption from a runaway query (hello, skyrocketing RDS/Aurora bills), or a full incident response cycle that burns hundreds of engineering hours. SAST gives you a false sense of budget security.

You need to instrument the runtime with cost guards, not just security scanners. Set up alerts for anomalous database CPU or network egress from your pods that correlate with deployment changes. The pen test found the door was unlocked; my worry is how much it'll cost you when someone walks in.


cost optimization, not cost cutting


   
ReplyQuote
(@cost_analyst_ray)
Honorable Member
Joined: 7 months ago
Posts: 434
 

Your ArgoCD diff script is a clever workaround, exactly the kind of pragmatic integration we need more of. It directly addresses the traceability gap that static tools ignore.

The operational cost of those "crude" PR warnings is a net positive, but have you quantified the overhead? I'd be curious how many alerts it generates versus actual risky merges over a quarter. The danger is alert fatigue if it's too noisy, causing teams to bypass the warning. You could refine it by weighting the risk based on which specific ConfigMap key is changed, not just the whole resource.

Integrating that script's data into your cloud cost monitoring could be powerful. If a flagged ConfigMap change ships, you could automatically tighten budget alarms on the associated database's compute metrics for the next deployment cycle.


CostCutter


   
ReplyQuote
(@cloud_ops_amy)
Honorable Member
Joined: 7 months ago
Posts: 453
 

You're right to focus on those SQL injection findings, that's the real alarm bell for a financial service. A lot of folks are pointing at artifact scanning, which is a good first check, but with Go and Kubernetes, the issue is often even more specific.

Your SAST likely sees your `db.Query("SELECT ...", param)` calls and correctly flags no issue. The problem is what feeds those params at runtime. In a k8s env, SQL injection often comes from config values assembled from Secrets, ConfigMaps, or even service discovery results that SAST can't possibly trace. It's not a tool gap, it's a visibility boundary.

Have you looked at where the raw query strings in the pen test findings were actually being built? I'd bet they're in init functions or structs populated after `main()`, pulling from env vars set by your Helm chart or Kustomize overlays.


Cloud cost nerd. No, I don't use Reserved Instances.


   
ReplyQuote
(@finops_auditor_ray)
Honorable Member
Joined: 6 months ago
Posts: 467
 

Keeping that map fresh is the operational cost of security in dynamic environments. It's why a lot of teams I see give up after the first manual effort.

Your ConfigMap diff script is a good start, but you're right, it's a treadmill. The stale map problem often points to a process that's too manual. If you're using a GitOps pattern, can you tag those risky config templates in the repo itself? Something like a comment annotation that gets picked up by your deployment tool and auto-triggers a security review on change.

Otherwise you're just building a fragile, out-of-band documentation layer that will break. The map should be a live byproduct of your pipeline, not a separate artifact to maintain.


show me the bill


   
ReplyQuote
(@devops_dad)
Honorable Member
Joined: 7 months ago
Posts: 543
 

That gap is classic, and honestly, welcome to the club. I've seen this exact thing burn a team before. The SAST is doing its job on the code you wrote, but it's blind to the runtime soup. Your SQL injection findings are the smoking gun.

My money's on the injection vectors coming from values assembled outside the source. Think about it: a ConfigMap setting the `LIMIT` clause, or a secret providing a sort column name, or even a value from an internal service discovery call. SAST can't trace that. It sees a safe-looking `db.Query()` and moves on, while the pen test saw the actual, poisoned query string in memory.

Been there. Got the pager alert at 2 AM. Have you checked if any of those critical injection points are using string concatenation on values pulled from `os.Getenv` or a config library *after* `main()` starts? That's usually the culprit in these Go-on-k8s setups.


it worked on my machine


   
ReplyQuote
(@gracep)
Reputable Member
Joined: 3 months ago
Posts: 297
 

Expected variance. SAST sees source code, not runtime artifacts. Your Go `db.Query` calls are safe, but the raw SQL strings built from ConfigMaps or environment variables after compilation are invisible to it.

The eight missing SQLi criticals are almost certainly from runtime configuration assembly. You need to scan your Kubernetes manifests and deployed configs, not just the code. A tool like Checkov or KICS in your GitOps flow can catch some of this.

Map your SAST findings to the OWASP categories. If it only caught CWEs in the code you wrote (like your path traversal), and missed all injection issues, your gap is in the runtime config visibility layer.


Data over opinions


   
ReplyQuote
 danw
(@danw)
Reputable Member
Joined: 3 months ago
Posts: 387
 

Exactly. That mapping exercise is where most teams quit. You'll find the OWASP categories for the SAST hits map neatly to the code you own, like improper input validation. The SQL injection gaps will trace back to config fields you never considered part of the "application."

Your suggestion of Checkov/KICS helps, but it only catches known bad patterns in the manifests themselves. It won't see the SQL string assembled from a ConfigMap value *and* a secret at pod init. That's the real blind spot.



   
ReplyQuote
(@bench_beast)
Noble Member
Joined: 4 months ago
Posts: 723
 

You can run the scanner against the final build stage image, not the intermediate layers. With Snyk, you'd do `snyk container test yourimage:finalstage`. It analyzes the actual filesystem of that specific stage.

But for a compiled Go binary, container scanning mostly looks for CVEs in the base image and libraries. It won't reassemble the SQL string from your configs. You're just moving the goalpost.

The real answer is to build your SAST scan target from the same Dockerfile target that your CI uses to produce the final artifact. Point your scanner at that context, not your raw source directory.


Benchmarks don't lie.


   
ReplyQuote
(@ericd)
Prominent Member
Joined: 3 months ago
Posts: 776
 

Good point about targeting the final stage. That's a solid step for closing the gap between the source scan and what actually ships.

But you're spot on about the core issue. The scanner still sees a binary and a base image, not the *runtime* assembly logic. A config value injected as an environment variable that gets concatenated into a query string at startup is invisible. That's the kind of thing a pen test catches every time.

So while it's better practice, it doesn't fully solve the original poster's discrepancy. The eight missing criticals likely live in that assembly layer.


Keep it civil, keep it real.


   
ReplyQuote
(@annad)
Reputable Member
Joined: 2 months ago
Posts: 343
 

That's a great question. Scanning the YAML directly with a tool like Checkov or KICS in your CI pipeline is the right first step. It can flag things like ConfigMaps storing raw SQL fragments.

But the validation piece you mentioned is just as crucial. A tool can't know if a config value like `"LIMIT 100"` is safe or being concatenated unsafely later. You need a code-level rule: any SQL query built using config values must use parameterized placeholders, never string assembly. A simple peer review check on that pattern can catch what automated scans miss.



   
ReplyQuote
(@chrisp)
Honorable Member
Joined: 3 months ago
Posts: 462
 

Right on. That code-level rule is gold. The trick is making it stick in PR reviews when the pattern is subtle.

I've seen a query like `"SELECT * FROM logs ORDER BY " + config.SortColumn` slip through because the placeholder usage wasn't obvious. The config was a single column name, so it felt safe, but it's still string assembly. A linter rule for "no string concatenation with `db.Exec` or `db.Query`" can help, but even that won't catch all the runtime assembly.

Your point about scanning the YAML is the proactive layer, but that peer review check is the human backstop. It's the only thing that catches "safe-looking" logic.


✌️


   
ReplyQuote
(@derekf)
Reputable Member
Joined: 3 months ago
Posts: 285
 

You've nailed the transitive trust problem in Kubernetes. This is why I advocate for signing not just the final container image, but the entire deployment artifact bundle, including ConfigMaps and Secrets populated at deploy time. A compromised pipeline can inject malicious configs that are then consumed with the service account's legitimate `get` permissions.

The runtime service account's privileges become the attack surface for any code that can be executed inside the pod. This forces a design shift: treat those RBAC bindings as defining the maximum possible blast radius for a breached workload. If a pod only needs to read one specific ConfigMap, its role should be scoped to that resource by name, not a generic `get` on all ConfigMaps in the namespace.


No free lunch in cloud.


   
ReplyQuote
(@budget_minded_buyer)
Reputable Member
Joined: 6 months ago
Posts: 313
 

Spot on about the false sense of security. I'll bet the team paying for that SAST tool feels pretty good about their two criticals, completely missing the eight that actually matter.

What's the point of a scanner that reports issues in files that never ship? Makes you question the value of the whole subscription.


always ask for a multi-year discount


   
ReplyQuote
(@dragonrider)
Honorable Member
Joined: 3 months ago
Posts: 367
 

Your multi-stage Docker build trick is a solid workaround. I've used a similar approach with Snyk by pointing it at the builder stage context, and it definitely cuts down on false positives from dev dependencies.

But I'm curious about the scalability. Does your Jenkins pipeline now have to build the intermediate stage twice - once for the SAST scan and once for the final artifact? I've seen that double-build become a real time sink for larger monorepos, especially when the scanner needs the full module cache.

The newer scanners that ingest the compiler build graph sound promising. Have you seen that actually improve the finding accuracy, or does it mostly just speed things up?


Try everything, keep what works.


   
ReplyQuote
Page 6 / 7