Table of Contents
Keep your supply chain secure
A secure code supply chain starts with knowing what code you are actually using in your applications.
Web applications today rely heavily on code produced by external developers. So, you’ll find that modern applications are predominantly built on open source software (OSS) from third parties.
The code supply chain contains all the external code that an application depends on - both open source or commercial. And like any supply chain it’s vital to ensure that the code always delivers what you need in a secure and efficient way.
A web application may consist of hundreds or even thousands of code dependencies. Synopsys state that by using external dependencies, up to 70% of the code in your applications is written by someone else. And 99% of all codebases analyzed contained open source code.
Adding to this, many companies don’t really have a good inventory or knowledge of what open source software they’re using in their products or the full extent of their dependency on open source.
Gartner projects that the level of global security spending will reach $170.4 billion by 2022. The overall financial cost to businesses impacted by cybercrime is projected to reach $6 trillion globally in 2021. So, the outlay for properly managing and securing the code supply chain is often minuscule compared to the potential financial costs and loss of reputation as a consequence of a security breach!
In order to keep track of vulnerabilities in your open source dependencies, you must first be aware that they exist in your codebase. Lacking visibility and insights into what packages you are using can negatively impact your software application in a number of ways.
Additionally, most dependencies you use have dependencies of their own. So, if you’re solely scanning your own code and its dependencies, then your attack surface is far bigger than you may think.
Avoid building an application with security vulnerabilities, dependency issues or breaching license conditions. Bytesafe can prevent putting your applications and business at risk by improving your dependency security and protecting your code supply chain.
What is dependency security?
Dependency security is the concept of managing the risk introduced into your application by external code, code that you have no direct control over.
Dependency security starts with knowing and controlling the dependencies you are using. And it continues with making sure dependencies are secure and trusted, always available, up-to-date, abiding to your company’s security policies and have been added intentionally.
Control is needed to be able to mitigate security attacks such as Cross-Site Scripting (XSS), Cross-Site Request Forgery (CSRF), XML External Entity (XXE) and Business logic attacks to name a few. Attacks potentially introduced into your supply chain through typosquatting or dependency confusion.
The ever changing open source landscape makes managing and keeping track of code dependencies, open source security and license compliance a challenging task for businesses using open source in their codebase.
Organizations need to ensure that:
- Open source dependencies are secure
- Package workflows meet the required business and security policies
In order to develop secure applications, developers need to understand and be aware of the different types of attacks that can be exploited. Not everyone does. OWASP is a great source of information that helps you get up to speed: https://cheatsheetseries.owasp.org/.
What is a dependency?
Using and sharing reusable building blocks of code is commonplace and speeds up the software development lifecycle (SDLC). Each piece of code is designed for a specific purpose, saving the time and effort of developers from having to write it themselves.
A dependency is a reusable piece of code that an application depends on and is required for it to work properly. For web application projects, these dependencies are often sourced using package managers such as npm. The public npm registry holds approximately 1.5 million packages that developers can download at any time, with on average 1 billion downloads per day.
Dependencies in the npm ecosystem are particularly interesting from a security perspective, for two reasons.
Secondly, dependencies often have dependencies of their own. As such, when adding new packages to your project you might include more dependencies than you originally thought or intended.
There are two types of dependencies;
- Direct dependencies when your application directly uses a piece of code and references it directly
- Transitive dependencies which are dependencies to your application’s direct dependencies (also known as a dependency of a dependency)
Good dependency management means having visibility, insights and control over all the dependencies your applications are using. Including all transitive dependencies!
The risk is that by introducing third-party software into your application, you’ll also incorporate the third-party software’s vulnerabilities, security flaws and software bugs.
Managing dependency security
In larger organizations with multiple development teams and numerous applications, it can be a complex task to keep track of what dependencies are being used in your applications.
Traditionally backend services use authentication, encryption of data, secure stores for tokens and credentials, access management and so on. But, your frontend security is only as strong as your weakest link or external dependency.
Keeping your dependencies up to date is critical, but prioritizing between dependencies vulnerable to security threats and updates that won’t break your code can be confusing.
Establishing a clear protocol to dependency management will help prevent headaches later in the development cycle when it could be more costly to resolve them.
Avoid outdated and obsolete dependencies
To an extent software is a fresh commodity where you want to make sure you’re using well maintained and updated components. New releases may not only include new features that you as an organization want to make use of, but also critical fixes for known vulnerabilities that close potential attack vectors.
As a user you want to avoid software decay and make sure the dependencies you are using are up to date with the latest releases. Organizations should develop an approach on how to continuously check and update their dependencies. Weighing the benefits of up to date dependencies with the work necessary to test their applications with new dependency versions.
Without a plan to prevent stale dependencies, combined with not updating versions you may miss out on:
- The latest enhancements that improve performance or added new functionality
- Bug fixes
- Alerts to code that has been deprecated or reached end-of-life
- Plus, expose your application and users to known security vulnerabilities
Use Bytesafe to identify and visualize the dependencies you are using in your projects and avoid software decay:
- View dependencies and manage package versions in Bytesafe together with potential security and licensing issues
- Create and clone new registries when updating dependency versions
- Archive the previous working states and revert back if needed
Dependency on external developers
Within your own organization you’ll probably have internal policies and controls to make sure that the code you have written is thoroughly tested, with defined KPIs for code metrics and so on.
For third party code, most of it is not written by large enterprises like Facebook or Google, with all their substantial developer power behind them. Instead, most packages are published by dedicated communities of individual developers who maintain the code with their own objectives in mind.
When your application utilizes external dependencies it means as an organization you’ll depend on developers who you can exert no real control over. And that is a sobering thought. Without having control, how do you know whether the open source components in your codebase are being maintained?
When you have a dependency on external developers you are not able to:
- Influence how the component code is written
- Prevent the code from being changed in the future
- Ensure adequate background checks on new developers helping out with the codebase
- Control if the developers manage tokens and credentials securely
- Know whether the code will remain compatible with your dependencies
Use Bytesafe for all your private and public packages to:
- Proxy and cache all public packages your applications depend on using Bytesafe
- Setup different registries for different purposes to adapt to your internal workflow and security process
- With Bytesafe you are able to set up hierarchies with different policies or clone registries for different teams or sprints
Lack of secure tokens and credentials management for package maintainers
Statistics from 2020 show that only 9.27% of all maintainers of npm packages use 2-factor authentication (2FA) to secure their accounts from being hacked or taken over.
With so many maintainers not using 2FA to protect their accounts, there is a risk that you cannot really trust if a new package version has been published by the original maintainer or a party with malicious intentions.
Assume that your dependencies will have vulnerabilities
Dependency security also involves how you manage known vulnerabilities in third party libraries, and avoid new threats as well as how you manage the external dependencies in your applications.
Over time, application dependencies can become deprecated or new vulnerabilities can be found. Therefore, knowing what dependencies your application is using (both direct and transitive dependencies) is key to being able to remediate potential issues and stay up to date.
It’s easy to include new dependencies, so you’ll need to make sure that your application dependencies are managed according to the rules set by your company.
Gain insights and receive notifications from Bytesafe:
- Bytesafe displays badges that flag that a particular package has been deprecated or has security or license issues
- All packages and versions are continuously scanned for known vulnerabilities and license issues
- Bytesafe identifies issues that need to be addressed in your third party dependencies as well
When it comes to the quality of open source, there are no controls or security/quality assurance checks that must be met in order to publish a package to a public registry.
That means that you will find packages where security has been taken seriously, but also there are many packages where security has not been a priority.
While there are many tools and services available to simplify discoverability of packages, it is also important to decide what metrics to look and assess before deciding to include a new dependency in your application.
For example, one often used metric is popularity (number of downloads, dependent packages etc), which is not sufficient for dependency security and a misleading signal. Other common metrics to look at may be latest release date, outdated dependencies, stable versions, existence of key files (e.g. README), code coverage from tests and if there is a custom website.
With the large number of external dependencies in existence, dependency security should be something that everyone in a team should work with and care about, rather than having just one or two dedicated persons. Dependency security is everyone’s problem!
Is open source code secure?
No, not by default.
In theory “open source allows for more eyes on the code” means that more people are “eyeballing” the code, implying a better level of security than for example proprietary closed code, that limits access and visibility.
While it’s true that more people are looking at the code, it’s a myth that they are all scrutinizing the lines of code, diligently looking to iron out the wrinkles. With so many open source projects running into millions of lines of code, there are not enough suitably qualified people in security with the capacity to check and review the code exhaustively.
And even worse, in situations where software that is seldom or never looked at or updated, code vulnerabilities can be leveraged for malicious activity.
Using packages from the public npm registry has become such an easy process that it has contributed to the increase in downloads and software productivity. But, with the breakneck pace expected of developers to produce applications, many have never actually looked at their code and the third party dependencies.
Hiding in plain sight
Attacks on the code supply chains
Supply chain attacks are on the rise and have been over the last few years. Instead of trying to hack and exploit existing vulnerabilities in code, hackers are more and more steering their attempts at getting their malicious code included in your applications as part of the build process.
Supply chain attacks to know of and look out for:
- Package and account takeover (with malicious intent)
- Typosquatting and combosquatting
- Dependency confusion
The recent SolarWinds supply chain attack is perhaps the most well known example of a supply chain attack, where malicious code was inserted into one of the SolarWinds products and distributed as an update to many of their customers. But there are also plenty of recent examples of malicious packages of similar attacks in the npm ecosystem.
With these kinds of attacks and attempts increasing, it is now more important than ever to protect your code supply chain!
Package and account takeover attacks
One way for hackers to get into your application is via the supply chain, exploiting a legitimate npm package from the long list of dependencies you are already using.
With access to the maintainer token for a package, a new version can easily be published that includes a targeted weakness ready to be exploited. Such attacks often keep all the original functionality of the original package as it makes it backward compatible and more difficult to detect. With the widespread reuse of npm packages, a compromised account can impact many users around the world.
One way to get access to a legitimate package, is to exploit the fact that many package maintainers are not securing their credentials, creating strong passwords or using two factor authentication with npmjs.
Traditional social engineering is also used, where malicious developers initially contribute to the code base, but once they are added as maintainers, they add malicious code and publish new versions or even remove the original maintainer (which is referred to as account takeover).
Typosquatting and combosquatting attacks
Typosquatting attacks that trick developers into installing malicious packages having similar names to the official packages. Combosquatting is similar to typosquatting, but uses real-like names instead of relying on typos.
By relying on human errors through typos or hoping developers will not bother to review dependencies, hackers want to get their packages pulled into your projects and supply chain.
When downloading and using open source packages you are essentially trusting its publisher, although none of the package hosting services can ever guarantee that all the code uploaded is free from malware.
Most developers and organizations blindly trust that the used dependencies don’t contain malicious content (intentionally or not). And when installing packages from npm or any other repository, users automatically download and install a package along with all related dependencies.
To be on the safe side you need to make sure you are pulling the packages you intend to.
Dependency confusion attacks
Dependency confusion (sometimes known as substitution attacks) confuses package managers on what package version to pull into their project. The attacks target vulnerabilities or design flaws in automated build or installation tools that enable public dependencies to be mistaken for internal dependencies with the exact same name.
The attack comprises uploading malware to open source repositories and packages automatically being distributed downstream into a company’s internal applications - with the public package getting priority and being pulled without needing any action from the developer.
If the attack is successful, a package from an unintended source will be included in your applications, with the possibility of running scripts and executing arbitrary code on the server.
Securing your code supply chain
Securing your supply chain assumes that you have the processes in place to make sure new dependencies or versions are added intentionally. It also implies having access to the right tools that give you the right depth of transparency and overview as well as help you protect your organization from malicious code.
As with quality assurance (QA) where it is better to find bugs before they are deployed, it is better to block and detect security and license issues before they become problems.
Secure your supply chain by:
- Continuously scan dependencies to find vulnerabilities
- Using Bytesafe Security Policies to manage your dependencies according to your business rules
- Creating a dependency firewall
- Having the same level of security for all packages
Continuously scan dependencies to find vulnerabilities
While your dependencies might be secure when you add them to your applications, new vulnerabilities are found all the time. Continuously scan your dependencies, instead of solely relying on point in time scans and make sure critical security flaws do not find their way into your applications.
The Vulnerability scanner in Bytesafe detects known security vulnerabilities in your dependencies. When the scanner identifies vulnerabilities, notifications will be sent to users and security badges will be added to flag the impacted dependencies.
The security badges show the severity of the vulnerability and link to the advisory which holds additional information such as a recommendation on how to remediate the security issue.
The vulnerability scanner helps you remain up to date with the security of your dependencies by finding and highlighting vulnerabilities. To restrict packages, read on how to use Bytesafe Security Policies.
Using Bytesafe Security Policies to manage your dependencies according to prescribed business rules
Security policies in Bytesafe allow you to manage your dependencies homogeneously throughout your environment according to your existing business rules. Bytesafe security policies are rules that are executed before any registry action, preventing unwanted package versions from being included in your registries.
To avoid having one or a few individuals responsible for dependency security shift responsibility from individual developers to your teams using efficient tools like Bytesafe.
Make use of the range of security policies in Bytesafe to establish control of the dependencies. One example is the Freeze policy that can be used to make registries read-only (temporarily or permanently). Or the Secure policy that prevents package versions with known vulnerabilities from being included in your registries.
The Block policy can be used to block whole packages or ranges of versions from being pulled into a registry.
By blocking internal package names in a firewall registry, external packages substituting internal packages is no longer an option.
Creating a Dependency firewall
The idea is simple, create a link to the public npm registry that works as a single point of contact with the outside world.
All other internal registries will use this single firewall registry as a package source. This enables a central point where security teams can monitor and ensure that only approved packages are included.
By using a dependency firewall in this way, new packages and versions do not automatically trickle down to all other users and applications in an organization.
Having the same level of security for all packages
Use Bytesafe to bring together your different teams (Dev / DevOps / DevSecOps) to collaborate around your dependency security.
Unless you have explicitly configured to use a private registry, the default is to use the public registry directly. The npm client actually allows installation of packages from both an npm registry or directly from a git repository.
In order to add a layer of security you should make sure that the whole organization is using private registries for your own packages that proxy packages from the public npm registry.
This way you gain insights in what packages are used in an application and have the flexibility to decide and control the level of security.
Setting up a hierarchy of registries with different levels of security (curation and separation of registries) you can apply Bytesafe policies and plugins on all your packages, regardless if they come from an npm registry or a git repo.
Therefore, all developers and systems using npm packages should be configured to use Bytesafe private registries with higher security and control.
What security does Bytesafe add?
Having all your own packages and external code dependencies held centrally in Bytesafe allows for continuous monitoring, scanning and control of the code you are using.
Knowing what (and who’s) code you are using is at the core of securing your code supply chain. Shift left and identify any issues early in the SDLC!
Using Bytesafe provides access to:
- Private registries. Share your packages within teams in fully managed artifact registries. Cache external dependencies to make sure they are always available
- Identification of all dependencies. Know what dependencies you are using. Immediately detect if any direct and transitive dependencies are flagged as deprecated
- Dependency firewall. Restrict what packages are allowed in your registries with policies and plugins
- Security scanning. Shift left and detect vulnerabilities early by continuously scanning all packages
- License compliance. Analyze what licenses you include in your applications and know if you have any license issues
- Deterministic results. Be sure to use Bytesafe in your CI/CD pipeline across different environments. The testers will be able to test the exact same versions that the developers intended. No more misconfigurations
- Bring together your team. Allow developers, QA, security experts and business teams to use the same tools to avoid an internal disconnect between different roles. Security is a team effort!