Malware Package UI Representation and Filters
## TL;DR
Enable users to identify and filter malicious packages across Dependency Lists, Vulnerability Reports, and Details pages as part of the SSCS add-on.
## Overview
This epic delivers the UI layer for malicious package detection, building on top of the backend ingestion work in [&20538](https://gitlab.com/groups/gitlab-org/-/epics/20538). Once malware data flows through the GitLab SBOM Vulnerability Scanner, users need a way to visually identify, filter, and understand malicious packages in their projects.
## Business Value
- **Security visibility:** Users can quickly identify malicious packages threatening their supply chain
- **Efficient triage:** Dedicated filters help security teams focus on malware vs CVE vulnerabilities
- **Appropriate context:** Details page shows relevant malware information without confusing CVE-specific fields
- **Revenue enablement:** Feature gated behind SSCS add-on drives add-on adoption
## Scope
### In Scope
**Dependency List**
- Malware indicator badge (red "Malware" badge)
- Rename "Vulnerabilities" column to "Risk"
- Malware indicator in dependency list export
- `malware` filter token
**Vulnerability Report**
- Malware package display with name, severity (Critical), identifier (CWE-506), report type
- `malware` (Y/N) filter token
- Under the hood: Filter by identifier (`CWE-506` or `GLAM`)
- Existing findings **must be retained**, **must not** be auto-resolved or removed, and their status should be left unmodified _(“Needs Triage”, “Confirmed”, “Dismissed” + reason, “Resolved” if a user takes an action to resolve it)_. Absence of updated detection of results reflects loss of scan capability, not remediation.
**Vulnerability Details Page**
- Display: Content from GLAD, affected packages, links, reachability, identifiers
- Exclude: Solution field (legal liability), KEV, EPSS, CVSS
**Security Dashboard**
- Track each malware package instance as 1 vulnerability
- Filter by report type support (Malware Packages should be a standalone report type - possibly implemented the same way as the vulnerability report feature)
- Risk score calculation updates for malware
- If the add on is removed, results from prior scans can remain aggregated in security dashboard until they are expired.
**License Gating**
- SSCS add-on entitlement checks
- Empty states with upsell messaging
### Out of Scope
- Filter for 'risk type' on dependency list (has vulns, is malware, none)
- Changes to policies
- Pipeline \> Security (findings)
- MR Security Widget (findings)
- Security Center changes
## Problem Statement
The Composition Analysis team is implementing backend ingestion of malware advisories into PMDB (see [epic &20538](https://gitlab.com/groups/gitlab-org/-/epics/20538)). Once complete, malware data will flow through the GitLab SBOM Vulnerability Scanner and appear as vulnerabilities. Users currently have no way to:
- Visually distinguish malware packages from CVE vulnerabilities
- Filter to focus on malware findings
- See appropriate details for malware (without irrelevant CVE fields)
## Proposed Approach
**Phase 1: Display Malware Package Information**
- Backend exposes `malware` fields in APIs
- Frontend displays badges on Dependency Lists and Vulnerability Reports
- Details page conditionally hides CVE-specific fields for malware
- Export includes malware status
**Phase 2: Malware Package Status Filters**
- Backend adds filter parameters to finders/resolvers
- Frontend adds filter tokens to Dependency Lists and Vulnerability Reports
**Phase 3: Gate Malware Packages Behind SSCS Add-on**
- Backend gates malware data behind SSCS add-on entitlement
- Frontend shows empty states with upsell when not entitled
**Phase 4: Integrate Malware Packages in Security Dashboard** (can run in parallel)
- Update risk score calculation to include malware
- Verify dashboard metrics include malware
- Coordinate with VR team on weighting
## Feature Flags
- [x] Required
- [ ] **`malicious_package_badges`** - Phase 1
* **`malicious_package_filters`** - Phase 2
* **`malicious_package_license_gating`** - Phase 3
* **`malicious_package_risk_score`** - Phase 4
* **Default state:** Disabled
* **Rollout plan:** Phase by phase
Alternatively, we can also put everything behind one feature flag (simpler rollout).
## Success Criteria
- [ ] Malware packages visually distinguishable via badges in Dependency Lists
- [ ] Malware packages visually distinguishable via badges in Vulnerability Reports
- [ ] Users can filter dependencies and vulnerabilities by malware status
- [ ] Vulnerability Details page hides Solution/CVSS/EPSS/KEV for malware
- [ ] Security Dashboard risk score includes malware
- [ ] Feature gated behind SSCS add-on license
- [ ] Works at project and group levels
## Timeline
`/estimate TBD (BE estimates are pending)`
### Milestones
| Phase | Scope | Estimate |
|-------|-------|----------|
| Phase 1 | Display Malware Package Information | TBD |
| Phase 2 | Malware Package Status Filters | TBD |
| Phase 3 | Gate Malware Packages Behind SSCS Add-on | TBD |
| Phase 4 | Integrate Malware Packages in Security Dashboard | TBD (parallel) |
## Dependencies
### Upstream Dependencies
| Dependency | Epic/Issue | Team | Status |
|------------|------------|------|--------|
| PMDB malware advisory ingestion | [&20538](https://gitlab.com/groups/gitlab-org/-/epics/20538) | Composition Analysis | In Progress |
| Private malware advisory repo | TBD | Vulnerability Research | In Progress |
| SBOM Scanner identifier generation | TBD (from &20538 discussion) | Composition Analysis | Planning |
| Dependency Management using ElasticSearch | #17619 | Security Infrastructure | Planning |
### Key Technical Context (from &20538)
**Identifier Format:**
- Proposed format: `GLAM-` (see https://gitlab.com/gitlab-org/gitlab/-/work_items/588568#note_3084795090)
**Data Flow:**
```
Private Malware Repo → PMDB Feeder → PMDB Exporter → Rails Sync → SBOM Scanner → Vulnerabilities
```
## Child Epics & Issues
### [Display Malware Package Information](https://gitlab.com/groups/gitlab-org/-/epics/20572)
```glql
display: table
title: Display Malware Package Information
fields: title, labels("backend", "frontend") AS "Type", status
query: group = "gitlab-org" and type in (Issue, Task) and epic = gitlab-org&20572
```
### [Malware Package Status Filters](https://gitlab.com/groups/gitlab-org/-/epics/20573)
```glql
display: table
title: Display Malware Package Information
fields: title, labels("backend", "frontend") AS "Type", status
query: group = "gitlab-org" and type in (Issue, Task) and epic = gitlab-org&20573
```
### [Gate Malware Packages Behind SSCS Add-on](https://gitlab.com/groups/gitlab-org/-/epics/20574)
```glql
display: table
title: Display Malware Package Information
fields: title, labels("backend", "frontend") AS "Type", status
query: group = "gitlab-org" and type in (Issue, Task) and epic = gitlab-org&20574
```
### [Integrate Malware Packages in Security Dashboard](https://gitlab.com/groups/gitlab-org/-/epics/20575)
```glql
display: table
title: Display Malware Package Information
fields: title, labels("backend", "frontend") AS "Type", status
query: group = "gitlab-org" and type in (Issue, Task) and epic = gitlab-org&20575
```
## Open Questions
See sub-epics for additional open questions:
- [Gate Malware Packages Behind SSCS Add-on](https://gitlab.com/groups/gitlab-org/-/epics/20574) - License gating & expiry behavior
- [Integrate Malware Packages in Security Dashboard](https://gitlab.com/groups/gitlab-org/-/epics/20575) - Risk score weighting
## Decision Log
| Date | Decision | Rationale | Owner |
|------|----------|-----------|-------|
| 2026-02-16 | Internal Identifier decision (`GLAM`) | distinction from other identifiers | |
| 2026-01-20 | Standalone `malware` filter token (not integrated with existing filters) | Malware triage is a distinct workflow from CVE triage | `@mclausen35` |
| 2026-01-20 | Malware stays under "Dependency Scanning" report type (no new report type) | Simpler implementation, malware is subset of DS findings | `@mclausen35` |
| 2026-01-20 | Hide malware records entirely when user lacks add-on | Clean UX, no partial data exposure | `@mclausen35` |
| 2025-07-11 | Exclude Solution field for malware (legal liability) | Cannot advise remediation for malware | `@johncrowley` |
| 2025-07-11 | Exclude KEV, EPSS, CVSS for malware | Not applicable to malware findings | `@johncrowley` |
| 2025-07-11 | Rename "Vulnerabilities" column to "Risk" | Encompasses both CVEs and malware | `@johncrowley` |
| 2026-23-02 | Keep and show existing data even after add-on-expiry (plus filter functionality) | | `@mclausen35` |
## Resources
- **Upstream epic:** [&20538 - Ingest malware advisories in PMDB](https://gitlab.com/groups/gitlab-org/-/epics/20538)
- Design issue: https://gitlab.com/gitlab-org/gitlab/-/issues/551225
- Technical spike: https://gitlab.com/gitlab-org/gitlab/-/issues/583911
- Risk score issue: https://gitlab.com/gitlab-org/gitlab/-/issues/551239#note_2620976437
---
<details>
<summary>
Original Epic Description (created by \`@mclausen35\`)
</summary>
## Executive Summary
All Executive Summary data is stored in the parent epic.
#### Engineering Assessment
#### Dependencies
* _Dependency for_ https://gitlab.com/gitlab-org/gitlab/-/issues/551225+
# In Scope
* These capabilities should only be available for orgs that have purchased the SSCM add-on. This ultimately means that the malicious package information should not be ingested (as everything else is downstream from that)
**On the dependency list**
* Malware indicator: We should possibly rename the vulnerability column to 'risks' and potentially include license risks in this too, in the future.
* The malware indicator should be present in the export of the dependency list
* The 'is malware' feature should be present on this page as well.
**On the vulnerability Report**
The malicious package should be rendered like this
* Name: Malicious package 'package name' detected, introducing CWE-xyz (from the GLAD repo)
* Severity: Collected pre-Sec. Insights, always Critical
* Identifier: CWE type **(always CWE-506)**
* **This will enable filtering as well**
* Report type: dependency scanning
* Filters
* Filtering can be applied via identifier (CWE-506 or MAL-XXXX)
* The filter should state 'isMalware (Y/N) and on the backend refer back to the CWE-506 value or the MAL- prefix.
* Vuln details
* Content in GLAD
* Affected packages
* Links: GLAD advisory, details on affecting CWE type
* Solution: Exclude solution per the below
* **Referencing at** [**GitHub advisory**](https://github.com/advisories/GHSA-778j-3w56-g989) **for Malware they do not provide a solution. I think we should not propose a solution because we are telling the user what to do when we are making an assumption. With a CVE the solution is provided to us and we just consume that data from GitHub / NVD. I think instructing the user to perform an action would potentially open us up to legal liability.**
* Exclude: KEV, EPSS, and CVSS
* Include: Reachability
* Identifiers (from GLAD)
* **CWE**
* **GitHub unique ID**
* **Internal ID (MAL-XXX)**
* **Any other links provided by GLAD, which is how we operate with CVE vulnerabilities.**
**On the dashboard**
* Track each instance of a 'malicious package' as 1 vulnerability (IE is imported transiitvely or directly via a pom file in a project)
* Filter by report type support
* Risk score update support required from VR team.
* https://gitlab.com/gitlab-org/gitlab/-/issues/551239#note_2620976437
# Out of Scope
* Filter for 'risk type' on the dependenct list (has vulns, is malware, none)
* Changes to policies
* New data and new filters on the vulnerability report
## Functional Requirements
### Page Level Support
* [x] Project
* [x] Group
* [ ] Pipeline \> Security (findings)
* [ ] MR Security Widget (findings)
* [ ] Security Center
* [x] Security Dashboard
* [x] Dependency List
### Workflow
* [ ] Requires an additional filter on the Vulnerability Report ([docs](https://docs.gitlab.com/development/internal_analytics/internal_event_instrumentation/quick_start/))
* [ ] Requires an addition to the Vulnerability Report export ([docs](https://docs.gitlab.com/user/application_security/vulnerability_report/#exporting))
* [ ] Requires an additional filter on the Dependency List ([docs](https://docs.gitlab.com/user/application_security/dependency_list/))
* [x] Requires an addition to the Dependency List export ([docs](https://docs.gitlab.com/user/application_security/dependency_list/#export))
* [ ] Requires ~documentation
## Non-Functional Requirements
### Product Usage
* [x] Requires new instrumentation ([docs](https://docs.gitlab.com/development/internal_analytics/internal_event_instrumentation/quick_start/))
### Feature Flag Usage
* [x] This feature should be released behind a feature flag? ([docs](https://handbook.gitlab.com/handbook/product-development/product-development-flow/feature-flag-lifecycle/#when-to-use-feature-flags))
### Testing
* [ ] Requires new E2E test coverage ([docs](https://docs.gitlab.com/development/testing_guide/end_to_end/))
* [ ] Requires extended manual / UAT phase
* [ ] Performance testing needed ([testing](https://docs.gitlab.com/ci/testing/load_performance_testing/))
## Outstanding Questions
tbd
## Designs
tbd
</details>
epic