Automate NIST SSDF Compliance: A Technical Guide to Policy as Code in JFrog AppTrust

Automate NIST SSDF Compliance_863x300

For many engineering and security teams, NIST SP 800-218 (Secure Software Development Framework, or SSDF) compliance feels like a hurdle that is too difficult to overcome. To meet these and other emerging regulations and be effective in today’s DevSecOps environment, organizations are moving toward codifying these standards into machine-readable rules, also known as Policy as Code (PaC).

Most tools force you into closed-set, rigid policies that are difficult to adapt to your specific software development needs. By using Rego, the industry-standard language for the Open Policy Agent (OPA) engine within JFrog AppTrust, you gain the precise control necessary to natively enforce any custom governance rule without compromising how your organization’s software development workflows.

How Do You Map NIST SSDF Requirements to JFrog AppTrust?

NIST (The U.S. National Institute of Standards and Technology) designed the SSDF framework around four pillars:

  • PO – Preparing the Organization
  • PS – Protecting the Software
  • PW – Producing Well-Secured Software
  • RV – Responding to Vulnerabilities

JFrog products integrate directly into these pillars to provide automated evidence for compliance. The following table demonstrates how AppTrust specifically addresses critical NIST SSDF requirements through automated integrations.

NIST Requirement Objective JFrog AppTrust Integration
PS.3.2 Validating SBOM Attestation Integrates with JFrog Xray for deep-scan SBOM evidence, facilitating fast high fidelity validation.
PW.5.1 Validating Secure Coding Practices Verifies attestations from ecosystem partners like SonarQube or Troj.ai, enabling you to demonstrate the use of multiple tools to prove your secure coding model.
PW.2.2 Automating Release Approvals Automates ServiceNow Change-Request approval checks, enabling faster consistent automated workflows.
PW.6 Hardening and Build Process Security Validates binary-level analysis from JFrog Advanced Security and GitHub provenance, demonstrating the consistent application of security best practices.

 

With this capability, you can translate complex NIST SSDF requirements into logic that is stored along with your software. Whether you need to enforce two-person code reviews (NIST PW.6.2) or verify signed build provenance (NIST PS.3.1), you can now create a script for these rules in Rego and let JFrog AppTrust handle the enforcement.

How Do You Automate NIST SSDF with JFrog AppTrust?

Translating frameworks into code requires precise execution. Below, we break down the exact Rego code you can use in JFrog AppTrust to automate your compliance today.

Step 1: Validating SBOM Attestation (PS.3.2)

NIST requirement PS.3.2 mandates “collecting, maintaining, and sharing provenance data for all components,” which teams typically achieve using a Software Bill of Materials (SBOM). JFrog AppTrust uses deep-scan SBOMs created automatically by JFrog Xray with new releases to provide a Single Point of Truth.


package curation.policies
    import rego.v1
default should_allow := false
release_evidence := [evidence | some evidence in input.data.evidenceConnection[_]]

# PaC: Enforce SBOM Evidence (NIST PS.3.2)
should_allow := true if {
# Check Xray SBOM evidence existence
	some evidence in release_evidence
     evidence.node.predicateType == "https://jfrog.com/evidence/cyclonedx/sbom/v1.6"
}
explanation := "NIST Violation (PS.3.2): SBOM evidence is required for provenance data compliance. No SBOM evidence found from Xray." if {
	should_allow == false
}

allow := {
    "should_allow": should_allow,
    "explanation": explanation
}

 

Step 2: Validating Secure Coding Practices (PW.5.1)

Under PW.5.1, you must prove automated security testing was performed to find vulnerabilities. JFrog AppTrust allows you to ingest and verify evidence from ecosystem partners like SonarQube or Troj.ai, ensuring that no code reaches production without a passing security scan.


package curation.policies
import rego.v1
default should_allow := false
#artifact_evidence := [evidence | some evidence in input.data.artifactsConnection[_].node.evidenceConnection[_]]
artifact_evidence := [evidence.node.evidenceConnection.edges[_] | some evidence in input.data.artifactsConnection.edges]
    
# PaC: Ecosystem Attestation Check (NIST PW.5.1)
should_allow := true if {
    # AppTrust checks for attestations from partner tools (SonarQube)
some evidence in artifact_evidence
     evidence.node.predicateType == "https://sonar.com/evidence/sonarqube/v1"
}

explanation := "NIST Violation (PW.5.1): Verified SonarQube analysis results are missing." if {
	should_allow == false
}
allow := {
    "should_allow": should_allow,
    "explanation": explanation
}

 

Step 3: Automating Release Approvals (PW.2.2)

Process-based evidence, such as change management approvals, is often the hardest to track. To satisfy PW.2.2, JFrog AppTrust merges technical results with business processes by automating a check to ensure a ServiceNow Change-Request approval was included in the release bundle. Note: JFrog AppTrust can also trigger workflows to retrieve decisions from ServiceNow automatically when they are made.


package curation.policies
import rego.v1
default should_allow := false
release_evidence := [evidence | some evidence in input.data.evidenceConnection[_]]

# PaC: ServiceNow Process Enforcement
should_allow := true if {
# Check if ServiceNow Change-Request approval evidence was 
	some evidence in release_evidence
     evidence.node.predicateType == "https://servicenow.com/change-approval/v1"
}
explanation := "Governance Block: Final release requires a ServiceNow evidence." if {
should_allow == false
}
allow := {
"should_allow": should_allow,
"explanation": explanation
}

Step 4: Hardening and Build Process Security (PW.6)

Requirement PW.6 is about ensuring the build process uses security flags like ASLR and DEP. JFrog Advanced Security performs binary-level analysis to check if the security features mentioned in PW.6 – such as stack canaries, NX bits, and ASLR – are actually enabled in the final executable, and you can use these checks as a control gate in JFrog AppTrust.

By combining GitHub Provenance, you create a powerful “Code-to-Binary” chain of trust where GitHub provides how the code was built (PS.3.2), while JFrog proves the resulting binary is secure and hardened (PW.6).

To satisfy NIST requirements, you must not only verify that a provenance file exists, but also verify it is signed by the builder and that the builder ID, repository, and git branch match your expectations.


package curation.policies
    import rego.v1
    release := input.data
    release_evidence := [evidence | some evidence in release.evidenceConnection[_]]
    artifact_evidence := [evidence.node.evidenceConnection.edges[_] | some evidence in release.artifactsConnection.edges]
    build_evidence := [evidence.evidenceConnection.edges[_] | some evidence in release.fromBuilds]
    all_layers_evidences := array.concat(release_evidence, array.concat(artifact_evidence, build_evidence))
    
    default exists := false
    
    exists if {
        some predicate in all_layers_evidences        
        startswith(predicate.node.predicateType, input.params.predicateType)
        startswith(predicate.node.predicate.runDetails.builder.id, input.params.GitHubOrg)
        predicate.node.predicate.buildDefinition.internalParameters.github.runner_environment == "github-hosted"
        predicate.node.predicate.buildDefinition.externalParameters.workflow.ref == "refs/heads/main"
        some dependency in predicate.node.predicate.buildDefinition.resolvedDependencies
        startswith(dependency.uri, input.params.codeRepo)
        endswith(dependency.uri, "@refs/heads/main")
    }
        
    allow := {"should_allow": exists}

What are the Benefits of Evidence-Based Governance?

Today’s software supply chains move too fast for manual audits, necessitating a shift toward a system where security is integrated into the binary itself. Transitioning to evidence-based governance provides the granular control required to meet the stringent demands of NIST SSDF framework without stalling development, including:

  • Physical Enforcement: If your specific Rego conditions are not met, releases are physically blocked from promotion.
  • Self-Evident Integrity: You no longer have to hope the process was followed; the artifact carries its own evidence of integrity.
  • Proactive Security Posture: Your organization moves from a reactive, manual posture to automated governance.

By natively embedding these controls into your existing workflows, you eliminate the friction between security and velocity. This architectural shift ensures that your software supply chain is not only compliant by design but also provides documented evidence to comply with emerging industry and governmental regulations.

How JFrog Automates and Simplifies Compliance

JFrog AppTrust moves you away from brittle DIY scripts and pre-defined inflexible templates toward a system that immutably binds evidence from your entire ecosystem to a build in JFrog Artifactory. With JFrog Artifactory as your System of Record, this proof stays with the release as it moves from development to staging to production giving you an audit trail that proves exactly what was built, how it was validated, and why it can be trusted for production.

By moving to a DevGovOps model with JFrog AppTrust, you realize two critical benefits:

  1. Acceleration of  development velocity by removing “stop-and-search” delays
  2. Establishing immutable trust at the artifact, build and release levels.

With JFrog as the trust layer across your software supply chain, achieving NIST SSDF compliance is no longer a monumental task; it is the natural outcome of a properly governed, automated platform.

Ready to automate NIST SSDF compliance? Contact us for a technical deep dive to see how JFrog AppTrust enforces Policy-as-Code and binds verifiable compliance evidence directly to every release.