Vulnerabilities created via API have invalid location metadata
Summary
Vulnerabilities created via the API have a symbolized location key in their raw_metadata, which causes the raw_metadata to be invalid JSON.
Steps to reproduce
Via GraphQL:
-
Enter this query:
mutation vulnerabilityCreate($input: VulnerabilityCreateInput!) { vulnerabilityCreate(input: $input) { errors clientMutationId vulnerability: vulnerability { id vulnerabilityPath project { id fullPath } } } }with these query variables:
{ "input": { "project": "gid://gitlab/Project/1", "name": "A manual vulnerability number 1", "description": "A descriptive description.\nNumber 1.", "scanner": { "id": "SAST", "name": "Test", "url": "", "vendor": { "name": "some vendor"}, "version": "v1" }, "state": "DETECTED", "severity": "CRITICAL", "identifiers": [ { "name": "CVE-1", "url": "http://localhost" } ] } }and receive response:
{ "data": { "vulnerabilityCreate": { "errors": [], "clientMutationId": null, "vulnerability": { "id": "gid://gitlab/Vulnerability/671", "vulnerabilityPath": "/gitlab-org/gitlab-test/-/security/vulnerabilities/671", "project": { "id": "gid://gitlab/Project/1", "fullPath": "gitlab-org/gitlab-test" } } } } } -
Take the vulnerability ID and check the metadata using the rails console:
[5] pry(main)> vuln = Vulnerability.find(671) => #<Vulnerability id:671 [vulnerability:gitlab-org/gitlab-test/671]> [6] pry(main)> vuln.finding.raw_metadata => "{:location=>nil}"
Via Starboard API:
-
Create a new KAS JWT using the rails console:
JWT.encode({ 'iss' => Gitlab::Kas::JWT_ISSUER }, Gitlab::Kas.secret, 'HS256') -
Create a new gitlab project
-
Create new agent:
agent = Clusters::Agent.new(project_id: project.id, created_by_user: User.find(1), name: "test-agent") agent.save! -
Create new agent token and retrieve the value
token = Clusters::AgentToken.new(agent: agent, created_by_user: User.find(1), name: "test-agent-token") token.save! token.token -
Send the API request:
curl --request PUT --include \ --header "Gitlab-Kas-Api-Request: $KAS_JWT" \ --header "Authorization: Bearer $AGENT_TOKEN" --header "Content-Type: application/json" \ --url "http://localhost:3000/api/v4/internal/kubernetes/modules/starboard_vulnerability" \ --data '{ "vulnerability": { "name": "CVE-123-4567 in libc", "severity": "high", "confidence": "unknown", "location": { "image": "index.docker.io/library/nginx:latest", "kubernetes_resource": { "namespace": "production", "kind": "deployment", "name": "nginx", "container_name": "nginx", "agent_id": "2" }, "dependency": { "package": { "name": "libc" }, "version": "v1.2.3" } }, "identifiers": [ { "type": "cve", "name": "CVE-123-4567", "value": "CVE-123-4567" } ] }, "scanner": { "id": "starboard_trivy", "name": "Trivy (via Starboard Operator)", "vendor": { "name": "GitLab" } } }' -
Observe that
raw_metadatahas a symbolized location:[5] pry(main)> project.vulnerabilities.map { |vuln| vuln.finding.raw_metadata } => ["{:location=>{\"image\"=>\"index.docker.io/library/nginx:latest\", \"kubernetes_resource\"=>{\"namespace\"=>\"production\", \"kind\"=>\"deployment\", \"name\"=>\"nginx\", \"container_name\"=>\"nginx\", \"agent_id\"=>\"2\"}, \"dependency\"=>{\"package\"=>{\"name\"=>\"libc\"}, \"version\"=>\"v1.2.3\"}}}"]
What is the current bug behavior?
The raw_location is a stringified hash instead of valid JSON.
What is the expected correct behavior?
The raw_location must contain valid JSON.
Possible fixes
We need to call .to_json on this object.
and also purge the invalid data from the database
Edited by Brian Williams