@cyclonedx/cdxgen 12.1.5 → 12.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -40
- package/bin/cdxgen.js +194 -97
- package/bin/evinse.js +4 -4
- package/bin/repl.js +1 -1
- package/bin/sign.js +102 -0
- package/bin/validate.js +233 -0
- package/bin/verify.js +69 -28
- package/data/queries.json +1 -1
- package/data/rules/ci-permissions.yaml +186 -0
- package/data/rules/dependency-sources.yaml +123 -0
- package/data/rules/package-integrity.yaml +135 -0
- package/data/rules/vscode-extensions.yaml +228 -0
- package/lib/cli/index.js +449 -429
- package/lib/cli/index.poku.js +117 -0
- package/lib/evinser/db.js +137 -0
- package/lib/{helpers → evinser}/db.poku.js +2 -6
- package/lib/evinser/evinser.js +2 -14
- package/lib/helpers/analyzer.js +606 -3
- package/lib/helpers/analyzer.poku.js +230 -0
- package/lib/helpers/bomSigner.js +312 -0
- package/lib/helpers/bomSigner.poku.js +156 -0
- package/lib/helpers/ciParsers/azurePipelines.js +295 -0
- package/lib/helpers/ciParsers/azurePipelines.poku.js +253 -0
- package/lib/helpers/ciParsers/circleCi.js +286 -0
- package/lib/helpers/ciParsers/circleCi.poku.js +230 -0
- package/lib/helpers/ciParsers/common.js +24 -0
- package/lib/helpers/ciParsers/githubActions.js +636 -0
- package/lib/helpers/ciParsers/githubActions.poku.js +802 -0
- package/lib/helpers/ciParsers/gitlabCi.js +213 -0
- package/lib/helpers/ciParsers/gitlabCi.poku.js +247 -0
- package/lib/helpers/ciParsers/jenkins.js +181 -0
- package/lib/helpers/ciParsers/jenkins.poku.js +197 -0
- package/lib/helpers/depsUtils.js +219 -0
- package/lib/helpers/depsUtils.poku.js +207 -0
- package/lib/helpers/display.js +426 -5
- package/lib/helpers/envcontext.js +18 -3
- package/lib/helpers/formulationParsers.js +351 -0
- package/lib/helpers/logger.js +14 -0
- package/lib/helpers/protobom.js +9 -9
- package/lib/helpers/pythonutils.js +9 -0
- package/lib/helpers/remote/dependency-track.js +84 -0
- package/lib/helpers/remote/dependency-track.poku.js +119 -0
- package/lib/helpers/table.js +384 -0
- package/lib/helpers/table.poku.js +186 -0
- package/lib/helpers/utils.js +865 -416
- package/lib/helpers/utils.poku.js +172 -265
- package/lib/helpers/versutils.js +202 -0
- package/lib/helpers/versutils.poku.js +315 -0
- package/lib/helpers/vsixutils.js +1061 -0
- package/lib/helpers/vsixutils.poku.js +2247 -0
- package/lib/managers/binary.js +19 -19
- package/lib/managers/docker.js +108 -1
- package/lib/managers/oci.js +10 -0
- package/lib/managers/piptree.js +3 -9
- package/lib/parsers/npmrc.js +17 -13
- package/lib/parsers/npmrc.poku.js +41 -5
- package/lib/server/openapi.yaml +34 -1
- package/lib/server/server.js +50 -13
- package/lib/server/server.poku.js +332 -144
- package/lib/stages/postgen/annotator.js +1 -1
- package/lib/stages/postgen/auditBom.js +196 -0
- package/lib/stages/postgen/auditBom.poku.js +378 -0
- package/lib/stages/postgen/postgen.js +54 -1
- package/lib/stages/postgen/postgen.poku.js +90 -1
- package/lib/stages/postgen/ruleEngine.js +369 -0
- package/lib/stages/pregen/envAudit.js +299 -0
- package/lib/stages/pregen/envAudit.poku.js +572 -0
- package/lib/stages/pregen/pregen.js +12 -8
- package/lib/{helpers/validator.js → validator/bomValidator.js} +107 -47
- package/lib/validator/complianceEngine.js +241 -0
- package/lib/validator/complianceEngine.poku.js +168 -0
- package/lib/validator/complianceRules.js +1610 -0
- package/lib/validator/complianceRules.poku.js +328 -0
- package/lib/validator/index.js +222 -0
- package/lib/validator/index.poku.js +144 -0
- package/lib/validator/reporters/annotations.js +121 -0
- package/lib/validator/reporters/console.js +149 -0
- package/lib/validator/reporters/index.js +41 -0
- package/lib/validator/reporters/json.js +37 -0
- package/lib/validator/reporters/sarif.js +184 -0
- package/lib/validator/reporters.poku.js +150 -0
- package/package.json +8 -9
- package/types/bin/sign.d.ts +3 -0
- package/types/bin/sign.d.ts.map +1 -0
- package/types/bin/validate.d.ts +3 -0
- package/types/bin/validate.d.ts.map +1 -0
- package/types/helpers/utils.d.ts +0 -1
- package/types/lib/cli/index.d.ts +49 -52
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/evinser/db.d.ts +34 -0
- package/types/lib/evinser/db.d.ts.map +1 -0
- package/types/lib/evinser/evinser.d.ts +63 -16
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/helpers/analyzer.d.ts.map +1 -1
- package/types/lib/helpers/bomSigner.d.ts +27 -0
- package/types/lib/helpers/bomSigner.d.ts.map +1 -0
- package/types/lib/helpers/ciParsers/azurePipelines.d.ts +17 -0
- package/types/lib/helpers/ciParsers/azurePipelines.d.ts.map +1 -0
- package/types/lib/helpers/ciParsers/circleCi.d.ts +17 -0
- package/types/lib/helpers/ciParsers/circleCi.d.ts.map +1 -0
- package/types/lib/helpers/ciParsers/common.d.ts +11 -0
- package/types/lib/helpers/ciParsers/common.d.ts.map +1 -0
- package/types/lib/helpers/ciParsers/githubActions.d.ts +34 -0
- package/types/lib/helpers/ciParsers/githubActions.d.ts.map +1 -0
- package/types/lib/helpers/ciParsers/gitlabCi.d.ts +17 -0
- package/types/lib/helpers/ciParsers/gitlabCi.d.ts.map +1 -0
- package/types/lib/helpers/ciParsers/jenkins.d.ts +17 -0
- package/types/lib/helpers/ciParsers/jenkins.d.ts.map +1 -0
- package/types/lib/helpers/depsUtils.d.ts +21 -0
- package/types/lib/helpers/depsUtils.d.ts.map +1 -0
- package/types/lib/helpers/display.d.ts +111 -11
- package/types/lib/helpers/display.d.ts.map +1 -1
- package/types/lib/helpers/envcontext.d.ts +19 -7
- package/types/lib/helpers/envcontext.d.ts.map +1 -1
- package/types/lib/helpers/formulationParsers.d.ts +50 -0
- package/types/lib/helpers/formulationParsers.d.ts.map +1 -0
- package/types/lib/helpers/logger.d.ts +15 -1
- package/types/lib/helpers/logger.d.ts.map +1 -1
- package/types/lib/helpers/protobom.d.ts +2 -2
- package/types/lib/helpers/pythonutils.d.ts +10 -1
- package/types/lib/helpers/pythonutils.d.ts.map +1 -1
- package/types/lib/helpers/remote/dependency-track.d.ts +16 -0
- package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -0
- package/types/lib/helpers/table.d.ts +6 -0
- package/types/lib/helpers/table.d.ts.map +1 -0
- package/types/lib/helpers/utils.d.ts +533 -128
- package/types/lib/helpers/utils.d.ts.map +1 -1
- package/types/lib/helpers/versutils.d.ts +8 -0
- package/types/lib/helpers/versutils.d.ts.map +1 -0
- package/types/lib/helpers/vsixutils.d.ts +130 -0
- package/types/lib/helpers/vsixutils.d.ts.map +1 -0
- package/types/lib/managers/docker.d.ts +12 -31
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/managers/oci.d.ts +11 -1
- package/types/lib/managers/oci.d.ts.map +1 -1
- package/types/lib/managers/piptree.d.ts.map +1 -1
- package/types/lib/parsers/npmrc.d.ts +4 -1
- package/types/lib/parsers/npmrc.d.ts.map +1 -1
- package/types/lib/server/server.d.ts +22 -2
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/auditBom.d.ts +20 -0
- package/types/lib/stages/postgen/auditBom.d.ts.map +1 -0
- package/types/lib/stages/postgen/postgen.d.ts +8 -1
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/postgen/ruleEngine.d.ts +18 -0
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -0
- package/types/lib/stages/pregen/envAudit.d.ts +8 -0
- package/types/lib/stages/pregen/envAudit.d.ts.map +1 -0
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
- package/types/lib/{helpers/validator.d.ts → validator/bomValidator.d.ts} +1 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -0
- package/types/lib/validator/complianceEngine.d.ts +66 -0
- package/types/lib/validator/complianceEngine.d.ts.map +1 -0
- package/types/lib/validator/complianceRules.d.ts +70 -0
- package/types/lib/validator/complianceRules.d.ts.map +1 -0
- package/types/lib/validator/index.d.ts +70 -0
- package/types/lib/validator/index.d.ts.map +1 -0
- package/types/lib/validator/reporters/annotations.d.ts +31 -0
- package/types/lib/validator/reporters/annotations.d.ts.map +1 -0
- package/types/lib/validator/reporters/console.d.ts +30 -0
- package/types/lib/validator/reporters/console.d.ts.map +1 -0
- package/types/lib/validator/reporters/index.d.ts +21 -0
- package/types/lib/validator/reporters/index.d.ts.map +1 -0
- package/types/lib/validator/reporters/json.d.ts +11 -0
- package/types/lib/validator/reporters/json.d.ts.map +1 -0
- package/types/lib/validator/reporters/sarif.d.ts +16 -0
- package/types/lib/validator/reporters/sarif.d.ts.map +1 -0
- package/lib/helpers/db.js +0 -162
- package/lib/stages/pregen/env-audit.js +0 -34
- package/lib/stages/pregen/env-audit.poku.js +0 -290
- package/types/helpers/db.d.ts +0 -35
- package/types/helpers/db.d.ts.map +0 -1
- package/types/lib/helpers/db.d.ts +0 -35
- package/types/lib/helpers/db.d.ts.map +0 -1
- package/types/lib/helpers/validator.d.ts.map +0 -1
- package/types/lib/stages/pregen/env-audit.d.ts +0 -2
- package/types/lib/stages/pregen/env-audit.d.ts.map +0 -1
- package/types/managers/binary.d.ts +0 -37
- package/types/managers/binary.d.ts.map +0 -1
- package/types/managers/docker.d.ts +0 -56
- package/types/managers/docker.d.ts.map +0 -1
- package/types/managers/oci.d.ts +0 -2
- package/types/managers/oci.d.ts.map +0 -1
- package/types/managers/piptree.d.ts +0 -2
- package/types/managers/piptree.d.ts.map +0 -1
- package/types/server/server.d.ts +0 -34
- package/types/server/server.d.ts.map +0 -1
- package/types/stages/postgen/annotator.d.ts +0 -27
- package/types/stages/postgen/annotator.d.ts.map +0 -1
- package/types/stages/postgen/postgen.d.ts +0 -51
- package/types/stages/postgen/postgen.d.ts.map +0 -1
- package/types/stages/pregen/pregen.d.ts +0 -59
- package/types/stages/pregen/pregen.d.ts.map +0 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# CI/CD Permission Security Rules
|
|
2
|
+
# Category: ci-permission
|
|
3
|
+
# Evaluates GitHub Actions, GitLab CI, Azure Pipelines, etc. for privilege risks
|
|
4
|
+
|
|
5
|
+
- id: CI-001
|
|
6
|
+
name: "Unpinned action in write-permission workflow"
|
|
7
|
+
description: "GitHub Actions referenced by tag/branch in workflows with write permissions pose supply chain risk"
|
|
8
|
+
severity: high
|
|
9
|
+
category: ci-permission
|
|
10
|
+
condition: |
|
|
11
|
+
components[
|
|
12
|
+
$prop($, 'cdx:github:action:isShaPinned') = 'false'
|
|
13
|
+
and (
|
|
14
|
+
$prop($, 'cdx:github:workflow:hasWritePermissions') = 'true'
|
|
15
|
+
or $prop($, 'cdx:github:job:hasWritePermissions') = 'true'
|
|
16
|
+
)
|
|
17
|
+
]
|
|
18
|
+
location: |
|
|
19
|
+
{
|
|
20
|
+
"bomRef": $."bom-ref",
|
|
21
|
+
"purl": purl,
|
|
22
|
+
"file": $prop($, 'cdx:github:workflow:file')
|
|
23
|
+
}
|
|
24
|
+
message: "Unpinned GitHub Action '{{ $prop($, 'cdx:github:action:uses') }}' in workflow with write permissions"
|
|
25
|
+
mitigation: "Pin action to full SHA: actions/setup-node@abc123def456..."
|
|
26
|
+
evidence: |
|
|
27
|
+
{
|
|
28
|
+
"pinningType": $prop($, 'cdx:github:action:versionPinningType'),
|
|
29
|
+
"workflowTriggers": $prop($, 'cdx:github:workflow:triggers'),
|
|
30
|
+
"jobName": $prop($, 'cdx:github:job:name')
|
|
31
|
+
}
|
|
32
|
+
- id: CI-002
|
|
33
|
+
name: "OIDC token issuance to non-official action"
|
|
34
|
+
description: "Workflows granting id-token:write to third-party actions may enable token exfiltration"
|
|
35
|
+
severity: high
|
|
36
|
+
category: ci-permission
|
|
37
|
+
condition: |
|
|
38
|
+
components[
|
|
39
|
+
$prop($, 'cdx:github:workflow:hasIdTokenWrite') = 'true'
|
|
40
|
+
and $prop($, 'cdx:actions:isOfficial') = 'false'
|
|
41
|
+
]
|
|
42
|
+
location: |
|
|
43
|
+
{ "bomRef": $."bom-ref", "purl": purl }
|
|
44
|
+
message: "Workflow grants OIDC token access to non-official action '{{ $prop($, 'cdx:github:action:uses') }}'"
|
|
45
|
+
mitigation: "Restrict id-token scope or use only verified/official actions for OIDC operations"
|
|
46
|
+
evidence: |
|
|
47
|
+
{
|
|
48
|
+
"isVerified": $prop($, 'cdx:actions:isVerified'),
|
|
49
|
+
"actionGroup": group
|
|
50
|
+
}
|
|
51
|
+
- id: CI-003
|
|
52
|
+
name: "Action pinned to mutable tag"
|
|
53
|
+
description: "GitHub Actions pinned to tags (vs SHA) can change behavior unexpectedly if tag is moved"
|
|
54
|
+
severity: medium
|
|
55
|
+
category: ci-permission
|
|
56
|
+
condition: |
|
|
57
|
+
components[
|
|
58
|
+
$prop($, 'cdx:github:action:versionPinningType') = 'tag'
|
|
59
|
+
]
|
|
60
|
+
location: |
|
|
61
|
+
{ "bomRef": $."bom-ref", "purl": purl }
|
|
62
|
+
message: "GitHub Action '{{ $prop($, 'cdx:github:action:uses') }}' pinned to mutable tag (not SHA)"
|
|
63
|
+
mitigation: "Consider pinning to full commit SHA for immutability: actions/setup-node@<full-sha>"
|
|
64
|
+
evidence: |
|
|
65
|
+
{
|
|
66
|
+
"currentVersion": version,
|
|
67
|
+
"isOfficial": $prop($, 'cdx:actions:isOfficial')
|
|
68
|
+
}
|
|
69
|
+
- id: CI-004
|
|
70
|
+
name: "Workflow uses pull_request_target trigger"
|
|
71
|
+
description: "pull_request_target can execute code in the context of the base branch, risking secret exposure"
|
|
72
|
+
severity: medium
|
|
73
|
+
category: ci-permission
|
|
74
|
+
# Check workflows (not components) for this trigger pattern
|
|
75
|
+
condition: |
|
|
76
|
+
formulation.workflows[
|
|
77
|
+
$hasProp($, 'cdx:github:workflow:triggers')
|
|
78
|
+
and $nullSafeProp($, 'cdx:github:workflow:triggers') ~> $trim() ~> $contains('pull_request_target')
|
|
79
|
+
]
|
|
80
|
+
location: |
|
|
81
|
+
{
|
|
82
|
+
"bomRef": $."bom-ref",
|
|
83
|
+
"file": $prop($, 'cdx:github:workflow:file')
|
|
84
|
+
}
|
|
85
|
+
message: "Workflow '{{ $prop($, 'cdx:github:workflow:name') }}' uses pull_request_target trigger"
|
|
86
|
+
mitigation: "Ensure workflow does not checkout or run code from the PR head; use pull_request with careful permissions"
|
|
87
|
+
evidence: |
|
|
88
|
+
{
|
|
89
|
+
"triggers": $prop($, 'cdx:github:workflow:triggers'),
|
|
90
|
+
"hasWritePermissions": $prop($, 'cdx:github:workflow:hasWritePermissions')
|
|
91
|
+
}
|
|
92
|
+
- id: CI-005
|
|
93
|
+
name: "Checkout step persists credentials unnecessarily"
|
|
94
|
+
description: "actions/checkout with persist-credentials=true (default) exposes GITHUB_TOKEN to subsequent steps"
|
|
95
|
+
severity: medium
|
|
96
|
+
category: ci-permission
|
|
97
|
+
condition: |
|
|
98
|
+
components[
|
|
99
|
+
$contains($nullSafeProp($, 'cdx:github:action:uses'), 'actions/checkout')
|
|
100
|
+
and $propBool($, 'cdx:github:checkout:persistCredentials') != false
|
|
101
|
+
and (
|
|
102
|
+
$propBool($, 'cdx:github:workflow:hasWritePermissions') = true
|
|
103
|
+
or $propBool($, 'cdx:github:job:hasWritePermissions') = true
|
|
104
|
+
)
|
|
105
|
+
]
|
|
106
|
+
location: |
|
|
107
|
+
{
|
|
108
|
+
"bomRef": $."bom-ref",
|
|
109
|
+
"purl": purl,
|
|
110
|
+
"file": $prop($, 'cdx:github:workflow:file')
|
|
111
|
+
}
|
|
112
|
+
message: "Checkout step uses persist-credentials=true in privileged workflow; consider persist-credentials: false;"
|
|
113
|
+
mitigation: "Add persist-credentials: false to checkout steps that don't require git push operations"
|
|
114
|
+
evidence: |
|
|
115
|
+
{
|
|
116
|
+
"persistCredentials": $prop($, 'cdx:github:checkout:persistCredentials'),
|
|
117
|
+
"workflowPermissions": $prop($, 'cdx:github:workflow:hasWritePermissions')
|
|
118
|
+
}
|
|
119
|
+
- id: CI-006
|
|
120
|
+
name: "Cache usage in untrusted trigger context"
|
|
121
|
+
description: "GitHub Actions cache can be poisoned when used in workflows triggered by untrusted input (e.g., pull_request from forks)"
|
|
122
|
+
severity: high
|
|
123
|
+
category: ci-permission
|
|
124
|
+
condition: |
|
|
125
|
+
components[
|
|
126
|
+
$nullSafeProp($, 'cdx:github:action:uses') ~> $contains('actions/cache')
|
|
127
|
+
and $nullSafeProp($, 'cdx:github:workflow:triggers') ~> $contains('pull_request')
|
|
128
|
+
]
|
|
129
|
+
location: |
|
|
130
|
+
{
|
|
131
|
+
"bomRef": $."bom-ref",
|
|
132
|
+
"purl": purl,
|
|
133
|
+
"file": $prop($, 'cdx:github:workflow:file')
|
|
134
|
+
}
|
|
135
|
+
message: "Cache action used in pull_request-triggered workflow; cache key '{{ $prop($, 'cdx:github:cache:key') }}' may be writable by untrusted code"
|
|
136
|
+
mitigation: "Scope cache keys to PR-specific values, validate restored cache contents, or avoid caching in untrusted workflows"
|
|
137
|
+
evidence: |
|
|
138
|
+
{
|
|
139
|
+
"cacheKey": $prop($, 'cdx:github:cache:key'),
|
|
140
|
+
"cachePath": $prop($, 'cdx:github:cache:path'),
|
|
141
|
+
"triggers": $prop($, 'cdx:github:workflow:triggers')
|
|
142
|
+
}
|
|
143
|
+
- id: CI-007
|
|
144
|
+
name: "Script injection via untrusted context interpolation"
|
|
145
|
+
description: "Direct interpolation of github.event.* or inputs.* into run: blocks enables command injection"
|
|
146
|
+
severity: critical
|
|
147
|
+
category: ci-permission
|
|
148
|
+
condition: |
|
|
149
|
+
formulation.components[
|
|
150
|
+
$prop($, 'cdx:github:step:hasUntrustedInterpolation') = 'true'
|
|
151
|
+
and $prop($, 'cdx:github:step:type') = 'run'
|
|
152
|
+
]
|
|
153
|
+
location: |
|
|
154
|
+
{
|
|
155
|
+
"bomRef": $."bom-ref",
|
|
156
|
+
"file": $prop($, 'cdx:github:workflow:file')
|
|
157
|
+
}
|
|
158
|
+
message: "Untrusted input interpolated into shell command: variables '{{ $prop($, 'cdx:github:step:interpolatedVars') }}'"
|
|
159
|
+
mitigation: "Use intermediate environment variables: env: TITLE: ${{ github.event.pull_request.title }} then reference $TITLE in run:"
|
|
160
|
+
evidence: |
|
|
161
|
+
{
|
|
162
|
+
"interpolatedVars": $prop($, 'cdx:github:step:interpolatedVars'),
|
|
163
|
+
"stepCommand": $prop($, 'cdx:github:step:command')
|
|
164
|
+
}
|
|
165
|
+
- id: CI-008
|
|
166
|
+
name: "High-risk trigger with write permissions"
|
|
167
|
+
description: "Triggers like pull_request_target, issue_comment, or workflow_run combined with write permissions enable privilege escalation"
|
|
168
|
+
severity: high
|
|
169
|
+
category: ci-permission
|
|
170
|
+
condition: |
|
|
171
|
+
formulation.workflows[
|
|
172
|
+
$prop($, 'cdx:github:workflow:hasHighRiskTrigger') = 'true'
|
|
173
|
+
and $prop($, 'cdx:github:workflow:hasWritePermissions') = 'true'
|
|
174
|
+
]
|
|
175
|
+
location: |
|
|
176
|
+
{
|
|
177
|
+
"bomRef": $."bom-ref",
|
|
178
|
+
"file": $prop($, 'cdx:github:workflow:file')
|
|
179
|
+
}
|
|
180
|
+
message: "Workflow '{{ $prop($, 'cdx:github:workflow:name') }}' uses high-risk trigger with write permissions"
|
|
181
|
+
mitigation: "Use pull_request instead of pull_request_target; require manual approval for issue_comment triggers; restrict permissions per job"
|
|
182
|
+
evidence: |
|
|
183
|
+
{
|
|
184
|
+
"triggers": $prop($, 'cdx:github:workflow:triggers'),
|
|
185
|
+
"hasWritePermissions": $prop($, 'cdx:github:workflow:hasWritePermissions')
|
|
186
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Dependency Source Integrity Rules
|
|
2
|
+
# Category: dependency-source
|
|
3
|
+
# Evaluates package manager data for non-registry, local, or mutable sources
|
|
4
|
+
- id: PKG-001
|
|
5
|
+
name: "Install script from non-registry source"
|
|
6
|
+
description: "npm packages with install scripts from git/file/local sources increase supply chain attack surface"
|
|
7
|
+
severity: high
|
|
8
|
+
category: dependency-source
|
|
9
|
+
condition: |
|
|
10
|
+
components[
|
|
11
|
+
$prop($, 'cdx:npm:hasInstallScript') = 'true'
|
|
12
|
+
and $prop($, 'cdx:npm:isRegistryDependency') = 'false'
|
|
13
|
+
]
|
|
14
|
+
location: |
|
|
15
|
+
{ "bomRef": $."bom-ref", "purl": purl }
|
|
16
|
+
message: "npm package '{{ name }}@{{ version }}' executes install script from non-registry source"
|
|
17
|
+
mitigation: "Avoid git/file dependencies with lifecycle hooks; use registry dependencies or vendor explicitly"
|
|
18
|
+
evidence: |
|
|
19
|
+
{
|
|
20
|
+
"riskyScripts": $prop($, 'cdx:npm:risky_scripts'),
|
|
21
|
+
"resolvedPath": $prop($, 'cdx:npm:resolvedPath'),
|
|
22
|
+
"isLink": $prop($, 'cdx:npm:isLink')
|
|
23
|
+
}
|
|
24
|
+
- id: PKG-002
|
|
25
|
+
name: "Go module uses local replacement"
|
|
26
|
+
description: "Go modules with local_dir replacements are non-hermetic and may not be reproducible"
|
|
27
|
+
severity: high
|
|
28
|
+
category: dependency-source
|
|
29
|
+
condition: |
|
|
30
|
+
components[
|
|
31
|
+
$hasProp($, 'cdx:go:local_dir')
|
|
32
|
+
]
|
|
33
|
+
location: |
|
|
34
|
+
{ "bomRef": $."bom-ref", "purl": purl }
|
|
35
|
+
message: "Go module '{{ name }}' uses local replacement: {{ $prop($, 'cdx:go:local_dir') }}"
|
|
36
|
+
mitigation: "Use published module versions or vendor dependencies explicitly for reproducible builds"
|
|
37
|
+
evidence: |
|
|
38
|
+
{
|
|
39
|
+
"localDir": $prop($, 'cdx:go:local_dir'),
|
|
40
|
+
"toolchain": $prop($, 'cdx:go:toolchain')
|
|
41
|
+
}
|
|
42
|
+
- id: PKG-003
|
|
43
|
+
name: "Swift local checkout in build"
|
|
44
|
+
description: "Swift packages with localCheckoutPath indicate developer-only dependencies not suitable for release"
|
|
45
|
+
severity: high
|
|
46
|
+
category: dependency-source
|
|
47
|
+
condition: |
|
|
48
|
+
components[
|
|
49
|
+
$hasProp($, 'cdx:swift:localCheckoutPath')
|
|
50
|
+
]
|
|
51
|
+
location: |
|
|
52
|
+
{ "bomRef": $."bom-ref", "purl": purl }
|
|
53
|
+
message: "Swift package '{{ name }}' uses local checkout: {{ $prop($, 'cdx:swift:localCheckoutPath') }}"
|
|
54
|
+
mitigation: "Use remote package references (URL or registry) for release artifacts"
|
|
55
|
+
evidence: |
|
|
56
|
+
{
|
|
57
|
+
"checkoutPath": $prop($, 'cdx:swift:localCheckoutPath'),
|
|
58
|
+
"packageName": $prop($, 'cdx:swift:packageName')
|
|
59
|
+
}
|
|
60
|
+
- id: PKG-004
|
|
61
|
+
name: "Nix flake missing reproducibility metadata"
|
|
62
|
+
description: "Nix dependencies without revision or nar_hash cannot be verified for content integrity"
|
|
63
|
+
severity: high
|
|
64
|
+
category: dependency-source
|
|
65
|
+
condition: |
|
|
66
|
+
components[
|
|
67
|
+
$startsWith(purl, 'pkg:nix/')
|
|
68
|
+
and (
|
|
69
|
+
$prop($, 'cdx:nix:revision') = null
|
|
70
|
+
or $prop($, 'cdx:nix:nar_hash') = null
|
|
71
|
+
)
|
|
72
|
+
]
|
|
73
|
+
location: |
|
|
74
|
+
{ "bomRef": $."bom-ref", "purl": purl }
|
|
75
|
+
message: "Nix package '{{ name }}' missing reproducibility metadata (revision or nar_hash)"
|
|
76
|
+
mitigation: "Ensure flake.lock includes both revision and nar_hash for content-addressed reproducibility"
|
|
77
|
+
evidence: |
|
|
78
|
+
{
|
|
79
|
+
"inputUrl": $prop($, 'cdx:nix:input_url'),
|
|
80
|
+
"ref": $prop($, 'cdx:nix:ref'),
|
|
81
|
+
"hasRevision": $hasProp($, 'cdx:nix:revision'),
|
|
82
|
+
"hasNarHash": $hasProp($, 'cdx:nix:nar_hash')
|
|
83
|
+
}
|
|
84
|
+
- id: PKG-005
|
|
85
|
+
name: "Ruby gem tracks mutable branch"
|
|
86
|
+
description: "Ruby gems sourced from git branches (without revision pin) can change unexpectedly"
|
|
87
|
+
severity: medium
|
|
88
|
+
category: dependency-source
|
|
89
|
+
condition: |
|
|
90
|
+
components[
|
|
91
|
+
$hasProp($, 'cdx:gem:remoteBranch')
|
|
92
|
+
and $hasProp($, 'cdx:gem:remoteRevision')
|
|
93
|
+
]
|
|
94
|
+
location: |
|
|
95
|
+
{ "bomRef": $."bom-ref", "purl": purl }
|
|
96
|
+
message: "Ruby gem '{{ name }}' tracks mutable branch '{{ $prop($, 'cdx:gem:remoteBranch') }}' without commit pin"
|
|
97
|
+
mitigation: "Pin to specific revision: gem 'foo', git: '...', ref: '<commit-sha>'"
|
|
98
|
+
evidence: |
|
|
99
|
+
{
|
|
100
|
+
"remote": $prop($, 'cdx:gem:remote'),
|
|
101
|
+
"branch": $prop($, 'cdx:gem:remoteBranch'),
|
|
102
|
+
"tag": $prop($, 'cdx:gem:remoteTag')
|
|
103
|
+
}
|
|
104
|
+
- id: PKG-006
|
|
105
|
+
name: "Python dependency from non-approved registry"
|
|
106
|
+
description: "PyPI packages from unapproved registries may introduce unvetted code"
|
|
107
|
+
severity: low
|
|
108
|
+
category: dependency-source
|
|
109
|
+
condition: |
|
|
110
|
+
components[
|
|
111
|
+
$hasProp($, 'cdx:pypi:registry')
|
|
112
|
+
and $prop($, 'cdx:pypi:registry') != 'https://pypi.org/simple'
|
|
113
|
+
and $prop($, 'cdx:pypi:registry') != 'https://pypi.org'
|
|
114
|
+
]
|
|
115
|
+
location: |
|
|
116
|
+
{ "bomRef": $."bom-ref", "purl": purl }
|
|
117
|
+
message: "Python package '{{ name }}' sourced from non-default registry: {{ $prop($, 'cdx:pypi:registry') }}"
|
|
118
|
+
mitigation: "Verify registry trustworthiness"
|
|
119
|
+
evidence: |
|
|
120
|
+
{
|
|
121
|
+
"registry": $prop($, 'cdx:pypi:registry'),
|
|
122
|
+
"resolvedFrom": $prop($, 'cdx:pypi:resolved_from')
|
|
123
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Package Integrity and Lifecycle Rules
|
|
2
|
+
# Category: package-integrity
|
|
3
|
+
# Detects deprecated, yanked, or tampered packages and suspicious metadata
|
|
4
|
+
|
|
5
|
+
- id: INT-001
|
|
6
|
+
name: "npm package with install script"
|
|
7
|
+
description: "npm packages with lifecycle hooks (preinstall, postinstall, etc.) execute arbitrary code during installation"
|
|
8
|
+
severity: medium
|
|
9
|
+
category: package-integrity
|
|
10
|
+
condition: |
|
|
11
|
+
components[
|
|
12
|
+
$prop($, 'cdx:npm:hasInstallScript') = 'true'
|
|
13
|
+
]
|
|
14
|
+
location: |
|
|
15
|
+
{ "bomRef": $."bom-ref", "purl": purl }
|
|
16
|
+
message: "npm package '{{ name }}@{{ version }}' has install-time execution hooks"
|
|
17
|
+
mitigation: "Review install scripts before use. Consider using --ignore-scripts or an allowlist-based approach"
|
|
18
|
+
evidence: |
|
|
19
|
+
{
|
|
20
|
+
"riskyScripts": $prop($, 'cdx:npm:risky_scripts'),
|
|
21
|
+
"isRegistryDependency": $prop($, 'cdx:npm:isRegistryDependency')
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
- id: INT-002
|
|
25
|
+
name: "npm package name or version mismatch"
|
|
26
|
+
description: "Detected mismatch between expected and resolved package name or version, which may indicate dependency confusion or tampering"
|
|
27
|
+
severity: high
|
|
28
|
+
category: package-integrity
|
|
29
|
+
condition: |
|
|
30
|
+
components[
|
|
31
|
+
$hasProp($, 'cdx:npm:nameMismatchError')
|
|
32
|
+
or $hasProp($, 'cdx:npm:versionMismatchError')
|
|
33
|
+
]
|
|
34
|
+
location: |
|
|
35
|
+
{ "bomRef": $."bom-ref", "purl": purl }
|
|
36
|
+
message: "npm package '{{ name }}@{{ version }}' has a name or version mismatch"
|
|
37
|
+
mitigation: "Investigate the mismatch immediately. This may indicate dependency confusion, registry tampering, or a corrupted lockfile"
|
|
38
|
+
evidence: |
|
|
39
|
+
{
|
|
40
|
+
"nameMismatch": $prop($, 'cdx:npm:nameMismatchError'),
|
|
41
|
+
"versionMismatch": $prop($, 'cdx:npm:versionMismatchError')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
- id: INT-003
|
|
45
|
+
name: "Deprecated Go module"
|
|
46
|
+
description: "Go modules marked as deprecated may contain known issues or be abandoned"
|
|
47
|
+
severity: medium
|
|
48
|
+
category: package-integrity
|
|
49
|
+
condition: |
|
|
50
|
+
components[
|
|
51
|
+
$hasProp($, 'cdx:go:deprecated')
|
|
52
|
+
]
|
|
53
|
+
location: |
|
|
54
|
+
{ "bomRef": $."bom-ref", "purl": purl }
|
|
55
|
+
message: "Go module '{{ name }}' is deprecated: {{ $prop($, 'cdx:go:deprecated') }}"
|
|
56
|
+
mitigation: "Migrate to the recommended replacement module or assess continued usage risk"
|
|
57
|
+
evidence: |
|
|
58
|
+
{
|
|
59
|
+
"deprecationNotice": $prop($, 'cdx:go:deprecated'),
|
|
60
|
+
"isIndirect": $prop($, 'cdx:go:indirect')
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
- id: INT-004
|
|
64
|
+
name: "Yanked Ruby gem in dependency tree"
|
|
65
|
+
description: "Yanked gems have been removed from RubyGems, typically due to security issues or critical bugs"
|
|
66
|
+
severity: high
|
|
67
|
+
category: package-integrity
|
|
68
|
+
condition: |
|
|
69
|
+
components[
|
|
70
|
+
$prop($, 'cdx:gem:yanked') = 'true'
|
|
71
|
+
]
|
|
72
|
+
location: |
|
|
73
|
+
{ "bomRef": $."bom-ref", "purl": purl }
|
|
74
|
+
message: "Ruby gem '{{ name }}@{{ version }}' has been yanked from RubyGems"
|
|
75
|
+
mitigation: "Update to a non-yanked version immediately. Yanked gems are typically removed due to security or correctness issues"
|
|
76
|
+
evidence: |
|
|
77
|
+
{
|
|
78
|
+
"platform": $prop($, 'cdx:gem:platform'),
|
|
79
|
+
"isPrerelease": $prop($, 'cdx:gem:prerelease')
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
- id: INT-005
|
|
83
|
+
name: "npm deprecated package"
|
|
84
|
+
description: "npm packages marked as deprecated may have known vulnerabilities or unmaintained code"
|
|
85
|
+
severity: low
|
|
86
|
+
category: package-integrity
|
|
87
|
+
condition: |
|
|
88
|
+
components[
|
|
89
|
+
$prop($, 'cdx:npm:deprecated') = 'true'
|
|
90
|
+
]
|
|
91
|
+
location: |
|
|
92
|
+
{ "bomRef": $."bom-ref", "purl": purl }
|
|
93
|
+
message: "npm package '{{ name }}@{{ version }}' is deprecated: {{ $prop($, 'cdx:npm:deprecation_notice') }}"
|
|
94
|
+
mitigation: "Migrate to a maintained alternative package"
|
|
95
|
+
evidence: |
|
|
96
|
+
{
|
|
97
|
+
"deprecationNotice": $prop($, 'cdx:npm:deprecation_notice')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
- id: INT-006
|
|
101
|
+
name: "Dart pub uses non-default registry"
|
|
102
|
+
description: "Dart packages from non-default registries may introduce unvetted code"
|
|
103
|
+
severity: low
|
|
104
|
+
category: package-integrity
|
|
105
|
+
condition: |
|
|
106
|
+
components[
|
|
107
|
+
$hasProp($, 'cdx:pub:registry')
|
|
108
|
+
]
|
|
109
|
+
location: |
|
|
110
|
+
{ "bomRef": $."bom-ref", "purl": purl }
|
|
111
|
+
message: "Dart package '{{ name }}' sourced from non-default registry: {{ $prop($, 'cdx:pub:registry') }}"
|
|
112
|
+
mitigation: "Verify registry trustworthiness"
|
|
113
|
+
evidence: |
|
|
114
|
+
{
|
|
115
|
+
"registry": $prop($, 'cdx:pub:registry')
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
- id: INT-007
|
|
119
|
+
name: "Maven shaded/relocated package"
|
|
120
|
+
description: "Maven packages with shaded or relocated classes may obscure the true dependency graph and introduce hidden vulnerabilities"
|
|
121
|
+
severity: low
|
|
122
|
+
category: package-integrity
|
|
123
|
+
condition: |
|
|
124
|
+
components[
|
|
125
|
+
$prop($, 'cdx:maven:shaded') = 'true'
|
|
126
|
+
]
|
|
127
|
+
location: |
|
|
128
|
+
{ "bomRef": $."bom-ref", "purl": purl }
|
|
129
|
+
message: "Maven package '{{ name }}@{{ version }}' contains shaded/relocated classes"
|
|
130
|
+
mitigation: "Prefer non-shaded dependency variants where available to maintain transparent dependency resolution"
|
|
131
|
+
evidence: |
|
|
132
|
+
{
|
|
133
|
+
"unshadedNamespaces": $prop($, 'cdx:maven:unshadedNamespaces'),
|
|
134
|
+
"scope": $prop($, 'cdx:maven:component_scope')
|
|
135
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# VS Code Extension Security Rules
|
|
2
|
+
# Category: vscode-extension
|
|
3
|
+
# Evaluates VS Code extensions for install-time execution, host access, and workspace trust risks
|
|
4
|
+
|
|
5
|
+
- id: VSC-001
|
|
6
|
+
name: "Extension with install-time lifecycle scripts"
|
|
7
|
+
description: "VS Code extensions with postinstall/preinstall scripts execute arbitrary code during installation"
|
|
8
|
+
severity: critical
|
|
9
|
+
category: vscode-extension
|
|
10
|
+
condition: |
|
|
11
|
+
components[
|
|
12
|
+
$startsWith(purl, 'pkg:vscode-extension/')
|
|
13
|
+
and $hasProp($, 'cdx:vscode-extension:lifecycleScripts')
|
|
14
|
+
]
|
|
15
|
+
location: |
|
|
16
|
+
{
|
|
17
|
+
"bomRef": $. "bom-ref",
|
|
18
|
+
"purl": purl,
|
|
19
|
+
"srcFile": $prop($, 'SrcFile')
|
|
20
|
+
}
|
|
21
|
+
message: "VS Code extension '{{ publisher }}.{{ name }}@{{ version }}' executes lifecycle scripts: {{ $prop($, 'cdx:vscode-extension:lifecycleScripts') }}"
|
|
22
|
+
mitigation: "Review extension source code before installation; prefer extensions without install-time scripts; use workspace trust boundaries"
|
|
23
|
+
evidence: |
|
|
24
|
+
{
|
|
25
|
+
"lifecycleScripts": $prop($, 'cdx:vscode-extension:lifecycleScripts'),
|
|
26
|
+
"mainEntryPoint": $prop($, 'cdx:vscode-extension:main'),
|
|
27
|
+
"browserEntryPoint": $prop($, 'cdx:vscode-extension:browser')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
- id: VSC-002
|
|
31
|
+
name: "Always-on extension with terminal access"
|
|
32
|
+
description: "Extensions activating on '*' with terminal-access contribution can execute commands in any workspace"
|
|
33
|
+
severity: high
|
|
34
|
+
category: vscode-extension
|
|
35
|
+
condition: |
|
|
36
|
+
components[
|
|
37
|
+
$startsWith(purl, 'pkg:vscode-extension/')
|
|
38
|
+
and $listContains($propList($, 'cdx:vscode-extension:activationEvents'), '*')
|
|
39
|
+
and $listContains($propList($, 'cdx:vscode-extension:contributes'), 'terminal-access')
|
|
40
|
+
]
|
|
41
|
+
location: |
|
|
42
|
+
{
|
|
43
|
+
"bomRef": $. "bom-ref",
|
|
44
|
+
"purl": purl
|
|
45
|
+
}
|
|
46
|
+
message: "Always-on VS Code extension '{{ publisher }}.{{ name }}' has terminal access capability"
|
|
47
|
+
mitigation: "Disable extension in untrusted workspaces; review contributed commands for injection risks; restrict via workspace trust settings"
|
|
48
|
+
evidence: |
|
|
49
|
+
{
|
|
50
|
+
"activationEvents": $prop($, 'cdx:vscode-extension:activationEvents'),
|
|
51
|
+
"contributes": $prop($, 'cdx:vscode-extension:contributes'),
|
|
52
|
+
"extensionKind": $prop($, 'cdx:vscode-extension:extensionKind')
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
- id: VSC-003
|
|
56
|
+
name: "Extension runs in untrusted workspaces with filesystem access"
|
|
57
|
+
description: "Extensions supporting untrustedWorkspaces=true with filesystem-provider contributions may access sensitive files"
|
|
58
|
+
severity: high
|
|
59
|
+
category: vscode-extension
|
|
60
|
+
condition: |
|
|
61
|
+
components[
|
|
62
|
+
$startsWith(purl, 'pkg:vscode-extension/')
|
|
63
|
+
and $propBool($, 'cdx:vscode-extension:untrustedWorkspaces') = true
|
|
64
|
+
and $listContains($propList($, 'cdx:vscode-extension:contributes'), 'filesystem-provider')
|
|
65
|
+
]
|
|
66
|
+
location: |
|
|
67
|
+
{
|
|
68
|
+
"bomRef": $. "bom-ref",
|
|
69
|
+
"purl": purl
|
|
70
|
+
}
|
|
71
|
+
message: "VS Code extension '{{ publisher }}.{{ name }}' operates in untrusted workspaces with filesystem access"
|
|
72
|
+
mitigation: "Set workspace trust to 'limited' for this extension; audit filesystem-provider implementations; avoid using in sensitive projects"
|
|
73
|
+
evidence: |
|
|
74
|
+
{
|
|
75
|
+
"untrustedWorkspaces": $prop($, 'cdx:vscode-extension:untrustedWorkspaces'),
|
|
76
|
+
"contributes": $prop($, 'cdx:vscode-extension:contributes'),
|
|
77
|
+
"virtualWorkspaces": $prop($, 'cdx:vscode-extension:virtualWorkspaces')
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
- id: VSC-004
|
|
81
|
+
name: "Extension pack with risky member extensions"
|
|
82
|
+
description: "Extension packs implicitly install bundled extensions; flag packs containing members with lifecycle scripts or privileged capabilities"
|
|
83
|
+
severity: medium
|
|
84
|
+
category: vscode-extension
|
|
85
|
+
condition: |
|
|
86
|
+
components[
|
|
87
|
+
$startsWith(purl, 'pkg:vscode-extension/')
|
|
88
|
+
and $hasProp($, 'cdx:vscode-extension:extensionPack')
|
|
89
|
+
]
|
|
90
|
+
location: |
|
|
91
|
+
{
|
|
92
|
+
"bomRef": $. "bom-ref",
|
|
93
|
+
"purl": purl
|
|
94
|
+
}
|
|
95
|
+
message: "VS Code extension pack '{{ publisher }}.{{ name }}' bundles extensions: {{ $prop($, 'cdx:vscode-extension:extensionPack') }}"
|
|
96
|
+
mitigation: "Review each bundled extension individually; prefer installing extensions explicitly rather than via packs"
|
|
97
|
+
evidence: |
|
|
98
|
+
{
|
|
99
|
+
"extensionPack": $prop($, 'cdx:vscode-extension:extensionPack'),
|
|
100
|
+
"extensionDependencies": $prop($, 'cdx:vscode-extension:extensionDependencies')
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
- id: VSC-005
|
|
104
|
+
name: "Extension dependency chain with execution risk"
|
|
105
|
+
description: "Extensions depending on other extensions inherit their trust boundary; flag chains where dependencies have install scripts or privileged access"
|
|
106
|
+
severity: medium
|
|
107
|
+
category: vscode-extension
|
|
108
|
+
condition: |
|
|
109
|
+
components[
|
|
110
|
+
$startsWith(purl, 'pkg:vscode-extension/')
|
|
111
|
+
and $hasProp($, 'cdx:vscode-extension:extensionDependencies')
|
|
112
|
+
]
|
|
113
|
+
location: |
|
|
114
|
+
{
|
|
115
|
+
"bomRef": $. "bom-ref",
|
|
116
|
+
"purl": purl
|
|
117
|
+
}
|
|
118
|
+
message: "VS Code extension '{{ publisher }}.{{ name }}' depends on extensions: {{ $prop($, 'cdx:vscode-extension:extensionDependencies') }}"
|
|
119
|
+
mitigation: "Audit all dependency extensions for lifecycle scripts and privileged contributions; prefer extensions with minimal dependency chains"
|
|
120
|
+
evidence: |
|
|
121
|
+
{
|
|
122
|
+
"extensionDependencies": $prop($, 'cdx:vscode-extension:extensionDependencies'),
|
|
123
|
+
"lifecycleScripts": $prop($, 'cdx:vscode-extension:lifecycleScripts')
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
- id: VSC-006
|
|
127
|
+
name: "Extension with debugger or authentication provider contributions"
|
|
128
|
+
description: "Extensions contributing debuggers or authentication providers have elevated host access and credential handling capabilities"
|
|
129
|
+
severity: high
|
|
130
|
+
category: vscode-extension
|
|
131
|
+
condition: |
|
|
132
|
+
components[
|
|
133
|
+
$startsWith(purl, 'pkg:vscode-extension/')
|
|
134
|
+
and (
|
|
135
|
+
$listContains($propList($, 'cdx:vscode-extension:contributes'), 'debuggers')
|
|
136
|
+
or $listContains($propList($, 'cdx:vscode-extension:contributes'), 'authentication-provider')
|
|
137
|
+
)
|
|
138
|
+
]
|
|
139
|
+
location: |
|
|
140
|
+
{
|
|
141
|
+
"bomRef": $. "bom-ref",
|
|
142
|
+
"purl": purl
|
|
143
|
+
}
|
|
144
|
+
message: "VS Code extension '{{ publisher }}.{{ name }}' contributes privileged capabilities: {{ $prop($, 'cdx:vscode-extension:contributes') }}"
|
|
145
|
+
mitigation: "Review extension source for credential handling; restrict to trusted workspaces; audit debugger attach permissions"
|
|
146
|
+
evidence: |
|
|
147
|
+
{
|
|
148
|
+
"contributes": $prop($, 'cdx:vscode-extension:contributes'),
|
|
149
|
+
"executesCode": $prop($, 'cdx:vscode-extension:executesCode'),
|
|
150
|
+
"extensionKind": $prop($, 'cdx:vscode-extension:extensionKind')
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
- id: VSC-007
|
|
154
|
+
name: "Extension running in workspace context with code execution"
|
|
155
|
+
description: "Extensions with extensionKind=workspace and executesCode=true run arbitrary code on remote hosts or containers"
|
|
156
|
+
severity: high
|
|
157
|
+
category: vscode-extension
|
|
158
|
+
condition: |
|
|
159
|
+
components[
|
|
160
|
+
$startsWith(purl, 'pkg:vscode-extension/')
|
|
161
|
+
and $listContains($propList($, 'cdx:vscode-extension:extensionKind'), 'workspace')
|
|
162
|
+
and $propBool($, 'cdx:vscode-extension:executesCode') = true
|
|
163
|
+
]
|
|
164
|
+
location: |
|
|
165
|
+
{
|
|
166
|
+
"bomRef": $. "bom-ref",
|
|
167
|
+
"purl": purl
|
|
168
|
+
}
|
|
169
|
+
message: "VS Code extension '{{ publisher }}.{{ name }}' executes code in workspace (remote) context"
|
|
170
|
+
mitigation: "Verify extension source before use in remote development; restrict workspace extensions to trusted publishers"
|
|
171
|
+
evidence: |
|
|
172
|
+
{
|
|
173
|
+
"extensionKind": $prop($, 'cdx:vscode-extension:extensionKind'),
|
|
174
|
+
"executesCode": $prop($, 'cdx:vscode-extension:executesCode'),
|
|
175
|
+
"main": $prop($, 'cdx:vscode-extension:main')
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
- id: VSC-008
|
|
179
|
+
name: "Extension with outdated VS Code engine requirement"
|
|
180
|
+
description: "Extensions requiring VS Code engine <1.80 may lack workspace trust and other modern security features"
|
|
181
|
+
severity: low
|
|
182
|
+
category: vscode-extension
|
|
183
|
+
condition: |
|
|
184
|
+
components[
|
|
185
|
+
$startsWith(purl, 'pkg:vscode-extension/')
|
|
186
|
+
and $hasProp($, 'cdx:vscode-extension:vscodeEngine')
|
|
187
|
+
and $count($match($prop($, 'cdx:vscode-extension:vscodeEngine'), /(\^|>=)?1\.(8[0-9]|9[0-9])\./)) = 0
|
|
188
|
+
]
|
|
189
|
+
location: |
|
|
190
|
+
{
|
|
191
|
+
"bomRef": $. "bom-ref",
|
|
192
|
+
"purl": purl
|
|
193
|
+
}
|
|
194
|
+
message: "VS Code extension '{{ publisher }}.{{ name }}' requires outdated engine: {{ $prop($, 'cdx:vscode-extension:vscodeEngine') }}"
|
|
195
|
+
mitigation: "Update extension or VS Code to ensure modern security features are available; contact publisher for updates"
|
|
196
|
+
evidence: |
|
|
197
|
+
{
|
|
198
|
+
"vscodeEngine": $prop($, 'cdx:vscode-extension:vscodeEngine'),
|
|
199
|
+
"version": version
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
- id: VSC-009
|
|
203
|
+
name: "Extension with browser entry point but no sandbox declaration"
|
|
204
|
+
description: "Extensions declaring browser entry points should run in web sandbox; flag if also declares workspace execution or filesystem access"
|
|
205
|
+
severity: medium
|
|
206
|
+
category: vscode-extension
|
|
207
|
+
condition: |
|
|
208
|
+
components[
|
|
209
|
+
$startsWith(purl, 'pkg:vscode-extension/')
|
|
210
|
+
and $hasProp($, 'cdx:vscode-extension:browser')
|
|
211
|
+
and (
|
|
212
|
+
$listContains($propList($, 'cdx:vscode-extension:extensionKind'), 'workspace')
|
|
213
|
+
or $listContains($propList($, 'cdx:vscode-extension:contributes'), 'filesystem-provider')
|
|
214
|
+
)
|
|
215
|
+
]
|
|
216
|
+
location: |
|
|
217
|
+
{
|
|
218
|
+
"bomRef": $. "bom-ref",
|
|
219
|
+
"purl": purl
|
|
220
|
+
}
|
|
221
|
+
message: "VS Code extension '{{ publisher }}.{{ name }}' has browser entry point but also declares workspace/filesystem capabilities"
|
|
222
|
+
mitigation: "Clarify extension execution context; prefer separate web/native extension variants; audit cross-context data flows"
|
|
223
|
+
evidence: |
|
|
224
|
+
{
|
|
225
|
+
"browser": $prop($, 'cdx:vscode-extension:browser'),
|
|
226
|
+
"main": $prop($, 'cdx:vscode-extension:main'),
|
|
227
|
+
"contributes": $prop($, 'cdx:vscode-extension:contributes')
|
|
228
|
+
}
|