Skip to content
Notifications
Clear all

Why is Semgrep missing critical vulnerabilities in my code?

19 Posts
19 Users
0 Reactions
55 Views
(@charlotte4)
Estimable Member
Joined: 2 months ago
Posts: 99
 

I had the same experience trying it on our old Django codebase. The default security packs missed several obvious template injection sinks.

Have you checked if taint analysis is enabled for your scan? I think some of the command injection rules require that mode, and it might not be the default. The command gets flagged in the docs' examples because they use a specific test setup.

But even with taint mode on, our results were still pretty hit-or-miss compared to other tools, which matches what you're seeing. Did you end up trying to write a custom rule for that specific pattern?



   
ReplyQuote
(@finleyh)
Estimable Member
Joined: 2 months ago
Posts: 154
 

Yep, the taint mode flag is easy to miss. The docs bury it. You'll see it in the CLI examples, but it's not on by default for most configs. That catches a few more issues, but it's still a whack-a-mole setup.

> our results were still pretty hit-or-miss
Exactly. For those Django template sinks, I wrote a custom rule. It was basically just matching `{{ something|safe }}` and the common `mark_safe` call patterns. It worked, but then I was just playing regex whack-a-mole against my own codebase, which feels like a step backwards. You're right, other tools just find that stuff out of the box.


YMMV


   
ReplyQuote
(@harperj)
Honorable Member
Joined: 2 months ago
Posts: 602
 

You're asking the right question. The default packs, especially the broader ones like `p/ci`, are intentionally tuned for lower false positives, so they miss a lot of the deeper security sinks unless you're in a specific taint-tracking mode.

Your example is a perfect illustration. For that `os.system` pattern, you'd need to enable taint mode *and* likely be using the `p/command-injection` pack. But even then, it's not magic. If `request.args.get` isn't defined as a source in the taint rule, it'll miss it. That's where the custom rule gap hits. The base rule might only flag `flask.request.args.get`, leaving `django` or generic `request` objects in the dark.


Keep it constructive.


   
ReplyQuote
(@carolp)
Reputable Member
Joined: 2 months ago
Posts: 363
 

Exactly. The whack-a-mole feeling is why I stopped relying on Semgrep for deep security. You end up writing a bespoke linter for your own codebase.

You can get that template injection rule into a semi-reusable state by defining proper taint sources and sinks, but then you're just building your own security pack. At that point, other tools with better out-of-the-box framework support become cheaper to run.


—cp


   
ReplyQuote
Page 2 / 2