By clicking “Accept All Cookies”, you agree to the storing of cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts. View our Privacy Policy for more information.
ToolAccuracy of FindingsDetects Non-Pattern-Based Issues?Coverage of SAST FindingsSpeed of ScanningUsability & Dev Experience
DryRun SecurityVery high – caught multiple critical issues missed by othersYes – context-based analysis, logic flaws & SSRFBroad coverage of standard vulns, logic flaws, and extendableNear real-time PR feedback
Snyk CodeHigh on well-known patterns (SQLi, XSS), but misses other categoriesLimited – AI-based, focuses on recognized vulnerabilitiesGood coverage of standard vulns; may miss SSRF or advanced auth logic issuesFast, often near PR speedDecent GitHub integration, but rules are a black box
GitHub Advanced Security (CodeQL)Very high precision for known queries, low false positivesPartial – strong dataflow for known issues, needs custom queriesGood for SQLi and XSS but logic flaws require advanced CodeQL experience.Moderate to slow (GitHub Action based)Requires CodeQL expertise for custom logic
SemgrepMedium, but there is a good community for adding rulesPrimarily pattern-based with limited dataflowDecent coverage with the right rules, can still miss advanced logic or SSRFFast scansHas custom rules, but dev teams must maintain them
SonarQubeLow – misses serious issues in our testingLimited – mostly pattern-based, code quality orientedBasic coverage for standard vulns, many hotspots require manual reviewModerate, usually in CIDashboard-based approach, can pass “quality gate” despite real vulns
Vulnerability ClassSnyk (partial)GitHub (CodeQL) (partial)SemgrepSonarQubeDryRun Security
SQL Injection
*
Cross-Site Scripting (XSS)
SSRF
Auth Flaw / IDOR
User Enumeration
Hardcoded Token
ToolAccuracy of FindingsDetects Non-Pattern-Based Issues?Coverage of C# VulnerabilitiesScan SpeedDeveloper Experience
DryRun Security
Very high – caught all critical flaws missed by others
Yes – context-based analysis finds logic errors, auth flaws, etc.
Broad coverage of OWASP Top 10 vulns plus business logic issuesNear real-time (PR comment within seconds)Clear single PR comment with detailed insights; no config or custom scripts needed
Snyk CodeHigh on known patterns (SQLi, XSS), but misses logic/flow bugsLimited – focuses on recognizable vulnerability patterns
Good for standard vulns; may miss SSRF or auth logic issues 
Fast (integrates into PR checks)Decent GitHub integration, but rules are a black box (no easy customization)
GitHub Advanced Security (CodeQL)Low - missed everything except SQL InjectionMostly pattern-basedLow – only discovered SQL InjectionSlowest of all but finished in 1 minuteConcise annotation with a suggested fix and optional auto-remedation
SemgrepMedium – finds common issues with community rules, some missesPrimarily pattern-based, limited data flow analysis
Decent coverage with the right rules; misses advanced logic flaws 
Very fast (runs as lightweight CI)Custom rules possible, but require maintenance and security expertise
SonarQube
Low – missed serious issues in our testing
Mostly pattern-based (code quality focus)Basic coverage for known vulns; many issues flagged as “hotspots” require manual review Moderate (runs in CI/CD pipeline)Results in dashboard; risk of false sense of security if quality gate passes despite vulnerabilities
Vulnerability ClassSnyk CodeGitHub Advanced Security (CodeQL)SemgrepSonarQubeDryRun Security
SQL Injection (SQLi)
Cross-Site Scripting (XSS)
Server-Side Request Forgery (SSRF)
Auth Logic/IDOR
User Enumeration
Hardcoded Credentials
VulnerabilityDryRun SecuritySemgrepGitHub CodeQLSonarQubeSnyk Code
1. Remote Code Execution via Unsafe Deserialization
2. Code Injection via eval() Usage
3. SQL Injection in a Raw Database Query
4. Weak Encryption (AES ECB Mode)
5. Broken Access Control / Logic Flaw in Authentication
Total Found5/53/51/51/50/5
VulnerabilityDryRun SecuritySnykCodeQLSonarQubeSemgrep
Server-Side Request Forgery (SSRF)
(Hotspot)
Cross-Site Scripting (XSS)
SQL Injection (SQLi)
IDOR / Broken Access Control
Invalid Token Validation Logic
Broken Email Verification Logic
DimensionWhy It Matters
Surface
Entry points & data sources highlight tainted flows early.
Language
Code idioms reveal hidden sinks and framework quirks.
Intent
What is the purpose of the code being changed/added?
Design
Robustness and resilience of changing code.
Environment
Libraries, build flags, and infra metadata flag, infrastructure (IaC) all give clues around the risks in changing code.
KPIPattern-Based SASTDryRun CSA
Mean Time to Regex
3–8 hrs per noisy finding set
Not required
Mean Time to Context
N/A
< 1 min
False-Positive Rate
50–85 %< 5 %
Logic-Flaw Detection
< 5 %
90%+
Severity
CriticalHigh
Location
utils/authorization.py :L118
utils/authorization.py :L49 & L82 & L164
Issue
JWT Algorithm Confusion Attack:
jwt.decode() selects the algorithm from unverified JWT headers.
Insecure OIDC Endpoint Communication:
urllib.request.urlopen called without explicit TLS/CA handling.
Impact
Complete auth bypass (switch RS256→HS256, forge tokens with public key as HMAC secret).
Susceptible to MITM if default SSL behavior is weakened or cert store compromised.
Remediation
Replace the dynamic algorithm selection with a fixed, expected algorithm list. Change line 118 from algorithms=[unverified_header.get('alg', 'RS256')] to algorithms=['RS256'] to only accept RS256 tokens. Add algorithm validation before token verification to ensure the header algorithm matches expected values.
Create a secure SSL context using ssl.create_default_context() with proper certificate verification. Configure explicit timeout values for all HTTP requests to prevent hanging connections. Add explicit SSL/TLS configuration by creating an HTTPSHandler with the secure SSL context. Implement proper error handling specifically for SSL certificate validation failures.
Key Insight
This vulnerability arises from trusting an unverified portion of the JWT to determine the verification method itself
This vulnerability stems from a lack of explicit secure communication practices, leaving the application reliant on potentially weak default behaviors.
Security
June 17, 2026

What Your Git History Knows That Your Call Graph Doesn’t

Ok, first, let’s be honest.

Most security conversations about Git history are painfully predictable... Someone committed a password. Someone left an API key in an old branch. Someone pushed a secret, rotated it, and then when the team is upset, they had to explain to the team why “it’s deleted now” isn’t actually how Git works.

That stuff matters, of course. But it’s also the obvious part in the year of 2026.

What has surprised me over the last few years building DryRun Security is that Git history has become one of the richest sources of security intelligence inside a modern software company, and not for any of the reasons most people think. The value isn’t that it tells you what the code says. The value is that it captures code-change behavior over time, how teams interact with the codebase, and how the system actually evolved, rather than how it was originally designed.

A static call graph can show you which function calls another function. Dependency analysis can show you which package imports another package. Architecture diagrams can show you how the system was supposed to be designed (assuming they were ever accurate and somebody remembered to update them sometime in the last five years). Git history is different because it captures historical movement.

One of the most interesting examples of this relevance to contextual security analysis is temporal coupling.

Temporal coupling occurs when two or more files are modified within the same time window frequently enough to not be considered correlated.

Article content
Example of temporal coupling, from DryRun Security.

In a microservices environment, some of the most important relationships are completely invisible when you look at the code statically. A payment service and an authorization service may never directly import each other and therefore never appear connected in a call graph. A feature flag system and a customer entitlement workflow may live in completely different parts of a mono-repo and be undocumented. A Kubernetes configuration, an API route, and a session validation module may exist in separate repositories, each managed by a separate team. If you looked at the system through the lens of structure alone, you could reasonably conclude that these things have very little to do with one another.

But the history in your source control management tools (e.g., GitHub Enterprise, GitLab) contain the truth.

Over months and years of development, patterns start to emerge as files get changed together. When two files, services, or repositories repeatedly change during the same window of work, there is usually a reason. Sometimes that relationship is obvious, but more often it isn’t. It may represent an undocumented dependency, an operational workaround that became permanent, a business process that evolved organically, or a security boundary that exists only in the heads of a few engineers who happen to understand how everything fits together.

What makes this particularly interesting from a security perspective is that many of the highest-impact vulnerabilities are not isolated to a single file, function, or service. Authorization flaws, tenant isolation issues, and business logic vulnerabilities often arise from interactions among multiple systems. Understanding those relationships turns out to be just as important as understanding the code itself, and those relationships are often much easier to discover by studying how software changes than by studying how software is structured.

This is one of the reasons we’ve become so interested in Git behavioral graphs at DryRun Security, because it helps us understand where risk is most likely to live before we ever begin analyzing code. If we can identify the parts of a system that are unusually interconnected outside of a call graph, we’ve already learned something useful about where deeper investigation should begin.

This is where I think many security tools struggle. Most tools evaluate code exactly as it exists today and attempt to determine whether a pattern is dangerous. That’s useful, but it ignores the history that produced the system in the first place. Security risk isn’t just a property of code. It’s also a property of change, ownership, institutional knowledge, and system evolution. The path a system took to arrive at its current state often tells you as much about future risk as the code itself.

Giving an AI an entire enterprise codebase and asking it to find problems is a bit like dropping a security engineer into a Fortune 500 company and saying, “Good luck.” The best reviewers don’t start everywhere. They start in the places where experience tells them risk is most likely to be hiding. They look for unusual patterns, hidden dependencies, and signs that a system has drifted away from its original assumptions. I

That’s ultimately what we’re trying to do at DryRun. We’re teaching our AI system to start where experienced security engineers would start. The goal isn’t simply to generate more findings. It’s to develop a better understanding of where risk actually lives inside a modern software system so that analysis can be focused where it matters most.

If that sounds cool to you, that's the tip of the iceberg on the new approaches we're taking at DryRun Security, and our team would love to help you get contextual security analysis helping your organization.