Behind every business is a multitude of software that keeps the operational engine running. When it comes to mechanical engines, we trust in the pieces and parts that help it run smoothly and safely. The same can be said for the software that we use to run our businesses. As new ‘pieces and parts’ (or features, functionality and updates) are built and deployed we have to be sure that they are safe and can be trusted.
Code signing is like a virtual mechanic, ensuring trust across the software supply chain by validating the identities of source code and verifying that it hasn’t been tampered with. Code signing, and the process of establishing and ensuring trust, has become more critical alongside our growing reliance on software that we purchase from third-party vendors and build and deploy within our own organizations using everything from PowerShell and Bash scripts to containers, libraries, files and executables.
The speed of DevOps continues to increase thanks to CI/CD, build and test automation tools. A heavier reliance on process automation generally means there are fewer human eyes on development cycles and a weaker line of sight on the pipeline itself.
Code signing isn’t new, but it has changed.
Attackers and malicious threat actors troll complex environments looking for weaknesses and vulnerabilities; overlooked or neglected areas where they can inject malicious code undetected. Their process is so stealth, that often the malicious code would resemble a few lines of benign-looking code in your source code repository or build servers. As we saw with the SolarWinds attack, the technique has the potential to cause widespread distribution (and mayhem) across the supply chain.
When it comes to security, signing code simply isn’t enough. DevOps must ensure authenticity by making sure that the product that developers build is the product that gets delivered to the customer, and that infrastructure and private keys used to sign code are tightly controlled.
A recent study found that businesses have 25 code-signing certificates, on average. About 51% of study participants said they store associated private keys in a hardware security module (HSM). Yet on the other side of the spectrum, many said that private keys are also stored on build servers (33%) and developer workstations (19%). Perhaps most alarmingly, nearly two-thirds (60%) of respondents said they have no formal access controls and approval processes for code-signing keys.
These findings, combined with an increasing number of code signing attacks, underscore the importance of formalizing code signing best practices, whether you’re starting from scratch or refreshing processes you’ve already in place.
Here are six steps your team can apply to establish code signing best practices:
- Protect private keys in a centrally controlled HSM (physical or cloud).
- Enable developers to use native tools and signing methods on their local machine, without private keys ever leaving the central HSM.
- Control access and segregate duties for different teams and roles.
- Enforce policy guardrails for signing based on user/group, location, signing method and other parameters.
- Maintain an audit trail and timestamp of all code signing activities and key usage.
- Integrate with build servers and CI/CD tools (most notably Jenkins), to automate code-signing.
With the shift toward more frequent software updates, remote development teams and more products, it’s important to retire manual processes and embrace code signing best practices and technology that delivers on transparency, ease of use and most importantly, security.