Skip to content

Commit 126383e

Browse files
committed
Implement OSPS-VM-04.01: Public vulnerability disclosure assessment
- Add hasPublicVulnerabilityDisclosure function to check for public disclosure mechanisms - Update OSPS-VM-04.01 assessment steps (IsActive + hasPublicVulnerabilityDisclosure) - Add comprehensive test coverage with 5 test cases: * GitHub security policy enabled * Security Insights policy URL present * No disclosure mechanisms available * Both mechanisms present (GitHub takes priority) * Invalid payload handling - Add stubGraphqlRepoWithSecurityPolicy helper function following existing patterns Closes #34
1 parent 77e197b commit 126383e

File tree

3 files changed

+117
-1
lines changed

3 files changed

+117
-1
lines changed

evaluation_plans/osps/vuln_management/evaluations.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ func OSPS_VM_04() (evaluation *layer4.ControlEvaluation) {
8383
"Maturity Level 3",
8484
},
8585
[]layer4.AssessmentStep{
86-
reusable_steps.NotImplemented,
86+
reusable_steps.IsActive,
87+
hasPublicVulnerabilityDisclosure,
8788
},
8889
)
8990

evaluation_plans/osps/vuln_management/steps.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,20 @@ func hasVulnerabilityDisclosurePolicy(payloadData any, _ map[string]*layer4.Chan
6060

6161
return layer4.Passed, "Vulnerability disclosure policy was specified in Security Insights data"
6262
}
63+
64+
func hasPublicVulnerabilityDisclosure(payloadData any, _ map[string]*layer4.Change) (result layer4.Result, message string) {
65+
data, message := reusable_steps.VerifyPayload(payloadData)
66+
if message != "" {
67+
return layer4.Unknown, message
68+
}
69+
70+
if data.GraphqlRepoData.Repository.IsSecurityPolicyEnabled {
71+
return layer4.Passed, "Public vulnerability disclosure available via GitHub security policy"
72+
}
73+
74+
if data.Insights.Project.Vulnerability.SecurityPolicy != "" {
75+
return layer4.Passed, "Public vulnerability disclosure available via security policy in Security Insights data"
76+
}
77+
78+
return layer4.Failed, "No public vulnerability disclosure mechanism found"
79+
}

evaluation_plans/osps/vuln_management/steps_test.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,101 @@ func TestHasVulnerabilityDisclosurePolicy(t *testing.T) {
164164
})
165165
}
166166
}
167+
168+
func stubGraphqlRepoWithSecurityPolicy(isSecurityPolicyEnabled bool) *data.GraphqlRepoData {
169+
repo := &data.GraphqlRepoData{}
170+
repo.Repository.IsSecurityPolicyEnabled = isSecurityPolicyEnabled
171+
return repo
172+
}
173+
174+
func TestHasPublicVulnerabilityDisclosure(t *testing.T) {
175+
tests := []struct {
176+
name string
177+
payloadData any
178+
expectedResult layer4.Result
179+
expectedMessage string
180+
}{
181+
{
182+
name: "Public disclosure via GitHub security policy",
183+
expectedResult: layer4.Passed,
184+
expectedMessage: "Public vulnerability disclosure available via GitHub security policy",
185+
payloadData: data.Payload{
186+
RestData: &data.RestData{
187+
Insights: si.SecurityInsights{
188+
Project: si.Project{
189+
Vulnerability: si.VulnReport{
190+
SecurityPolicy: "",
191+
},
192+
},
193+
},
194+
},
195+
GraphqlRepoData: stubGraphqlRepoWithSecurityPolicy(true),
196+
},
197+
},
198+
{
199+
name: "Public disclosure via Security Insights policy",
200+
expectedResult: layer4.Passed,
201+
expectedMessage: "Public vulnerability disclosure available via security policy in Security Insights data",
202+
payloadData: data.Payload{
203+
RestData: &data.RestData{
204+
Insights: si.SecurityInsights{
205+
Project: si.Project{
206+
Vulnerability: si.VulnReport{
207+
SecurityPolicy: "https://github.com/example/repo/blob/main/SECURITY.md",
208+
},
209+
},
210+
},
211+
},
212+
GraphqlRepoData: stubGraphqlRepoWithSecurityPolicy(false),
213+
},
214+
},
215+
{
216+
name: "No public disclosure mechanism",
217+
expectedResult: layer4.Failed,
218+
expectedMessage: "No public vulnerability disclosure mechanism found",
219+
payloadData: data.Payload{
220+
RestData: &data.RestData{
221+
Insights: si.SecurityInsights{
222+
Project: si.Project{
223+
Vulnerability: si.VulnReport{
224+
SecurityPolicy: "",
225+
},
226+
},
227+
},
228+
},
229+
GraphqlRepoData: stubGraphqlRepoWithSecurityPolicy(false),
230+
},
231+
},
232+
{
233+
name: "Both mechanisms available - GitHub policy takes priority",
234+
expectedResult: layer4.Passed,
235+
expectedMessage: "Public vulnerability disclosure available via GitHub security policy",
236+
payloadData: data.Payload{
237+
RestData: &data.RestData{
238+
Insights: si.SecurityInsights{
239+
Project: si.Project{
240+
Vulnerability: si.VulnReport{
241+
SecurityPolicy: "https://github.com/example/repo/blob/main/SECURITY.md",
242+
},
243+
},
244+
},
245+
},
246+
GraphqlRepoData: stubGraphqlRepoWithSecurityPolicy(true),
247+
},
248+
},
249+
{
250+
name: "Invalid payload",
251+
expectedResult: layer4.Unknown,
252+
expectedMessage: "Malformed assessment: expected payload type data.Payload, got string (invalid_payload)",
253+
payloadData: "invalid_payload",
254+
},
255+
}
256+
257+
for _, test := range tests {
258+
t.Run(test.name, func(t *testing.T) {
259+
result, message := hasPublicVulnerabilityDisclosure(test.payloadData, nil)
260+
assert.Equal(t, test.expectedResult, result)
261+
assert.Equal(t, test.expectedMessage, message)
262+
})
263+
}
264+
}

0 commit comments

Comments
 (0)