1+ ---
2+ cases :
3+ # Vulnerable package detection
4+ - note : purlbuiltins/sbom_vulnerable_log4j
5+ query : data.security.sbom.deny = x
6+ modules :
7+ - |
8+ package security.sbom
9+ import rego.v1
10+
11+ vulnerable_packages := [
12+ {"type": "npm", "name": "lodash", "version": "4.17.19"},
13+ {"type": "maven", "namespace": "org.apache.logging.log4j", "name": "log4j-core", "version": "2.14.0"},
14+ {"type": "pypi", "name": "tensorflow", "version": "2.5.0"}
15+ ]
16+
17+ deny contains msg if {
18+ some component in input.components
19+ pkg := purl.parse(component.purl)
20+
21+ some vuln in vulnerable_packages
22+ pkg.type == vuln.type
23+ pkg.name == vuln.name
24+ pkg.namespace == vuln.namespace
25+ pkg.version == vuln.version
26+
27+ msg := sprintf("Vulnerable package detected: %s", [component.purl])
28+ }
29+ data :
30+ input :
31+ components :
32+ -
purl :
" pkg:maven/org.apache.logging.log4j/[email protected] " 33+ -
purl :
" pkg:npm/[email protected] " 34+ want_result :
35+ - x :
36+ -
" Vulnerable package detected: pkg:maven/org.apache.logging.log4j/[email protected] " 37+
38+ # Test non-vulnerable package passes
39+ - note : purlbuiltins/sbom_safe_package
40+ query : data.security.sbom.deny = x
41+ modules :
42+ - |
43+ package security.sbom
44+ import rego.v1
45+
46+ vulnerable_packages := [
47+ {"type": "npm", "name": "lodash", "version": "4.17.19"},
48+ {"type": "maven", "namespace": "org.apache.logging.log4j", "name": "log4j-core", "version": "2.14.0"}
49+ ]
50+
51+ deny contains msg if {
52+ some component in input.components
53+ pkg := purl.parse(component.purl)
54+
55+ some vuln in vulnerable_packages
56+ pkg.type == vuln.type
57+ pkg.name == vuln.name
58+ pkg.namespace == vuln.namespace
59+ pkg.version == vuln.version
60+
61+ msg := sprintf("Vulnerable package detected: %s", [component.purl])
62+ }
63+ data :
64+ input :
65+ components :
66+ -
purl :
" pkg:maven/org.apache.logging.log4j/[email protected] " # Safe version67+ -
purl :
" pkg:npm/[email protected] " 68+ want_result :
69+ - x : []
70+
71+ # Registry policy enforcement
72+ - note : purlbuiltins/registry_policy_violation
73+ query : data.registry.policy.violations = x
74+ modules :
75+ - |
76+ package registry.policy
77+ import rego.v1
78+
79+ allowed_registries := {
80+ "docker": ["docker.io", "gcr.io"]
81+ }
82+
83+ violations contains msg if {
84+ some component in input.components
85+ pkg := purl.parse(component.purl)
86+ pkg.type == "docker"
87+
88+ # Check qualifiers for repository_url
89+ repository := pkg.qualifiers.repository_url
90+ not allowed_registry(repository)
91+
92+ msg := sprintf("Unapproved registry: %s", [repository])
93+ }
94+
95+ allowed_registry(repo) if {
96+ some allowed in allowed_registries.docker
97+ contains(repo, allowed)
98+ }
99+ data :
100+ input :
101+ components :
102+ -
purl :
" pkg:docker/[email protected] ?repository_url=unauthorized.registry.io" 103+ - purl : " pkg:docker/nginx@latest?repository_url=docker.io"
104+ want_result :
105+ - x :
106+ - " Unapproved registry: unauthorized.registry.io"
107+
108+ # License compliance check
109+ - note : purlbuiltins/license_compliance_violation
110+ query : data.compliance.licenses.violations = x
111+ modules :
112+ - |
113+ package compliance.licenses
114+ import rego.v1
115+
116+ prohibited_licenses := {"GPL-3.0", "AGPL-3.0"}
117+
118+ violations contains msg if {
119+ some component in input.components
120+ pkg := purl.parse(component.purl)
121+
122+ some license in component.licenses
123+ license.id in prohibited_licenses
124+
125+ msg := sprintf("Package %s/%s@%s uses prohibited license %s",
126+ [pkg.type, pkg.name, pkg.version, license.id])
127+ }
128+ data :
129+ input :
130+ components :
131+ -
purl :
" pkg:npm/[email protected] " 132+ licenses :
133+ - id : " GPL-3.0"
134+ - id : " MIT"
135+ -
purl :
" pkg:npm/[email protected] " 136+ licenses :
137+ - id : " MIT"
138+ want_result :
139+ - x :
140+ -
" Package npm/[email protected] uses prohibited license GPL-3.0" 141+
142+ # Supply chain verification - missing checksums
143+ - note : purlbuiltins/supply_chain_missing_verification
144+ query : data.supply_chain.require_verification = x
145+ modules :
146+ - |
147+ package supply_chain
148+ import rego.v1
149+
150+ require_verification contains msg if {
151+ some component in input.components
152+ pkg := purl.parse(component.purl)
153+
154+ not component.hashes
155+ not pkg.qualifiers.checksum
156+
157+ msg := sprintf("Package lacks verification: %s", [component.purl])
158+ }
159+ data :
160+ input :
161+ components :
162+ -
purl :
" pkg:npm/[email protected] " 163+ -
purl :
" pkg:npm/[email protected] " 164+ hashes :
165+ - alg : " SHA-256"
166+ content : " abcd1234"
167+ want_result :
168+ - x :
169+ -
" Package lacks verification: pkg:npm/[email protected] " 170+
171+ # High risk packages without namespace
172+ - note : purlbuiltins/high_risk_packages
173+ query : data.supply_chain.high_risk_packages = x
174+ modules :
175+ - |
176+ package supply_chain
177+ import rego.v1
178+
179+ high_risk_packages contains pkg if {
180+ some component in input.components
181+ pkg := purl.parse(component.purl)
182+
183+ pkg.type in {"npm", "pypi", "gem"}
184+ not pkg.namespace
185+ }
186+ data :
187+ input :
188+ components :
189+ -
purl :
" pkg:npm/[email protected] " # No namespace190+ -
purl :
" pkg:npm/@angular/[email protected] " # Has namespace191+ -
purl :
" pkg:pypi/[email protected] " # No namespace192+ want_result :
193+ - x :
194+ - type : " npm"
195+ name : " lodash"
196+ version : " 4.17.21"
197+ - type : " pypi"
198+ name : " requests"
199+ version : " 2.28.0"
0 commit comments