Zero Trust Supply Chain Security: Implementation Framework for Enterprise Software Dependencies
A comprehensive guide to implementing Zero Trust principles for software supply chain security, covering SBOMs, dependency management, and practical implementation phases for enterprises.
Zero Trust Supply Chain Security: Implementation Framework for Enterprise Software Dependencies
Modern enterprises increasingly rely on third-party libraries, open-source packages, and external dependencies to accelerate development. While these dependencies enable faster innovation, they also introduce significant security risks. Attackers have shifted focus from direct exploitation of target systems to compromising upstream software suppliers, creating ripple effects across entire industries. Supply chain attacks bypass traditional perimeter defenses by inserting malicious code or vulnerabilities into trusted components that organizations willingly deploy.
The SolarWinds attack and Log4j vulnerability demonstrated how a single compromised dependency can affect thousands of organizations worldwide. These incidents exposed fundamental weaknesses in how enterprises verify, track, and secure software dependencies throughout the development lifecycle. Traditional security models assume trusted components behind the perimeter, but supply chain attacks originate from within the software supply chain itself. Organizations need a new approach that treats every dependency and build artifact as untrusted until verified.
Zero Trust Principles Applied to Software Supply Chains
Zero Trust architecture, as defined by NIST Special Publication 800-207, operates on the principle of never trusting, always verifying. While traditionally applied to network access and user authentication, these principles translate directly to supply chain security. Each component entering the software lifecycle must be authenticated, authorized, and continuously monitored for suspicious behavior.
Applying Zero Trust to supply chains means treating every external dependency as potentially compromised until proven otherwise. This approach requires visibility into all dependencies, verification of component integrity, and continuous monitoring for newly discovered vulnerabilities. Trust is no longer granted based on reputation or download metrics alone. Instead, cryptographic signatures, vulnerability databases, and security policies determine whether a component is allowed into production environments.
The implementation requires changes across the entire software lifecycle, from initial dependency selection through build and deployment processes. Security controls must be embedded into development workflows rather than applied as a final gate. This shift-left approach reduces the cost and complexity of addressing issues by catching them earlier in the delivery process.
Core Components of a Zero Trust Supply Chain
Software Bill of Materials (SBOM)
An SBOM provides a comprehensive inventory of all software components, libraries, and modules included in an application. Similar to ingredient lists in food packaging, an SBOM enables organizations to quickly identify vulnerable components when new threats emerge. The National Telecommunications and Information Administration established minimum requirements for SBOMs, providing a baseline for industry adoption.
Two widely adopted standards govern SBOM formats: SPDX and CycloneDX. SPDX, managed by the Linux Foundation, provides a flexible format for sharing software package data. CycloneDX, originally developed by OWASP, offers comprehensive capabilities for software supply chain security including vulnerability analysis and license compliance. Both formats enable machine-readable exchange of component information between tools and organizations.
Generating SBOMs at build time creates a reliable record of dependencies actually used in production. Manual dependency inventories quickly become outdated as developers introduce new packages during development. Automated SBOM generation tools scan build artifacts, package managers, and container images to create accurate, up-to-date inventories.
Consider a financial services organization that must demonstrate compliance with federal supply chain security regulations during a quarterly audit. The security team needs to generate SBOMs for all production applications in SPDX format to support compliance reporting. The process scans the container image registry, extracts dependency information from each image, and produces standardized SBOM documents that feed into the organization's vulnerability management platform. This automation enables the team to respond to auditor requests within hours rather than days, while maintaining an accurate record of every component deployed across their microservices infrastructure.
#!/bin/bash
# Usage: ./generate-sbom.sh <image_name>
# Reference: https://github.com/anchore/syft
IMAGE_NAME="${1:-alpine:latest}"
OUTPUT_FILE="sbom.spdx."
# Generate SPDX SBOM in JSON format and save to file
syft "$IMAGE_NAME" -o "spdx-=$OUTPUT_FILE"
Execute the code with caution.
Dependency Verification and Scanning
Software Composition Analysis (SCA) tools scan dependencies against known vulnerability databases, identifying risky components before they enter production. These tools maintain catalogs of published vulnerabilities, including severity ratings and available patches. Integration into CI/CD pipelines enables automated blocking of dependencies containing critical or high-severity vulnerabilities.
Scanning should occur at multiple stages in the development lifecycle. Initial scanning during dependency selection helps developers choose secure alternatives. Build-time scanning captures the actual components included in artifacts. Runtime scanning monitors for newly discovered vulnerabilities after deployment. Each stage provides different insights, and together they create a layered defense.
Effective dependency management extends beyond vulnerability scanning. Organizations need policies governing which sources are acceptable, what versions are permitted, and how updates are approved. Transitive dependencies, or dependencies of dependencies, present additional challenges because they are often invisible to developers but can introduce significant risk.
A healthcare technology company processes millions of patient records through a web application built with hundreds of open-source dependencies. After a major vulnerability disclosure affects a popular JavaScript library, the engineering team must quickly determine whether their application is exposed. The SCA scanner correlates the dependency inventory against the newly published CVE, identifies which microservices include the vulnerable version, and prioritizes remediation based on whether the affected component is present in patient-facing versus internal systems. This rapid assessment enables the team to patch the critical patient-facing services within 24 hours while scheduling maintenance for lower-risk internal applications.
- name: Run Grype vulnerability scanner
uses: anchore/grype-action@v0.15.1
with:
image-ref: ${{ steps.build.outputs.image-name }}:latest
format: sarif
output: grype-results.sarif
severity-cutoff: critical
fail-on-severity: critical
Execute the code with caution.
Code Signing and Artifact Verification
Cryptographic signatures provide strong assurance that software artifacts have not been modified after being signed. Code signing applies digital signatures to binaries, container images, and build outputs. During deployment, systems verify these signatures against trusted keys before executing the code. This practice prevents attackers from replacing legitimate artifacts with malicious versions during transport or storage.
Sigstore provides an open-source framework for signing and verifying software artifacts using transparent logs and certificate authority infrastructure. The project enables developers to sign commits, container images, and build artifacts using integrated tools. Verification can be automated in deployment pipelines to reject unsigned or improperly signed artifacts before production rollout.
Build provenance tracking records the complete history of how an artifact was created, including source code references, build tools, and environment configuration. This information enables security teams to investigate incidents by reconstructing exactly what was built, when it was built, and what inputs were used. Provenance data is particularly valuable for regulatory compliance and post-incident forensics.
A multinational e-commerce platform deploys thousands of container images daily to global data centers serving customer transactions. To ensure integrity of their deployment pipeline, the platform automatically signs every image after the build process completes using organizational signing keys. During deployment to production, the orchestration platform verifies each image's signature against the trusted public key before scheduling it on worker nodes. When an attacker attempts to inject a malicious image into the registry, signature verification fails immediately, preventing unauthorized code from ever executing in the production environment. This cryptographic control provides tamper evidence and ensures that only artifacts built through approved pipelines can reach production infrastructure.
#!/bin/bash
# Sign and verify a container image using Sigstore cosign
# Reference: https://docs.sigstore.dev/cosign/
# Define the image to sign (pass as argument or use placeholder)
IMAGE="${1:-your-image:tag}"
# Prevent interactive password prompt for key generation
export COSIGN_PASSWORD=""
# 1. Generate a key pair (cosign.key, cosign.pub)
cosign generate-key-pair
# 2. Sign the image using the private key
cosign sign --key cosign.key --yes "$IMAGE"
# 3. Verify the image signature using the public key
cosign verify --key cosign.pub "$IMAGE"
Execute the code with caution.
Implementation Framework
Phase 1: Visibility and Inventory
The first phase focuses on understanding what software dependencies exist across the organization. Many enterprises lack comprehensive visibility into open-source usage, particularly in legacy applications and shadow IT projects. Without visibility, any security controls will be incomplete and potentially ineffective.
Begin by conducting dependency audits across all applications and services. Use automated scanning tools to catalog dependencies in production environments. Classify applications by risk level based on public exposure, data sensitivity, and criticality to business operations. This classification enables prioritization of security investments based on the most important assets.
Establish an SBOM generation process integrated into build pipelines. Configure SBOM tools to run automatically for every build, creating consistent records of dependency usage. Store SBOMs in a centralized location where security teams can access them during incident response and vulnerability assessments.
Create a dependency inventory management system to track all approved and prohibited packages. This system should capture package names, versions, sources, and approval status. Development teams should have easy access to this information during dependency selection to make informed decisions.
Phase 2: Policy Definition
With visibility established, the next phase involves creating policies that govern acceptable component usage. Policies provide the rules that automated systems will enforce consistently across the organization. Without clear policies, security controls will appear arbitrary and developers may find ways to bypass them.
Define vulnerability acceptance criteria based on severity, exploitability, and compensating controls. Not all vulnerabilities need to block deployment. Low-severity vulnerabilities in internal-only systems with strong network controls might be acceptable for temporary periods. Conversely, critical vulnerabilities with public exploits should require immediate remediation or deployment blocking.
Establish approval workflows for introducing new dependencies. Small teams should not independently add packages without review, but requiring security approval for every package would create unacceptable delays. Implement tiered approvals where high-risk or uncommon dependencies require additional scrutiny while common, low-risk packages have streamlined approval processes.
Create supplier assessment criteria for commercial software vendors and critical open-source projects. Evaluate vendor security practices, update frequency, and incident response capabilities. For critical infrastructure projects, establish requirements for SBOM delivery, code signing, and vulnerability disclosure processes.
An energy sector enterprise implementing critical infrastructure protection requirements must define policies that govern which software components can be deployed to operational technology systems. The security team develops a policy that prohibits dependencies with critical or high-severity vulnerabilities from being installed in control systems, while allowing temporary exceptions for non-critical vulnerabilities with documented compensating controls. The policy also defines acceptable open-source licenses, prohibits packages from certain geographic regions, and requires additional review for any dependency not present on a pre-approved list. These rules are encoded as policy-as-code and automatically enforced during the build process, ensuring consistent application across all development teams regardless of manual review capacity.
package supply_chain_security
import future.keywords.if
import future.keywords.in
# Deny messages that describe policy violations
deny contains msg if {
violation[msg]
}
# Rule 1: Enforce Vulnerability Severity Thresholds
# Blocks packages with Critical or High severity vulnerabilities
violation[msg] if {
some vuln in input.vulnerabilities
vuln.severity in ["CRITICAL", "HIGH"]
msg := sprintf("Vulnerability severity '%s' is not allowed for package '%s'", [vuln.severity, vuln.package_name])
}
# Rule 2: Enforce Allowed License Types
# Blocks packages with licenses not in the approved list
violation[msg] if {
some pkg in input.packages
not pkg.license_type in ["MIT", "Apache-2.0", "BSD-3-Clause"]
msg := sprintf("License '%s' is not allowed for package '%s'", [pkg.license_type, pkg.name])
}
Execute the code with caution.
Phase 3: Control Implementation
Phase 3 involves deploying automated controls that enforce policies across the software lifecycle. Manual reviews cannot keep pace with modern development velocity, and inconsistency in enforcement creates exploitable gaps. Automation ensures policies are applied consistently and provides audit trails for compliance requirements.
Integrate SCA tools into CI/CD pipelines to block builds containing prohibited or vulnerable dependencies. Configure pipeline gates that fail builds based on configurable severity thresholds. Integration with issue tracking systems automatically creates remediation tickets, streamlining the workflow for developers to address findings.
Implement code signing for all build artifacts. Configure build systems to automatically sign binaries, container images, and packages with organizational keys. Deploy verification steps in production deployment pipelines that reject unsigned or improperly signed artifacts. Consider using cloud provider code signing services to simplify key management and rotation.
Establish runtime monitoring for newly discovered vulnerabilities in production dependencies. Integrate container image scanning and dependency monitoring with cloud-native security platforms. Configure automated alerts when critical vulnerabilities are discovered in running workloads, enabling rapid assessment and remediation decisions.
A cloud-native SaaS company manages a continuous delivery pipeline that processes hundreds of deployments per day across multiple environments. The engineering team implements an automated control system where every build must pass security gates before progressing to the next stage. The pipeline runs SCA scanning, generates an SBOM, signs the artifact, and verifies provenance—all as mandatory steps that cannot be bypassed. When a developer introduces a new dependency with a known critical vulnerability, the pipeline automatically fails, creates a ticket in the issue tracker, and notifies the security team. The developer receives immediate feedback with the vulnerability details and suggested remediation steps, enabling rapid resolution without manual intervention. This automated enforcement ensures consistent security posture regardless of deployment velocity or team size.
name: Secure CI/CD Pipeline
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build-and-scan:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build Application
run: |
echo "Building application..."
# Replace with actual build command (e.g., mvn package, docker build)
docker build . -t myapp:latest
- name: Generate SBOM
id: sbom
run: |
# Using Syft to generate Software Bill of Materials
docker pull anchore/syft
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock anchore/syft myapp:latest -o spdx- > sbom.
- name: SCA Scan
run: |
# Using Trivy for Software Composition Analysis and Vulnerability Scanning
docker pull aquasec/trivy
# Fail pipeline if HIGH or CRITICAL vulnerabilities are found
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v $PWD:/work aquasec/trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:latest
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: security-artifacts
path: |
sbom.
sign-and-deploy:
needs: build-and-scan
runs-on: ubuntu-latest
# Conditional Gate: Only execute on main branch if build-and-scan succeeded
if: github.ref == 'refs/heads/main' && success()
permissions:
contents: write
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download Artifacts
uses: actions/download-artifact@v4
with:
name: security-artifacts
- name: Install Cosign
uses: sigstore/cosign-installer@v3
- name: Sign SBOM
env:
COSIGN_EXPERIMENTAL: "true"
run: |
# Sign the generated SBOM file
cosign sign-blob sbom. --output-signature sbom.sig
- name: Deploy to Production
run: |
echo "Deploying signed artifacts..."
# Add deployment commands here
Execute the code with caution.
Phase 4: Continuous Monitoring and Response
The final phase focuses on ongoing operations, incident response, and continuous improvement. Security controls require constant adjustment as threats evolve and organizations change their technology stacks. Static controls quickly become obsolete without regular review and updates.
Subscribe to vulnerability feeds and security advisories from CISA, NIST, and software vendors. Configure automated correlation between vulnerability announcements and your dependency inventory to quickly identify affected applications. Prioritize remediation based on exploitability, asset criticality, and available mitigations.
Conduct regular security assessments of the supply chain itself. Red team exercises can test whether attackers could introduce malicious components through compromised build systems or supplier accounts. Independent penetration testing of third-party components provides additional assurance, particularly for critical business systems.
Establish incident response procedures specifically for supply chain incidents. Supply chain attacks differ from traditional breaches because they affect trusted components rather than direct compromises. Response plans should include processes for identifying affected applications, coordinating with suppliers, and communicating with stakeholders about impact and remediation timelines.
A federal government agency managing citizen services must maintain continuous awareness of supply chain risks across hundreds of applications. When the CISA Known Exploited Vulnerabilities Catalog is updated with a new entry, the security operations center needs to immediately determine which agency systems are affected and prioritize remediation according to mission impact. The agency's monitoring platform automatically ingests the updated vulnerability feed, correlates CVE identifiers against the centralized SBOM inventory, and generates a prioritized remediation report identifying which applications contain the vulnerable component. The platform also assesses whether affected applications are internet-facing, handle sensitive data, or support critical government functions, enabling the security team to focus immediate response efforts on the highest-risk systems while documenting the analysis chain for audit purposes.
import requests
def get_cve_affected_projects(base_url, api_key, cve_id):
"""Query Dependency-Track API for projects affected by a specific CVE."""
headers = {'X-Api-Key': api_key, 'Accept': 'application/'}
url = f"{base_url}/api/v1/vulnerability"
params = {'vulnId': cve_id}
try:
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
vulnerabilities = response.()
results = []
for vuln in vulnerabilities:
for affected in vuln.get('affectedComponents', []):
project = affected.get('project', {})
component = affected.get('component', {})
info = {
'vulnerability': vuln.get('vulnId'),
'severity': vuln.get('severity'),
'project': project.get('name'),
'component': component.get('name'),
'version': component.get('version')
}
results.append(info)
return results
except requests.exceptions.RequestException as e:
print(f"API error: {e}")
return None
Execute the code with caution.
Industry-Level Project Examples
Beginner: Secure Dependency Management for a Web Application
Implement a comprehensive dependency management system for a web application portfolio. The project integrates SCA scanning into the build pipeline, generates SBOMs for all builds, and establishes a dependency approval workflow. Vulnerability scanning blocks builds with critical or high-severity findings, while lower-severity issues generate tickets for review.
Tech Stack: GitHub Actions, Syft for SBOM generation, Grype for vulnerability scanning, Snyk for dependency analysis, artifact repository for signed packages
Business Value: Reduces vulnerability exposure by identifying risky dependencies before deployment, provides auditable compliance documentation, and enables rapid response to newly discovered vulnerabilities through accurate SBOM records.
Complexity Level: Beginner
Intermediate: Zero Trust Build Pipeline for Microservices
Design and implement a Zero Trust-compliant build pipeline for a microservices architecture. The pipeline automatically signs all build artifacts using Sigstore, verifies provenance for external dependencies, and integrates comprehensive security controls at each stage. Container images are scanned before promotion, and only properly signed artifacts deploy to production environments.
Tech Stack: Jenkins or GitLab CI, Sigstore cosign for signing, Syft and Grype for scanning, Harbor for container registry with notary support, Open Policy Agent for policy enforcement
Business Value: Provides cryptographic assurance of supply chain integrity, prevents unauthorized code modifications, and enables rapid rollback when vulnerabilities are discovered. The implementation supports regulatory requirements for supply chain transparency and accountability.
Complexity Level: Intermediate
Advanced: Enterprise-Wide Supply Chain Security Platform
Build an enterprise platform that provides centralized visibility, policy management, and automated enforcement across all development teams. The platform aggregates SBOMs from multiple build systems, correlates vulnerability data across applications, and provides dashboards for security leadership. Integration with incident management systems automates response workflows for supply chain incidents.
Tech Stack: Kubernetes for platform deployment, Grype and Trivy for scanning, Dependency-Track for SBOM management, PostgreSQL for metadata storage, Grafana for dashboards, API integration with CI/CD tools and cloud security platforms
Business Value: Provides organization-wide visibility into supply chain risk, enables efficient vulnerability response through automated correlation, and reduces security team workload through centralized policy management. The platform supports compliance with federal and industry supply chain security requirements.
Complexity Level: Advanced
Tools and Technologies
SBOM Generation Tools
Syft provides command-line tools for generating SPDX and CycloneDX SBOMs from container images, file systems, and package archives. The tool integrates easily into CI/CD pipelines and supports multiple output formats. Microsoft SBOM Generator offers similar capabilities for Windows environments and integrates with build systems like Azure Pipelines.
A DevOps team managing a hybrid cloud infrastructure needs to generate SBOMs for applications running across both Linux containers and Windows services. The team implements a unified SBOM generation strategy using Syft for container-based applications and Microsoft SBOM Generator for Windows services. The SBOMs are uploaded to a centralized repository where security tools can parse and analyze them for vulnerabilities and license compliance. This cross-platform approach ensures complete inventory coverage regardless of the underlying operating system, supporting the organization's requirement for comprehensive supply chain visibility across all environments.
{
"spdxVersion": "SPDX-2.3",
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "Example-Project-SBOM",
"documentNamespace": "https://example.com/example-project-sbom",
"creationInfo": {
"created": "2023-10-27T12:00:00Z",
"creators": [
"Tool: Formula-Generator"
]
},
"packages": [
{
"SPDXID": "SPDXRef-Package-root",
"name": "example-component",
"versionInfo": "1.0.0",
"downloadLocation": "https://example.com/package.zip",
"filesAnalyzed": false,
"licenseConcluded": "NOASSERTION",
"description": "Root component metadata example",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:npm/example-component@1.0.0"
}
]
},
{
"SPDXID": "SPDXRef-Package-dep",
"name": "example-dependency",
"versionInfo": "2.0.0",
"downloadLocation": "https://example.com/dep.zip",
"filesAnalyzed": false,
"licenseConcluded": "Apache-2.0",
"description": "Dependency component metadata"
}
],
"relationships": [
{
"spdxElementId": "SPDXRef-DOCUMENT",
"relationshipType": "DESCRIBES",
"relatedSpdxElement": "SPDXRef-Package-root"
},
{
"spdxElementId": "SPDXRef-Package-root",
"relationshipType": "DEPENDS_ON",
"relatedSpdxElement": "SPDXRef-Package-dep"
}
]
}
Execute the code with caution.
Vulnerability Scanning
Grype scans container images and filesystems for vulnerabilities using the Grype vulnerability database. It integrates with Syft-generated SBOMs to provide efficient scanning. Trivy offers comprehensive security scanning for container images, file systems, and git repositories, with a focus on ease of integration into DevOps workflows. Snyk provides commercial-grade vulnerability detection with additional features for license compliance and policy enforcement.
Code Signing and Verification
Sigstore provides an open-source toolkit for signing and verifying software artifacts using certificate transparency and Fulcio for certificate authority functions. Cosign handles container image signing and verification, with integration into major container registry platforms. AWS Signer and Azure Code Signing offer managed services for code signing with simplified key management.
SBOM Management and Correlation
OWASP Dependency-Track provides a platform for analyzing component risk across applications. It aggregates SBOMs, correlates vulnerability data, and provides dashboards for risk visualization. The tool supports continuous monitoring and alerting when vulnerabilities affect deployed applications.
Challenges and Considerations
False positives from vulnerability scanners can create alert fatigue and reduce trust in security controls. Not all reported vulnerabilities are exploitable in specific application contexts. Effective implementation requires tuning scanners, understanding actual exploitability, and establishing processes for exempting findings that cannot be exploited.
License compliance represents another significant challenge. Open-source licenses have varying requirements around attribution, modification, and redistribution. Organizations need policies for acceptable licenses and tools to detect license violations before they create legal risks. SBOM tools can capture license information, but interpretation and enforcement require legal expertise.
Legacy applications present particular difficulties for supply chain security. These systems may use outdated dependencies with known vulnerabilities that cannot be easily updated due to compatibility concerns. Organizations must balance security risk against business continuity, implementing compensating controls when immediate remediation is not feasible.
Getting Started
Organizations beginning their supply chain security journey should start with visibility. Before implementing complex controls, understand what dependencies exist across applications. Automated scanning tools can provide baseline data quickly. Use this information to prioritize efforts based on business risk and regulatory requirements.
Select initial tools that integrate easily with existing build systems. Many organizations start with SBOM generation and dependency scanning, as these provide immediate value with minimal disruption. Expand capabilities incrementally as teams gain experience with new processes.
Invest in developer education alongside tool deployment. Supply chain security requires changes to how developers select and manage dependencies. Training on secure coding practices, dependency evaluation, and policy compliance helps create a security-aware culture that supports long-term success.
Sources
- CISA - Supply Chain Risk Management Toolkit: https://www.cisa.gov/resources-tools/resources/supply-chain-risk-management-toolkit
- NIST Special Publication 800-207: Zero Trust Architecture: https://csrc.nist.gov/publications/detail/sp/800-207/final
- NIST Special Publication 800-161: Supply Chain Risk Management Practices for Federal Information Systems: https://csrc.nist.gov/publications/detail/sp/800-161/rev-1/final
- Executive Order on Improving the Nation's Cybersecurity (EO 14028): https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/
- NTIA Minimum Elements for a Software Bill of Materials (SBOM): https://ntia.gov/page/minimum-elements-sbom
- SPDX Documentation: https://spdx.dev/
- CycloneDX Specification: https://cyclonedx.org/
- OWASP Software Supply Chain Attacks: https://owasp.org/www-community/attacks/Software_Supply_Chain_Attacks
- Cloud Native Computing Foundation (CNCF) - Supply Chain Security: https://www.cncf.io/projects/
- CISA - Known Exploited Vulnerabilities Catalog: https://www.cisa.gov/known-exploited-vulnerabilities-catalog