Group-level vulnerability reports do not show all of the vulnerabilities belonging to the project that have been moved from other groups.
Summary
Group-level vulnerability reports do not show vulnerabilities detected before the project under that group is moved from another group.
Related slack thread(GitLab internal)
Zendesk ticket(gitLab internal)
Steps to reproduce
- There are
groupA
andgroupB
- The
projectA
is created under thegroupA
. (groupA/projectA
) - Vulnerabilities are detected on the
projectA
- The
projectA
is transferred to under thegroupB
. (groupB/projectA
) - Check the group-level vulnerability reports for
groupB
Example Project
This contains customer information, so I'll leave it as the internal comment.
What is the current bug behavior?
The bug is ongoing. Customers can't see all vulnerabilities in the group-level report.
What is the expected correct behavior?
Group-level vulnerabilities report shows all vulnerabilities belonging to the project under the group no matter when it is detected.
Relevant logs and/or screenshots
This contains customer information, so I'll leave it as the internal comment.
Output of checks
This bug happens on GitLab.com /label reproduced on GitLab.com
Results of GitLab environment info
Expand for output related to GitLab environment info
(For installations with omnibus-gitlab package run and paste the output of: `sudo gitlab-rake gitlab:env:info`) (For installations from source run and paste the output of: `sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`)
Results of GitLab application Check
N/A
Possible fixes
Testing locally, the group vulnerability GraphQL endpoint first queries a list of namespaces with type Group
for the given group name.
Expand to see query
SELECT
"namespaces"."id" AS t0_r0,
"namespaces"."name" AS t0_r1,
"namespaces"."path" AS t0_r2,
"namespaces"."owner_id" AS t0_r3,
"namespaces"."created_at" AS t0_r4,
"namespaces"."updated_at" AS t0_r5,
"namespaces"."type" AS t0_r6,
"namespaces"."description" AS t0_r7,
"namespaces"."avatar" AS t0_r8,
"namespaces"."membership_lock" AS t0_r9,
"namespaces"."share_with_group_lock" AS t0_r10,
"namespaces"."visibility_level" AS t0_r11,
"namespaces"."request_access_enabled" AS t0_r12,
"namespaces"."ldap_sync_status" AS t0_r13,
"namespaces"."ldap_sync_error" AS t0_r14,
"namespaces"."ldap_sync_last_update_at" AS t0_r15,
"namespaces"."ldap_sync_last_successful_update_at" AS t0_r16,
"namespaces"."ldap_sync_last_sync_at" AS t0_r17,
"namespaces"."description_html" AS t0_r18,
"namespaces"."lfs_enabled" AS t0_r19,
"namespaces"."parent_id" AS t0_r20,
"namespaces"."shared_runners_minutes_limit" AS t0_r21,
"namespaces"."repository_size_limit" AS t0_r22,
"namespaces"."require_two_factor_authentication" AS t0_r23,
"namespaces"."two_factor_grace_period" AS t0_r24,
"namespaces"."cached_markdown_version" AS t0_r25,
"namespaces"."project_creation_level" AS t0_r26,
"namespaces"."runners_token" AS t0_r27,
"namespaces"."file_template_project_id" AS t0_r28,
"namespaces"."saml_discovery_token" AS t0_r29,
"namespaces"."runners_token_encrypted" AS t0_r30,
"namespaces"."custom_project_templates_group_id" AS t0_r31,
"namespaces"."auto_devops_enabled" AS t0_r32,
"namespaces"."extra_shared_runners_minutes_limit" AS t0_r33,
"namespaces"."last_ci_minutes_notification_at" AS t0_r34,
"namespaces"."last_ci_minutes_usage_notification_level" AS t0_r35,
"namespaces"."subgroup_creation_level" AS t0_r36,
"namespaces"."emails_disabled" AS t0_r37,
"namespaces"."max_pages_size" AS t0_r38,
"namespaces"."max_artifacts_size" AS t0_r39,
"namespaces"."mentions_disabled" AS t0_r40,
"namespaces"."default_branch_protection" AS t0_r41,
"namespaces"."unlock_membership_to_ldap" AS t0_r42,
"namespaces"."max_personal_access_token_lifetime" AS t0_r43,
"namespaces"."push_rule_id" AS t0_r44,
"namespaces"."shared_runners_enabled" AS t0_r45,
"namespaces"."allow_descendants_override_disabled_shared_runners" AS t0_r46,
"namespaces"."traversal_ids" AS t0_r47,
"namespaces"."organization_id" AS t0_r48,
"routes"."id" AS t1_r0,
"routes"."source_id" AS t1_r1,
"routes"."source_type" AS t1_r2,
"routes"."path" AS t1_r3,
"routes"."created_at" AS t1_r4,
"routes"."updated_at" AS t1_r5,
"routes"."name" AS t1_r6,
"routes"."namespace_id" AS t1_r7
FROM
"namespaces"
LEFT OUTER JOIN "routes" ON "routes"."source_type" = 'Namespace'
AND "routes"."source_id" = "namespaces"."id"
WHERE
"namespaces"."type" = 'Group'
AND ((LOWER(routes.path) = LOWER('gitlab-org')))
Then queries all vulnerability_reads
for the given group namespaces:
Expand to see query
SELECT
"vulnerability_reads".*
FROM
"vulnerability_reads"
WHERE
"vulnerability_reads"."vulnerability_id" IN (
SELECT
"vulnerability_reads"."vulnerability_id"
FROM
unnest(ARRAY (
SELECT
"namespaces"."id" FROM "namespaces"
WHERE
"namespaces"."type" = 'Group'
AND (traversal_ids @> ('{24}')))::bigint[]) AS "namespace_ids" ("namespace_id"), unnest('{6,2,5,3,1,0,4,99}'::smallint[]) AS "report_types" ("report_type"), unnest('{1,4}'::smallint[]) AS "states" ("state"), LATERAL (
SELECT
"vulnerability_reads"."namespace_id", "vulnerability_reads"."report_type", "vulnerability_reads"."state", "vulnerability_reads"."severity", "vulnerability_reads"."vulnerability_id"
FROM
"vulnerability_reads"
WHERE (vulnerability_reads. "namespace_id" = "namespace_ids"."namespace_id")
AND (vulnerability_reads. "report_type" = "report_types"."report_type")
AND (vulnerability_reads. "state" = "states"."state")
ORDER BY
"vulnerability_reads"."severity" DESC,
"vulnerability_reads"."vulnerability_id" DESC
LIMIT 21) AS vulnerability_reads
ORDER BY
"vulnerability_reads"."severity" DESC,
"vulnerability_reads"."vulnerability_id" DESC
LIMIT 21)
ORDER BY
"vulnerability_reads"."severity" DESC,
"vulnerability_reads"."vulnerability_id" DESC
LIMIT 21
It seems likely that that namespaces associated with the vulnerability_reads
are not being updated when a project is moved from one group to another.
If that's the case a possible fix is:
- Update
ee/app/services/ee/projects/transfer_service.rb
and add a hook to update thevulnerability_reads#namespace_id
values to the new group when transferring a project. This should be performed in batches. - Write a migration to find and fix up 'orphan'
vulnerability_reads
- i.e. like those in this bug report - and repoint them to the correct group.
For the record, the namespace_id
on vulnerability_reads
is initially set via a trigger here