As software developers, one of the things that we worry a lot about is our software dependencies. To speed up delivery time of new functionality within our code we reuse software – we don’t have time to reinvent the wheel. We stand on the shoulders of giants and leverage all the hard work and lessons learned from the software developers of our past. Sounds great right! Well mostly great because we are faced with the underlying trials intrinsec to software development.
The challenge with software dependencies
There may be a slight (or massive) problem when we start adding the dependencies that we don’t examine closely. Before we dive into the level of dependency we have with external libraries, modules and frameworks, we need to define dependencies. Dependencies are the internal parts of our software and they can be used at different stages of the development lifecycle: development, runtime execution and testing. Dependencies are not all the same and can actually harm our software without us knowing it.
Types of software dependencies
There’s no limit in the size of the dependencies. A dependency can be thousands of lines of code, like a full fledged framework, or it can be a one liner. There is a whole range of different types of software dependencies.
Types of Dependencies: Frameworks, libraries packages, modules and resources.
Resources – Collections of files, for example templates, media (audio, video or images), plain text files or blobs that need to be included by applications to execute correctly.
Modules – Set of methods and functions that provide a self contained functionality. A module usually has an interface that specifies both the functionality it provides as well as the functionality it depends on.
Package – A collection of modules that hold in general the same functional purpose. Usually a directory that contains a file that describes metadata about the package.
Library – A collection of related functionality defined in several packages, is essentially a set of functions that you can call, each call does some work and returns control to the client or application that executed the function.
Frameworks – A framework embodies some abstract design, with more behavior built in. In order to use it you need to insert your behavior into various places in the framework. The framework’s code then calls your code at these points.
Level of dependency
Now that we have identified the dependency types, we have a clearer picture. The next step is to identify what dependencies are crucial, important, cosmetic, easily exchanged or superfluous to our own projects.
These two pieces of information help us decide the cadence of update, migration costs or cleanup efforts of each dependency and prioritize our resources!
What can possibly go wrong?
When we add a dependency to our project we are actually trusting the work of other developers. We are essentially outsourcing the work of developing that code – designing, writing, testing, debugging and maintaining – to someone else. Every time we use a dependency, we are potentially exposed to all failures and flaws of that dependency, and I am not talking about open source exclusively, closed source software has been known to have issues as well.
Open source software introduced a concept of “use as is’. An open source developer creates projects that adhere to their core values, intention and reputation. What we don’t know is whether all open source code libraries that we have are in optimal condition. This introduces a variety of security and performance challenges that require our awareness and treatment. Taking preventive measures today will save you time, headaches, and money in the future.
The next reasonable question is what methodology should we use to verify that the open source software we want to use is safe. What are the considerations that we need to double check when adding a specific dependency? What are the questions that we should be asking ourselves when using open source software? How well is the code written? How important is testing? What are the security best practices? What about transitive dependencies? How do we deal with dependencies?
Some free tools that can help
- Secure your git repository with Frogbot the git bot
- Scan your Docker containers for security vulnerabilities
- OWASP Dependency-Check Project
- Ossf security scorecards
Want to learn more? Join me at my next workshop to get all the details on these questions and more!