Add malware filter argument to Dependency GraphQL APIs
What does this MR do and why?
Introduces a new malware: Boolean argument on the project-level and group-level dependency list GraphQL APIs:
Query.project.dependencies(malware: …)Query.group.dependencies(malware: …)
The argument is added to the shared Resolvers::Sbom::DependencyInterfaceResolver, so both DependenciesResolver (powers project.dependencies and group.dependencies) and DependencyAggregationResolver automatically expose it.
Per the slack discussion summary, this MR only introduces the field surface in 19.0 so the frontend (#587762 (closed)) is unblocked despite the GraphQL multi-version compatibility constraints. Actual filtering against the finders is intentionally left as a follow-up.
Why behind a feature flag
Per the issue's performance concern and the slack discussion, joining identifiers in PostgreSQL to filter dependencies by malware status may not scale (see &17619). The new argument is therefore gated behind the malicious_packages_dependency_list_filtering feature flag so we can roll it out gradually (and, if needed, defer to Elasticsearch-backed filtering before GA).
What is not done in this MR (TODO)
- Wiring
:malwarethroughSbom::DependenciesFinder/Sbom::AggregationsFinder. Tracked inline via aTODOreferencing #587758. - SSCS add-on license gating (returning empty / null vs raising). To be decided alongside #587647.
- REST endpoint
GET /api/v4/groups/:id/dependencies?malware=…(only required if the group dependencies GraphQL migration in &17254 has not landed when filtering is implemented).
Implementation notes
- The GraphQL field description reads: "Filter dependencies by malware status. Work in progress and gated with feature flag
malicious_packages_dependency_list_filtering." It intentionally avoids prescribing the implementation approach (identifier-based vs ES-backed) until that decision is made. mapped_paramsremoves:malwarebefore passing params to the finders (result.delete(:malware)with an inlineTODO), so the field is currently a no-op (returns the unfiltered dependency list).- When the FF is disabled, supplying
malware: true|falseraisesGitlab::Graphql::Errors::ArgumentErrorwith"The malware filter is not available.", mirroring the pattern inResolvers::VulnerabilityFilterable#validate_malware!. - The argument is marked as
experiment: { milestone: '19.0' }so it appears with the experiment marker in the auto-generated GraphQL reference docs.
Feature flag
| Name | malicious_packages_dependency_list_filtering |
| Type | wip |
| Default enabled | false |
| Milestone | 19.0 |
| Rollout issue | #600025 |
How to set up and validate locally
# With FF disabled (default) — expect an error
query {
project(fullPath: "flightjs/Flight") {
dependencies(malware: true) { nodes { id name } }
}
}
# Enable the flag, then re-run — expect the unfiltered list (TODO: real filtering)
# Rails console:
# Feature.enable(:malicious_packages_dependency_list_filtering)Follow-ups
- Implement actual malware filtering in
Sbom::DependenciesFinderandSbom::AggregationsFinder. - Add SSCS license gating once #587647 lands.
- Decide whether ES-backed filtering (&17619) is a prerequisite before GA.
References
- Issue: #587758
- Rollout issue: #600025
- Frontend follow-up: #587762 (closed)
- Parent epic: &20573
- Related: #587647 (expose malware status)
- Slack discussion summary: note_3343856241
Milestone: 19.0 — please set via the sidebar (quick actions are disabled for AI workflows).
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.