Security Tip: Keep Dependencies Updated
[Tip#18] Dependencies are security risks, especially if you have a lot of them or don't keep them updated...
👉 Looking to dive deeper into Laravel security? Check out Practical Laravel Security, my hands-on security course that uses interactive hacking challenges to teach you about how vulnerabilities work, so you can avoid them in your own code! 🕵️
👉 When was your last security audit or penetration test? Book in a Laravel Security Audit and Penetration Test today! 🕵️
A common pattern I see in the development communities is to use packages for everything, big and small. While this is a great way to avoid reinventing the wheel in your own code, each dependency you introduce into your application adds an extra security risk. This is known as a supply-chain attack.
Here are some examples:
Thomas Chauchefoin recently posted about a PHP Supply Chain Attack he discovered on the PEAR website. He studied the open source code behind the pear website to find a password reset vulnerability. Then he identified a known vulnerability in one of the site’s dependencies, an outdated version of`Archive_Tar`
, and used that to escalate the attack to gain remote code execution - i.e. a complete takeover of the site.
Yes, there was an initial vulnerability in the PEAR website, but the outdated vulnerable dependency made it so much worse.
Back in 2018, David Gilbertson posted a fantastic article about how he harvested credit card numbers and passwords1 through an npm dependency. He outlines the process and how easy it is to make a dependency malicious, and steal data like credit cards and passwords.
Over on his Kernel Mode blog, Sean Murphy has disclosed two malicious composer packages he discovered: typosquattingsymfont/process
, and cloned`laraveli/qr-code`
. Both of these malicious plugins allowed an attacker to gain remote code execution through a simple web request on any site with the package installed.
So what’s my point here?
Go and check your composer and npm dependencies and answer these questions:
- When did you last update your dependencies the latest available versions?
(You can use`composer outdated`
to check for outdated packages.) - When were they actually updated by their maintainers?
- Are you locked to an older major version of a package?
- Do you actually use each package you install?
- Does
`composer audit`
flag any vulnerable packages? - Does
`npm audit`
flag any vulnerable packages?
While you may have done a `composer update`
today, I’m willing to bet your answer to #2 includes some packages that haven’t been updated in 12+ months, and you’ll almost certainly have something that hits #3. As for #4, I guarantee you’ll have an unused package somewhere. #5 and #6 should come back clean, unless you haven’t updated in a while…
My recommendation is to only install the minimum required packages that you absolutely need.
Consider each package that you use: If it’s only a minor thing, can you implement it yourself and remove the dependency? Do you have an unused code path you can remove to eliminate an old dependency? Can you redesign how your app works so the dependency is no longer required?
I usually “implement it myself” when the package is essentially middleware or a facade wrapper around another package (and this happens a lot in the Laravel community).
Implementing my own middleware (like my CSP middleware) or my own facade-wrapper avoids the use of a package and realistically doesn’t take much extra time than installing a package and figuring out how to use it.
I’m no saying dependencies are bad, without them we wouldn’t have Laravel, but you need to be careful when adding them into your projects. For each dependency, consider if you really need it, or if you can implement it yourself, because every dependency adds a new risk.
Spoiler: He made up the story, but the risk is very real and malicious packages appear on npm all the time. ↩