To sidetrack for a moment, I wish to put emphasis on the practice of dating packages. Just because dates are recent does not mean that all imported code is up to date.
First, repositories do not always have the most recent versions of libraries. Babel, which was referenced in the previous section, is version 7.2.2 within NPM and the most recent tagged release is 7.3.1 on Github at the time of writing.
Second, repository descriptions may not align with actual releases. As one example that drove my desire for this post, I noticed something very odd within a RichFaces UI Maven repository: all the dates for the versions were incorrect. RichFaces 3.3.4 released in July 2011, RichFaces 4.0.0 released in March 2011, and RichFaces 3.3.3 launched sometime in 2009. Additionally, all versions through 3.3.4 are vulnerable to CVE-2018-14667. When browsing the Maven repository for
org.richfaces.ui, Maven will give a variety of repositories, dates, and versions. If one needed RichFaces and were unfamiliar with Maven repositories, additional work would be necessary to ensure that the versions and deployments are up to date.
Note: Despite the focus on RichFaces, it should be recognized that RichFaces has been end-of-life since February of 2016.
Third, recently updated projects may still have older, more vulnerable libraries. As a rather weak example, the Spring PetClinic is a test project used to show Spring Boot in action. Despite receiving updates months prior, a vulnerable version of Jackson Databind was imported, as flagged by OWASP’s Dependency Check. However, as I wrote this post, another update was provided and this issue no longer persists.
Ultimately, what is needed is more discovery. We must first understand what is imported with every project build. The following is a list of commands and utilities that show the full dependency tree for libraries in various languages:
- Java Maven:
- Ruby Bundler:
gem dependency does not appear to present a full tree
- NodeJS NPM:
- NodeJS Yarn:
- Python Pip:
go list -f (naturally, no versions)
The above is only a subset and, if there is a repository or dependency-fetching system, there is more likely a standard or third-party tool that can assist in printing dependency trees for manual inspection.
Additionally, applications should have dependencies tested for known vulnerabilities. Note that all testing should be done with built projects. Simply scraping the list of explicit dependencies will miss vulnerabilities deeper in the dependency tree. Some tools, such as NPM, include an
audit command that will print known vulnerabilities (
npm audit). Additionally, some open source tooling exists that can scan built projects, such as OWASP Dependency Check. Enterprise solutions do exist, such as Sonatype, but come with a price tag.
What runs within our applications is not limited to just our internal code but our dependencies and any further libraries imported by them. However, we must not neglect to ensure that these deeper dependencies are up to date and secure. Additionally, we must take care when trusting repositories as they may lag behind or even contain incorrect or compromised data. Please take this post not as a specific learning point but as a reminder to audit and recall the whole of our applications.
Thank you for reading.