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 :malware through Sbom::DependenciesFinder / Sbom::AggregationsFinder. Tracked inline via a TODO referencing #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_params removes :malware before passing params to the finders (result.delete(:malware) with an inline TODO), so the field is currently a no-op (returns the unfiltered dependency list).
  • When the FF is disabled, supplying malware: true|false raises Gitlab::Graphql::Errors::ArgumentError with "The malware filter is not available.", mirroring the pattern in Resolvers::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

  1. Implement actual malware filtering in Sbom::DependenciesFinder and Sbom::AggregationsFinder.
  2. Add SSCS license gating once #587647 lands.
  3. Decide whether ES-backed filtering (&17619) is a prerequisite before GA.

References

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.

Edited by Bala Kumar

Merge request reports

Loading