--- name: "gitlab-vulnerability" description: "GitLab vulnerability operations via API. ALWAYS use this skill when user wants to: (1) list security vulnerabilities, (2) view vulnerability details, (3) confirm/dismiss/resolve vulnerabilities, (4) view vulnerability findings." version: "1.0.0" author: "GitLab-Assistant-Skills" license: "MIT" allowed-tools: ["Bash", "Read", "Glob", "Grep"] --- # Vulnerability Skill Security vulnerability management for GitLab using `glab api` raw endpoint calls. ## Quick Reference | Operation | Command Pattern | Risk | |-----------|-----------------|:----:| | List vulnerabilities | `glab api projects/:id/vulnerabilities` | - | | Get vulnerability | `glab api projects/:id/vulnerabilities/:vuln_id` | - | | Confirm vulnerability | `glab api projects/:id/vulnerabilities/:vuln_id/confirm -X POST` | ⚠️ | | Dismiss vulnerability | `glab api projects/:id/vulnerabilities/:vuln_id/dismiss -X POST -f ...` | ⚠️ | | Resolve vulnerability | `glab api projects/:id/vulnerabilities/:vuln_id/resolve -X POST` | ⚠️ | | Revert to detected | `glab api projects/:id/vulnerabilities/:vuln_id/revert -X POST` | ⚠️ | | List findings | `glab api projects/:id/vulnerability_findings` | - | **Risk Legend**: - Safe | ⚠️ Caution | ⚠️⚠️ Warning | ⚠️⚠️⚠️ Danger ## When to Use This Skill **ALWAYS use when:** - User mentions "vulnerability", "security issue", "CVE" - User wants to view security scan results - User mentions "SAST", "DAST", "dependency scanning", "container scanning" - User wants to dismiss or resolve security findings - User asks about security dashboard **NEVER use when:** - User wants to run security scans (use gitlab-ci) - User wants to configure security settings (use project settings) - User wants general issue tracking (use gitlab-issue) ## API Prerequisites **Required Token Scopes:** `read_api` or `api` **Permissions:** - Read vulnerabilities: Developer+ - Manage vulnerabilities: Developer+ **GitLab Tier:** Ultimate required for full vulnerability management features ## Vulnerability States | State | Description | |-------|-------------| | `detected` | New, unreviewed vulnerability | | `confirmed` | Verified as real vulnerability | | `dismissed` | Marked as false positive or won't fix | | `resolved` | Fixed and no longer present | ## Severity Levels | Severity | Description | |----------|-------------| | `critical` | Highest severity, immediate action needed | | `high` | Significant risk | | `medium` | Moderate risk | | `low` | Minor risk | | `info` | Informational finding | | `unknown` | Severity not determined | ## Available Commands ### List Project Vulnerabilities ```bash # List all vulnerabilities glab api projects/123/vulnerabilities --method GET # Filter by state glab api "projects/123/vulnerabilities?state=detected" --method GET # Filter by severity glab api "projects/123/vulnerabilities?severity=critical,high" --method GET # Filter by multiple criteria glab api "projects/123/vulnerabilities?state=detected&severity=critical,high" --method GET # With pagination glab api projects/123/vulnerabilities --paginate # Using project path glab api "projects/$(echo 'mygroup/myproject' | jq -Rr @uri)/vulnerabilities" ``` ### Get Vulnerability Details ```bash # Get specific vulnerability glab api projects/123/vulnerabilities/456 --method GET ``` ### Confirm Vulnerability Marks a detected vulnerability as confirmed (real security issue). ```bash # Confirm vulnerability glab api projects/123/vulnerabilities/456/confirm --method POST ``` ### Dismiss Vulnerability Marks a vulnerability as dismissed (false positive or accepted risk). ```bash # Dismiss as false positive glab api projects/123/vulnerabilities/456/dismiss --method POST \ -f comment="False positive - this code path is not reachable" # Dismiss as acceptable risk glab api projects/123/vulnerabilities/456/dismiss --method POST \ -f comment="Accepted risk - mitigated by network controls" # Dismiss with dismissal reason (if available) glab api projects/123/vulnerabilities/456/dismiss --method POST \ -f comment="Not applicable to our use case" \ -f dismissal_reason="used_in_tests" ``` ### Resolve Vulnerability Marks a vulnerability as resolved (fixed). ```bash # Resolve vulnerability glab api projects/123/vulnerabilities/456/resolve --method POST ``` ### Revert to Detected State Reverts a vulnerability back to detected state. ```bash # Revert to detected glab api projects/123/vulnerabilities/456/revert --method POST ``` ### List Vulnerability Findings Findings are the raw results from security scanners. ```bash # List all findings glab api projects/123/vulnerability_findings --method GET # Filter by severity glab api "projects/123/vulnerability_findings?severity=critical,high" --method GET # Filter by scanner glab api "projects/123/vulnerability_findings?scanner=sast" --method GET # Filter by pipeline glab api "projects/123/vulnerability_findings?pipeline_id=789" --method GET # With pagination glab api projects/123/vulnerability_findings --paginate ``` ### Security Dashboard (Group Level) ```bash # Get security statistics for group glab api groups/456/vulnerability_exports --method POST \ -f export_format="csv" # Get group vulnerability statistics glab api "groups/456/vulnerability_statistics" --method GET ``` ## Common Workflows ### Workflow 1: Triage New Vulnerabilities ```bash project_id=123 # Get all detected (new) vulnerabilities glab api "projects/$project_id/vulnerabilities?state=detected" --paginate | \ jq -r '.[] | "[\(.severity)] \(.title) - \(.id)"' # Review critical/high first glab api "projects/$project_id/vulnerabilities?state=detected&severity=critical,high" | \ jq -r '.[] | "ID: \(.id)\nTitle: \(.title)\nSeverity: \(.severity)\nScanner: \(.scanner.name)\nLocation: \(.location | @json)\n---"' ``` ### Workflow 2: Generate Security Report ```bash project_id=123 # Summary by severity echo "=== Vulnerability Summary ===" glab api "projects/$project_id/vulnerabilities" --paginate | \ jq -r 'group_by(.severity) | map({severity: .[0].severity, count: length}) | .[] | "\(.severity): \(.count)"' # Summary by state echo "" echo "=== By State ===" glab api "projects/$project_id/vulnerabilities" --paginate | \ jq -r 'group_by(.state) | map({state: .[0].state, count: length}) | .[] | "\(.state): \(.count)"' # Summary by scanner echo "" echo "=== By Scanner ===" glab api "projects/$project_id/vulnerabilities" --paginate | \ jq -r 'group_by(.scanner.name) | map({scanner: .[0].scanner.name, count: length}) | .[] | "\(.scanner): \(.count)"' ``` ### Workflow 3: Bulk Dismiss False Positives ```bash project_id=123 # Dismiss all info-level findings from specific scanner glab api "projects/$project_id/vulnerabilities?severity=info&state=detected" --paginate | \ jq -r '.[].id' | while read vuln_id; do echo "Dismissing $vuln_id" glab api projects/$project_id/vulnerabilities/$vuln_id/dismiss --method POST \ -f comment="Bulk dismissed - info level findings" done ``` ### Workflow 4: Track Critical Vulnerabilities ```bash project_id=123 # List critical vulnerabilities with details glab api "projects/$project_id/vulnerabilities?severity=critical" --paginate | \ jq -r '.[] | { id: .id, title: .title, state: .state, detected_at: .detected_at, scanner: .scanner.name, identifiers: [.identifiers[]?.name] | join(", ") }' ``` ### Workflow 5: Check for CVEs ```bash project_id=123 cve="CVE-2021-44228" # Search for specific CVE glab api "projects/$project_id/vulnerabilities" --paginate | \ jq -r ".[] | select(.identifiers[]?.name == \"$cve\") | \"ID: \(.id), State: \(.state), Title: \(.title)\"" ``` ### Workflow 6: Export Vulnerabilities ```bash project_id=123 # Export to JSON glab api "projects/$project_id/vulnerabilities" --paginate > vulnerabilities.json # Export to CSV format glab api "projects/$project_id/vulnerabilities" --paginate | \ jq -r '["id","title","severity","state","scanner","detected_at"], (.[] | [.id, .title, .severity, .state, .scanner.name, .detected_at]) | @csv' > vulnerabilities.csv ``` ### Workflow 7: Compare Pipeline Results ```bash project_id=123 # Get findings from specific pipeline pipeline_id=789 glab api "projects/$project_id/vulnerability_findings?pipeline_id=$pipeline_id" | \ jq -r '.[] | "\(.severity): \(.name)"' ``` ## Scanner Types | Scanner | Report Type | Description | |---------|-------------|-------------| | `sast` | SAST | Static Application Security Testing | | `dast` | DAST | Dynamic Application Security Testing | | `dependency_scanning` | Dependency Scanning | Third-party dependency vulnerabilities | | `container_scanning` | Container Scanning | Container image vulnerabilities | | `secret_detection` | Secret Detection | Hardcoded secrets in code | | `coverage_fuzzing` | Coverage Fuzzing | Fuzzing test results | | `api_fuzzing` | API Fuzzing | API fuzzing results | ## Troubleshooting | Issue | Cause | Solution | |-------|-------|----------| | 403 Forbidden | Ultimate required or no access | Check GitLab tier and permissions | | Empty results | No scans run | Configure and run security scanners in CI | | Old vulnerabilities | No recent pipeline | Run new pipeline with security jobs | | Can't dismiss | Already dismissed or resolved | Check current state | | Missing scanner type | Scanner not configured | Add scanner to CI configuration | ## Best Practices 1. **Triage regularly**: Review new vulnerabilities frequently 2. **Document dismissals**: Always add comments explaining why 3. **Track critical issues**: Monitor critical/high severity closely 4. **Integrate with issues**: Create issues for confirmed vulnerabilities 5. **Automate where possible**: Use CI to fail on new critical findings ## Related Documentation - [API Helpers](../shared/docs/API_HELPERS.md) - [Safeguards](../shared/docs/SAFEGUARDS.md) - [Quick Reference](../shared/docs/QUICK_REFERENCE.md) - [GitLab Vulnerabilities API](https://docs.gitlab.com/ee/api/vulnerabilities.html) - [GitLab Vulnerability Findings API](https://docs.gitlab.com/ee/api/vulnerability_findings.html)