IT companies were the first to go open source, and many large businesses followed suit. After all, the ability to reuse and independently modify code as well as fix bugs spurs rapid innovation and cost reduction.
But open source has some inherent negative characteristics too — due to the blurred responsibilities for creating and maintaining the code. Endor Labs, aided by over 20 CISOs and CTOs of large IT firms, carried out a systematic analysis to produce this top-10 risk list.
The most significant risk identified was the presence of vulnerabilities both in the open-source project itself and in its dependencies — that is, external open-source components used in the project. Vulnerabilities in dependencies can cause critical issues for dozens of large commercial software suites, as was the case with the modest Apache Log4j library (CVE-2021-44228).
Safeguards: Regularly scan your applications for known vulnerabilities — including vulnerabilities in both direct and indirect dependencies. Apply available fixes promptly. To optimize company resources, patches can be prioritized based on the severity of a given vulnerability and the likelihood of its exploitation in the software you’re using.
Compromised legitimate packages
Since up to 80% of open-source project code is inherited from other projects in the form of those said dependencies, there’s always a chance that third-party components used in your application have been trojanized. This can happen when the developer of these components gets hacked, or the component distribution system (that is, the package manager) is found to contain a vulnerability that allows the package to be spoofed. In this case, third-party malicious code suddenly appears inside your application, which in practice is often used to steal information or for various illicit enrichment schemes (spam, adware scams, mining).
Safeguards: No mature methodology currently exists to safeguard against this threat, so a combination of measures is called for: manual and automatic systems for analyzing source code and monitoring repositories; local storage of trusted versions of components; use of Threat Intelligence to detect such attacks in their early stages (before they have time to affect packages used in the company’s open-source applications).
Attack of the “namesakes”
Attackers create packages with names that resemble legitimate packages, or copy the names of legitimate packages written in other programming languages or posted on other distribution platforms. This creates the risk that your open-source developers might integrate a malicious “namesake” package instead of the genuine one.
Safeguards: Instruct developers to be vigilant. As part of a standard procedure, before use, developers need to check the source code of packages for peculiarities such as encrypted fragments in the code, hijacking of functions and the like. And it’s advisable to check the digital signatures of packages (if any).
Developers of open-source components, packages and applications can pull support for them at any time and for any reason. This often happens with small packages developed by 1–2 people. If this does happen, there’s no one to update the package for compatibility with new technologies or eliminate information security risks.
Safeguards: Assess the project’s maturity level and development/support prospects before integrating it into business processes and your own code. Pay attention to the number of developers maintaining the project and the frequency of releases. Check for long-term support (LTS) releases and when they came out. For some stable projects, however, it’s quite normal for releases to be infrequent and to only fix bugs.
The use of old versions of components in projects makes patching much more difficult. This problem is especially acute in the event of risk number one: vulnerabilities in components. Typically, an issue with deprecated dependencies arises when a new version of a component differs significantly from previous iterations in terms of syntax or semantics. In this scenario, an outdated version can remain in use for many years without any security updates.
Safeguards: Allow developers time to work with dependencies — including refactoring your code to update to the latest versions of in-use components.
Since almost every application uses third-party components — which in turn use other third-party components — the developers of the main application are often unaware that a particular component is in their code. In this case, it doesn’t get checked for all the other risks in the list. The status of updates, vulnerabilities and the rest is simply unknown.
Safeguards: Maintain a detailed Software Bill of Materials (SBOM) with the use of scanning tools that can detect even dependencies that are used without a package manager.
Regulatory and licensing risks
Despite being open-source, every open-source application and package comes with its own usage license. Risks arise if the license turns out to be incompatible with using the application for the intended purpose, or the licenses of some application components are incompatible with each other. It’s also possible for one or more dependency components to violate applicable laws or regulatory requirements imposed on the company.
Safeguards: The already mentioned SBOM and code-scanning tools should be used to keep track of licenses and licensing requirements applicable to open-source applications and components used within the company. And it makes sense to work with the legal department to develop a list of standard licenses acceptable to the company, detailing their compatibility with the purpose of the software used. Software with incompatible licenses or no license at all should be removed.
Using components developed by a team that lacks maturity entails a number of inconveniences and risks. The problems associated with immature software range from insufficient or inaccurate code documentation to instability and error-prone operation and the absence of a set of tests for regression testing. What’s more, immature code is more likely to harbor critical vulnerabilities. All of this makes immature software impractical to use, and increases both the costs involved and the risks of critical events and downtime.
Safeguards: Before deploying an application or component, make sure the developers are using the best current practices. Indicators of this include having full and up-to-date documentation, CI/CD pipelines for regression testing, as well as detailed information about test coverage and even the number of packages that already use the given component.
The components used by an application can change in ways that are completely invisible to its developers. This situation can arise if components are downloaded from a server without strict version-control and/or over unencrypted communication channels, and are not verified using hashes and digital signatures. In this case, the application’s assembly can theoretically produce a different result each time.
Safeguards: Be strict in applying secure development practices. During development, use resource identifiers that clearly indicate the component version. Additionally, verify downloaded components using digital signatures. Always use secure communication protocols.
Dependencies too large or too small
These days, developers can integrate a component with just three lines of code. At the same time, it’s equally detrimental when the entire component consists of four lines of code (very small) and when code you intend to use is just one of thousands of component features — the rest of which are not used in the company’s application. In this case, the developers are burdened with maintaining yet another dependency for the sake of very little functionality.
Safeguards: Avoid dependencies with little functionality; develop such functionality inside the main application.