One effective way to accelerate your security code review or pentest is to understand what developers get for free! In this blog post, we'll see why this matters.
Today, it's increasingly rare for developers to create applications without utilizing frameworks and libraries. These tools offer functionalities that are often more mature and reliable than custom-written code.
For example, developers shouldn't usually have to write their own implementations for authentication, password storage, JWT, or SAML. These features are hard to write and hard to get right. The more developers rely on battle-tested code for these, the better.
For security reviewers, this means you can probably increase your coverage by spending more time on the code that developers didn't get for free!
This doesn't mean you shouldn't test these frameworks or libraries. Instead, it suggests that the code provided by these tools is generally of higher quality and security.
Understanding what developers get for free can also help you identify common misuse. If you're experienced in code review or pentesting, you know that many frameworks and libraries do not always provide a high level of error-proofing, and developers often make similar mistakes.
As a security code reviewer, you can look at the list of dependencies used by the application to know what the application is using. From there, you just need to ensure they are using those dependencies properly.
From a black box perspective, it's a bit harder to know accurately, but you can rely on a few clues: error messages, URL mapping, quirks that the library or framework may have, exposed documentation and example pages left from development, favicons, HTTP headers, cookie names, and so on. It’s challenging at first, but with time and experience, you can get really good at this!
If you are working in application security and want to scale your efforts, providing as much "free code" to your developers as possible is key. This "free code" ensures they don't reinvent the wheel, and you won't have to review 200 implementations of the same thing. Be sure to check out our blog post on building blocks that covers this in detail.
In some cases, especially with hard targets, you may need to do the opposite and scrutinize the "free code" more closely. You may find that the dependencies are a softer target than the main codebase relying on them.
In conclusion, "free code" is a crucial aspect of any source code review and pentest, as well as a key component of a scalable application security strategy.
Let’s walk through a few examples of where frameworks and languages are doing a great job, and where they still leave developers exposed to unnecessary risks.
Modern frameworks do a great job at embedding security features into the core developer experience. Here are a few examples that stand out:
Django's password hashing auto-upgrade: when a user logs in, Django transparently re-hashes their password using the most secure algorithm configured. Developers don’t need to worry about migrating hash formats or checking against legacy ones — it just works, securely.
Traversal-resistant file APIs in Go: Go recently introduced secure file system functions that help prevent directory traversal vulnerabilities. With these APIs, developers can safely resolve file paths without manually sanitizing input or writing fragile code. It’s an example of how better primitives lead to fewer bugs.
While frameworks and languages have improved significantly, there are still security pitfalls that developers routinely fall into — often because the APIs lead them in the wrong direction by default.
HTTP clients that follow redirects by default: This behavior is one of the most common causes of SSRF vulnerabilities observed during code reviews and CVE research. Developers add a deny list of internal IP addresses to prevent SSRF, but the HTTP client automatically follows redirects — allowing attackers to bounce through an external site and land inside the restricted range.
Disabling redirect-following should be the default, or at the very least much easier to control. Developers should have to opt into redirect behavior — not the other way around.
Hostname validation done wrong: Validating that a hostname belongs to a trusted domain seems easy, but it’s a trap for many developers. Common mistakes include using Contains("trusted.com")
or even EndsWith("trusted.com")
, which can be bypassed with hostnames like notreallytrusted.com
or hackingtrusted.com
.
This could be solved with better APIs — something like isSubdomainOf("trusted.com", input)
— that do the hard work correctly and consistently, making it easier to avoid common errors.
The more developers get for free — through secure defaults, guardrails, and high-quality primitives — the less they have to invent and the less security has to review. Some frameworks like Django and Go are leading the way, but there’s still a lot of room for improvement.
We should continue asking: what else should developers get for free? Because the more we get this right at the foundation, the more secure our applications become — by default.