Version 1.1 of The Secure Software Development Framework (SSDF): Recommendations for Mitigating the Risk of Software Vulnerabilities from NIST (NIST 800-218) was just published on February 3rd, 2022. The document was first released in September of 2021, but the SSDF program first started in May 2021 after Executive Order 14028.
I’ve been following this document from the start, having helped coordinate and contribute to Google’s response for public comment. After that I presented at the November NIST workshop where I was invited to speak on “Criteria and Attestation Approaches for Code Provenance” shortly after I left Google to start Chainguard, Inc.
After the latest document release, I took some time to explain and break it down! I especially focused on the areas I’m currently most interested in, which includes both in OSS on the Sigstore Project, and in our product development at Chainguard. If you would like a more general synopsis, please check out our previous post 'What is the SSDF?' gives a quick overview (complete with an infographic!)
The SSDF is broken down into four sections that can be implemented separately, but are all required in the development of secure software:
These are organized into tables, which contain a list of best practices. Each practice includes examples and references to other similar frameworks.
For each section, I’ll give a brief description then pick out three things:
Prepare The Organization (PO)
Protect The Organization is about “people, processes, and tools”, and focuses on organizational dynamics and design to produce secure software. The recommendations and best practices in this section explain how to define requirements and communicate them across your organization, as well as how to assign owners and ensure the requirements are met.
The first piece of advice here is obvious but often overlooked: Make sure the security requirements are defined and understood by your entire organization early! There are a variety of methods to assess risk levels and define security requirements. It’s most important that you pick one and use it!
Another sorely needed requirement is PO5.2: MFA And ZT for development infrastructure. I’ve been saying this for years: treat build systems like production systems, because they are! The entire Secure and harden development endpoints section is focused on this topic.
Define and document your security requirements (PO1.2) highlights that as part of this your organization should analyze the risk of applicable technology stacks (e.g., languages, environments, deployment models). This is important as some stacks will reduce risk as compared to others and this is changing fast as we start to see a better security posture across the industry.
Automation (PO.3) - use of automation is highly encouraged as it helps improve the accuracy, reproducibility, usability and comprehensiveness. Definitely time to throw out those clipboards and invest in automated tooling!
Require third parties to provide provenance data and integrity verification mechanisms for all components of their software (PO 1.3) - challenging as use of these mechanisms is not at all widespread yet.
Protect The Software (PS)
This section focuses on software and artifact integrity. It deals with artifact tampering, build system security, and version control. The recommendations in Protecting the Software are focused on making sure that the artifacts you execute were produced securely from source code, and that each step is protected from unauthorized access.
It has a lot of focus on cryptographic signatures and provenance, which are my favorite topics!
Store code securely. Anyone that has write access to your code has write access to production. When’s the last time you audited access to your GitHub repository?
Store and protect release integrity verification information and provenance data, such as by keeping it in a separate location from the release files or by signing the data. I see a sha256 hash next to the file itself all the time! This doesn’t provide any meaningful security guarantees.
Signing, Signing, Signing! It’s everywhere here. You’re supposed to sign and verify your releases, your source code, and your binaries. It’s all too easy to attack or persist an attack in artifact repositories. Requiring digital signatures is one technique to trace artifacts or source code back to their original author.
Signing also belongs here. Commit signing is difficult to get right and of little value (IMO) with today’s PKI, but things are improving with the addition of ssh keys in Git. Artifact signing works with central CAs, but these are typically expensive and hard to work with. Enter Sigstore! This is an open source effort to provide free, short-lived code signing certificates for open source development (I work on it!).
Produce Well-Secured Software (PW)
This section focuses on designing, writing, and testing secure software. The advice here focuses on techniques around code review, design review, and component selection. There’s also some guidance on toolchain maintenance, which is great to see.
Review the Design (PW.2). It’s sort of obvious, but having a second (or third) set of eyes reviewing a high level design, especially when dealing with sensitive data or complicated security controls, can help catch costly mistakes early.
Secure-by-default (PW.9). is another welcome reminder. Developers are lazy, and making them actively choose to do the secure thing is a recipe for disaster.
I was happy to see a concrete recommendation to reuse secure, shared components instead of rewriting them yourself (PW.4). This will be an amazing requirement to cite when trying to push back on NIH.
The guidance to periodically check that the compiler/build tool hasn’t been tampered with is very useful advice, and something easy to forget (PW.6). Losing trust in your compiler is straight out of Reflections on Trusting Trust, and is a doomsday scenario for sensitive workloads.
Change control for config! (PW 9.2) with configuration-as-code becoming de facto it is good to spell out that all the best practices for our code should also now apply to our configuration too.
Compiler vulnerabilities. Few organizations have accurate asset inventory, let alone provenance information that would contain which compiler version was used for a given release.
Respond to Vulnerabilities (RV)
This section focuses on everything you have to do after building your software! The saying goes “code ages like milk, not wine”. Operational software requires constant attention to monitor for reported vulnerabilities, understand your inventory, and patch or react quickly.
Monitor Vulnerabilities (RV 1.1) - don’t just wait for reports to come in, it’s important to be proactive by monitoring vulnerability databases, security mailing lists, etc. Even better if you can automate this.
Have policies for standard and zero day (RV 1.3) and also specific policies for incidents that involve multiple parties and open source software components.
Establish a program. This is hard. Katie says so.
The team at Chainguard are working on full end-to-end solutions to solve the problems outlined in NIST 800-218. If you want to learn more or discuss specific requirements for your organization check out Chainguard Services and get in touch!
This is the second article in a five-part series on NIST 800-218 ‘The Secure Software Development Framework (SSDF): Recommendations for Mitigating the Risk of Software Vulnerabilities’
The full series: