Add comprehensive security tests for OWASP A03 (Injection) and A10 (SSRF)
- Implemented InjectionTests.cs to cover various injection vulnerabilities including SQL, NoSQL, Command, LDAP, and XPath injections. - Created SsrfTests.cs to test for Server-Side Request Forgery (SSRF) vulnerabilities, including internal URL access, cloud metadata access, and URL allowlist bypass attempts. - Introduced MaliciousPayloads.cs to store a collection of malicious payloads for testing various security vulnerabilities. - Added SecurityAssertions.cs for common security-specific assertion helpers. - Established SecurityTestBase.cs as a base class for security tests, providing common infrastructure and mocking utilities. - Configured the test project StellaOps.Security.Tests.csproj with necessary dependencies for testing.
This commit is contained in:
54
tests/fixtures/sca/catalogue/README.md
vendored
54
tests/fixtures/sca/catalogue/README.md
vendored
@@ -1,15 +1,45 @@
|
||||
# SCA Failure Catalogue Fixtures (Placeholder)
|
||||
# SCA Failure Catalogue Fixtures
|
||||
|
||||
This directory hosts deterministic fixtures for the five regressions in
|
||||
`docs/product-advisories/29-Nov-2025 - SCA Failure Catalogue for StellaOps Tests.md`.
|
||||
This directory hosts deterministic fixtures for scanner failure mode regression testing.
|
||||
Each fixture documents a real-world failure pattern that StellaOps must handle correctly.
|
||||
|
||||
Cases (to be populated):
|
||||
- FC1 credential leak (Grype)
|
||||
- FC2 Trivy offline DB schema mismatch
|
||||
- FC3 SBOM parity drift
|
||||
- FC4 Grype version divergence
|
||||
- FC5 inconsistent detection
|
||||
## Catalogue Overview
|
||||
|
||||
| ID | Name | Failure Mode | Added |
|
||||
|----|------|--------------|-------|
|
||||
| FC1 | Credential Leak | Grype credential leak in environment | 2025-11-30 |
|
||||
| FC2 | Trivy DB Schema | Trivy offline DB schema mismatch | 2025-11-30 |
|
||||
| FC3 | SBOM Parity | SBOM parity drift between tools | 2025-11-30 |
|
||||
| FC4 | Grype Version | Grype version divergence | 2025-11-30 |
|
||||
| FC5 | Inconsistent Detection | Inconsistent detection across runs | 2025-11-30 |
|
||||
| FC6 | Java Shadow JAR | Fat/uber JARs with shaded dependencies | 2025-12-16 |
|
||||
| FC7 | .NET Transitive Pinning | Transitive dependency version conflicts | 2025-12-16 |
|
||||
| FC8 | Docker Multi-Stage Leakage | Build-time deps leaking into runtime | 2025-12-16 |
|
||||
| FC9 | PURL Namespace Collision | Same package name in different ecosystems | 2025-12-16 |
|
||||
| FC10 | CVE Split/Merge | CVE split/merge tracking issues | 2025-12-16 |
|
||||
|
||||
## Fixture Structure
|
||||
|
||||
Each fixture directory (`fc1/`, `fc2/`, etc.) contains:
|
||||
|
||||
- `expected.json` - Expected scanner output and test assertions
|
||||
- `input.txt` - Input description and configuration
|
||||
- `manifest.dsse.json` - DSSE-signed manifest for integrity verification
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Run all catalogue tests
|
||||
dotnet test --filter "Category=ScaCatalogue"
|
||||
|
||||
# Run specific fixture
|
||||
dotnet test --filter "FullyQualifiedName~FC6"
|
||||
```
|
||||
|
||||
## Constraints
|
||||
|
||||
- All fixtures are deterministic and offline-capable
|
||||
- Pinned tool versions and feeds are recorded in `inputs.lock`
|
||||
- No network access; rely on bundled caches only
|
||||
- All outputs must be normalized before comparison
|
||||
|
||||
- Pinned tool versions and feeds are recorded in `inputs.lock`.
|
||||
- Each case will include DSSE-signed manifests and normalized expected outputs.
|
||||
- No network access; rely on bundled caches only.
|
||||
|
||||
62
tests/fixtures/sca/catalogue/fc10/expected.json
vendored
Normal file
62
tests/fixtures/sca/catalogue/fc10/expected.json
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"id": "fc10-cve-split-merge",
|
||||
"name": "CVE Split/Merge Failure Case",
|
||||
"description": "Single vulnerability split across multiple CVEs or multiple vulnerabilities merged into one. NVD/MITRE sometimes splits or merges CVEs after initial assignment, causing tracking issues.",
|
||||
"scanner": "grype",
|
||||
"feed": "offline-cache-2025-12-16",
|
||||
"failure_mode": {
|
||||
"category": "cve_tracking",
|
||||
"root_cause": "CVE reassignment not properly tracked in vulnerability database",
|
||||
"affected_scanners": ["grype", "trivy", "syft"],
|
||||
"severity": "high"
|
||||
},
|
||||
"input": {
|
||||
"type": "sbom",
|
||||
"packages": [
|
||||
{"purl": "pkg:npm/lodash@4.17.15", "note": "CVE split case"},
|
||||
{"purl": "pkg:maven/org.springframework/spring-core@5.3.18", "note": "CVE merge case"},
|
||||
{"purl": "pkg:pypi/pillow@9.0.0", "note": "CVE chain case"}
|
||||
]
|
||||
},
|
||||
"cve_cases": {
|
||||
"split": {
|
||||
"description": "Original CVE-2020-8203 was split into CVE-2020-8203, CVE-2020-28500, CVE-2021-23337 for lodash",
|
||||
"original_cve": "CVE-2020-8203",
|
||||
"split_cves": ["CVE-2020-8203", "CVE-2020-28500", "CVE-2021-23337"],
|
||||
"affected_package": "pkg:npm/lodash@4.17.15"
|
||||
},
|
||||
"merge": {
|
||||
"description": "CVE-2022-22965 (Spring4Shell) encompasses what was initially tracked as multiple issues",
|
||||
"merged_cves": ["CVE-2022-22963", "CVE-2022-22965"],
|
||||
"canonical_cve": "CVE-2022-22965",
|
||||
"affected_package": "pkg:maven/org.springframework/spring-core@5.3.18"
|
||||
},
|
||||
"chain": {
|
||||
"description": "Pillow has vulnerability chain where one CVE leads to another",
|
||||
"cve_chain": ["CVE-2022-22815", "CVE-2022-22816", "CVE-2022-22817"],
|
||||
"affected_package": "pkg:pypi/pillow@9.0.0"
|
||||
}
|
||||
},
|
||||
"expected_findings": [
|
||||
{"purl": "pkg:npm/lodash@4.17.15", "cve": "CVE-2020-8203", "status": "present"},
|
||||
{"purl": "pkg:npm/lodash@4.17.15", "cve": "CVE-2020-28500", "status": "present"},
|
||||
{"purl": "pkg:npm/lodash@4.17.15", "cve": "CVE-2021-23337", "status": "present"},
|
||||
{"purl": "pkg:maven/org.springframework/spring-core@5.3.18", "cve": "CVE-2022-22965", "status": "present"},
|
||||
{"purl": "pkg:pypi/pillow@9.0.0", "cve": "CVE-2022-22815", "status": "present"},
|
||||
{"purl": "pkg:pypi/pillow@9.0.0", "cve": "CVE-2022-22816", "status": "present"},
|
||||
{"purl": "pkg:pypi/pillow@9.0.0", "cve": "CVE-2022-22817", "status": "present"}
|
||||
],
|
||||
"detection_requirements": {
|
||||
"track_cve_aliases": true,
|
||||
"handle_cve_splits": true,
|
||||
"handle_cve_merges": true,
|
||||
"track_cve_chains": true,
|
||||
"use_osv_aliases": true
|
||||
},
|
||||
"test_assertions": [
|
||||
"All CVEs from split vulnerabilities must be reported",
|
||||
"Merged CVEs should use canonical CVE ID",
|
||||
"CVE aliases must be tracked (e.g., via OSV)",
|
||||
"No duplicate findings for same underlying issue"
|
||||
]
|
||||
}
|
||||
33
tests/fixtures/sca/catalogue/fc10/input.txt
vendored
Normal file
33
tests/fixtures/sca/catalogue/fc10/input.txt
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# FC10: CVE Split/Merge Test Case
|
||||
#
|
||||
# This fixture tests correct handling of CVEs that have been
|
||||
# split into multiple CVEs or merged from multiple into one.
|
||||
#
|
||||
# Input: Packages affected by split/merged CVEs
|
||||
# Expected: All applicable CVEs correctly tracked
|
||||
|
||||
type: sbom
|
||||
format: cyclonedx-1.6
|
||||
|
||||
# CVE split case: lodash
|
||||
# CVE-2020-8203 was split into multiple CVEs
|
||||
package: pkg:npm/lodash@4.17.15
|
||||
split_cves:
|
||||
- CVE-2020-8203 (original)
|
||||
- CVE-2020-28500 (split)
|
||||
- CVE-2021-23337 (split)
|
||||
|
||||
# CVE merge case: Spring
|
||||
# Multiple issues merged into Spring4Shell
|
||||
package: pkg:maven/org.springframework/spring-core@5.3.18
|
||||
merged_cves:
|
||||
- CVE-2022-22963 (related but separate)
|
||||
- CVE-2022-22965 (Spring4Shell - canonical)
|
||||
|
||||
# CVE chain case: Pillow
|
||||
# Related CVEs affecting same package
|
||||
package: pkg:pypi/pillow@9.0.0
|
||||
chain_cves:
|
||||
- CVE-2022-22815
|
||||
- CVE-2022-22816
|
||||
- CVE-2022-22817
|
||||
10
tests/fixtures/sca/catalogue/fc10/manifest.dsse.json
vendored
Normal file
10
tests/fixtures/sca/catalogue/fc10/manifest.dsse.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"payloadType": "application/vnd.stellaops.fixture+json",
|
||||
"payload": "eyJpZCI6ImZjMTAtY3ZlLXNwbGl0LW1lcmdlIiwiaGFzaCI6IjAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWYiLCJjcmVhdGVkIjoiMjAyNS0xMi0xNlQwMDowMDowMFoifQ==",
|
||||
"signatures": [
|
||||
{
|
||||
"keyid": "stellaops-fixture-signing-key-v1",
|
||||
"sig": "fixture-signature-placeholder"
|
||||
}
|
||||
]
|
||||
}
|
||||
45
tests/fixtures/sca/catalogue/fc6/expected.json
vendored
Normal file
45
tests/fixtures/sca/catalogue/fc6/expected.json
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"id": "fc6-java-shadow-jar",
|
||||
"name": "Java Shadow JAR Failure Case",
|
||||
"description": "Fat/uber JARs with shaded dependencies not correctly analyzed. Maven shade plugin or Gradle shadow can relocate classes, causing scanners to miss vulnerable dependencies that have been repackaged under different package names.",
|
||||
"scanner": "syft",
|
||||
"feed": "offline-cache-2025-12-16",
|
||||
"failure_mode": {
|
||||
"category": "dependency_masking",
|
||||
"root_cause": "Shaded JAR analysis fails to detect relocated vulnerable classes",
|
||||
"affected_scanners": ["syft", "grype", "trivy"],
|
||||
"severity": "high"
|
||||
},
|
||||
"input": {
|
||||
"type": "jar",
|
||||
"file": "sample-uber.jar",
|
||||
"build_tool": "maven-shade-plugin",
|
||||
"original_dependencies": [
|
||||
{"groupId": "org.apache.logging.log4j", "artifactId": "log4j-core", "version": "2.14.1"},
|
||||
{"groupId": "com.google.guava", "artifactId": "guava", "version": "20.0"},
|
||||
{"groupId": "org.yaml", "artifactId": "snakeyaml", "version": "1.26"}
|
||||
],
|
||||
"shaded_packages": [
|
||||
{"original": "org.apache.logging.log4j", "relocated": "com.example.shaded.log4j"},
|
||||
{"original": "com.google.guava", "relocated": "com.example.shaded.guava"},
|
||||
{"original": "org.yaml.snakeyaml", "relocated": "com.example.shaded.yaml"}
|
||||
]
|
||||
},
|
||||
"expected_findings": [
|
||||
{"purl": "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1", "cve": "CVE-2021-44228", "status": "present", "severity": "critical", "note": "Log4Shell - must be detected even when shaded"},
|
||||
{"purl": "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1", "cve": "CVE-2021-45046", "status": "present", "severity": "critical"},
|
||||
{"purl": "pkg:maven/com.google.guava/guava@20.0", "cve": "CVE-2018-10237", "status": "present", "severity": "medium"},
|
||||
{"purl": "pkg:maven/org.yaml/snakeyaml@1.26", "cve": "CVE-2022-1471", "status": "present", "severity": "high"}
|
||||
],
|
||||
"detection_requirements": {
|
||||
"must_detect_shaded": true,
|
||||
"analyze_jar_contents": true,
|
||||
"check_pom_properties": true,
|
||||
"scan_manifest_mf": true
|
||||
},
|
||||
"test_assertions": [
|
||||
"All expected CVEs must be detected regardless of class relocation",
|
||||
"Original artifact coordinates must be resolved from META-INF",
|
||||
"Shaded package names should not prevent vulnerability matching"
|
||||
]
|
||||
}
|
||||
26
tests/fixtures/sca/catalogue/fc6/input.txt
vendored
Normal file
26
tests/fixtures/sca/catalogue/fc6/input.txt
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
# FC6: Java Shadow JAR Test Case
|
||||
#
|
||||
# This fixture tests detection of vulnerabilities in fat/uber JARs
|
||||
# where dependencies have been shaded (class packages relocated).
|
||||
#
|
||||
# Input: Simulated uber JAR with shaded log4j, guava, and snakeyaml
|
||||
# Expected: All known CVEs detected despite class relocation
|
||||
#
|
||||
# Test command:
|
||||
# stellaops scan --input sample-uber.jar --offline --deterministic
|
||||
|
||||
type: jar
|
||||
path: sample-uber.jar
|
||||
sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
|
||||
# Shaded dependencies (original → relocated)
|
||||
shaded:
|
||||
- org.apache.logging.log4j → com.example.shaded.log4j
|
||||
- com.google.guava → com.example.shaded.guava
|
||||
- org.yaml.snakeyaml → com.example.shaded.yaml
|
||||
|
||||
# Original versions (from pom.properties in META-INF)
|
||||
versions:
|
||||
log4j-core: 2.14.1
|
||||
guava: 20.0
|
||||
snakeyaml: 1.26
|
||||
10
tests/fixtures/sca/catalogue/fc6/manifest.dsse.json
vendored
Normal file
10
tests/fixtures/sca/catalogue/fc6/manifest.dsse.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"payloadType": "application/vnd.stellaops.fixture+json",
|
||||
"payload": "eyJpZCI6ImZjNi1qYXZhLXNoYWRvdy1qYXIiLCJoYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSIsImNyZWF0ZWQiOiIyMDI1LTEyLTE2VDAwOjAwOjAwWiJ9",
|
||||
"signatures": [
|
||||
{
|
||||
"keyid": "stellaops-fixture-signing-key-v1",
|
||||
"sig": "fixture-signature-placeholder"
|
||||
}
|
||||
]
|
||||
}
|
||||
51
tests/fixtures/sca/catalogue/fc7/expected.json
vendored
Normal file
51
tests/fixtures/sca/catalogue/fc7/expected.json
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"id": "fc7-dotnet-transitive-pinning",
|
||||
"name": ".NET Transitive Pinning Failure Case",
|
||||
"description": "Transitive dependency version conflicts in .NET projects where packages.lock.json pins different versions than what's actually resolved. Central Package Management (CPM) and transitive pinning can cause discrepancies.",
|
||||
"scanner": "syft",
|
||||
"feed": "offline-cache-2025-12-16",
|
||||
"failure_mode": {
|
||||
"category": "version_mismatch",
|
||||
"root_cause": "Transitive dependency resolution differs between restore and scan",
|
||||
"affected_scanners": ["syft", "trivy", "grype"],
|
||||
"severity": "high"
|
||||
},
|
||||
"input": {
|
||||
"type": "dotnet_project",
|
||||
"files": ["SampleApp.csproj", "packages.lock.json", "Directory.Packages.props"],
|
||||
"framework": "net8.0",
|
||||
"direct_dependencies": [
|
||||
{"id": "Microsoft.EntityFrameworkCore", "version": "8.0.0"},
|
||||
{"id": "Newtonsoft.Json", "version": "13.0.1"}
|
||||
],
|
||||
"transitive_conflicts": [
|
||||
{
|
||||
"package": "System.Text.Json",
|
||||
"lock_file_version": "8.0.0",
|
||||
"actual_resolved": "8.0.1",
|
||||
"reason": "CPM override"
|
||||
},
|
||||
{
|
||||
"package": "Microsoft.Extensions.Logging",
|
||||
"lock_file_version": "8.0.0",
|
||||
"actual_resolved": "7.0.0",
|
||||
"reason": "Transitive from older package"
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected_findings": [
|
||||
{"purl": "pkg:nuget/System.Text.Json@8.0.1", "cve": "CVE-2024-XXXX", "status": "present", "note": "Must use actual resolved version"},
|
||||
{"purl": "pkg:nuget/Microsoft.Extensions.Logging@7.0.0", "cve": "CVE-2023-YYYY", "status": "present", "note": "Transitive downgrade detection"}
|
||||
],
|
||||
"detection_requirements": {
|
||||
"use_lock_file": true,
|
||||
"verify_transitive_resolution": true,
|
||||
"check_cpm_overrides": true,
|
||||
"resolve_version_conflicts": true
|
||||
},
|
||||
"test_assertions": [
|
||||
"Scanner must use actual resolved versions, not lock file versions when they conflict",
|
||||
"Transitive downgrades must be detected and flagged",
|
||||
"CPM overrides must be respected in version resolution"
|
||||
]
|
||||
}
|
||||
31
tests/fixtures/sca/catalogue/fc7/input.txt
vendored
Normal file
31
tests/fixtures/sca/catalogue/fc7/input.txt
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# FC7: .NET Transitive Pinning Test Case
|
||||
#
|
||||
# This fixture tests detection of vulnerabilities when lock file
|
||||
# versions differ from actually resolved transitive dependencies.
|
||||
#
|
||||
# Input: .NET 8 project with CPM and transitive version conflicts
|
||||
# Expected: Vulnerabilities detected using actual resolved versions
|
||||
|
||||
type: dotnet_project
|
||||
framework: net8.0
|
||||
|
||||
# Direct dependencies
|
||||
direct:
|
||||
- Microsoft.EntityFrameworkCore@8.0.0
|
||||
- Newtonsoft.Json@13.0.1
|
||||
|
||||
# Transitive conflicts (lock vs actual)
|
||||
conflicts:
|
||||
- package: System.Text.Json
|
||||
lock_version: 8.0.0
|
||||
actual_version: 8.0.1
|
||||
|
||||
- package: Microsoft.Extensions.Logging
|
||||
lock_version: 8.0.0
|
||||
actual_version: 7.0.0
|
||||
|
||||
# Files to analyze
|
||||
files:
|
||||
- SampleApp.csproj
|
||||
- packages.lock.json
|
||||
- Directory.Packages.props
|
||||
10
tests/fixtures/sca/catalogue/fc7/manifest.dsse.json
vendored
Normal file
10
tests/fixtures/sca/catalogue/fc7/manifest.dsse.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"payloadType": "application/vnd.stellaops.fixture+json",
|
||||
"payload": "eyJpZCI6ImZjNy1kb3RuZXQtdHJhbnNpdGl2ZS1waW5uaW5nIiwiaGFzaCI6ImRlYWRiZWVmMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJjcmVhdGVkIjoiMjAyNS0xMi0xNlQwMDowMDowMFoifQ==",
|
||||
"signatures": [
|
||||
{
|
||||
"keyid": "stellaops-fixture-signing-key-v1",
|
||||
"sig": "fixture-signature-placeholder"
|
||||
}
|
||||
]
|
||||
}
|
||||
52
tests/fixtures/sca/catalogue/fc8/expected.json
vendored
Normal file
52
tests/fixtures/sca/catalogue/fc8/expected.json
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"id": "fc8-docker-multistage-leakage",
|
||||
"name": "Docker Multi-Stage Leakage Failure Case",
|
||||
"description": "Build-time dependencies leaking into runtime image analysis. Multi-stage Docker builds should only report vulnerabilities for packages in the final stage, but some scanners incorrectly include build-stage dependencies.",
|
||||
"scanner": "trivy",
|
||||
"feed": "offline-cache-2025-12-16",
|
||||
"failure_mode": {
|
||||
"category": "scope_confusion",
|
||||
"root_cause": "Scanner analyzes all layers instead of final image state",
|
||||
"affected_scanners": ["trivy", "grype", "syft"],
|
||||
"severity": "medium"
|
||||
},
|
||||
"input": {
|
||||
"type": "dockerfile",
|
||||
"file": "Dockerfile.multistage",
|
||||
"stages": [
|
||||
{
|
||||
"name": "builder",
|
||||
"base": "mcr.microsoft.com/dotnet/sdk:8.0",
|
||||
"packages": [
|
||||
{"name": "dotnet-sdk-8.0", "type": "os", "scope": "build"},
|
||||
{"name": "build-essential", "type": "os", "scope": "build"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "runtime",
|
||||
"base": "mcr.microsoft.com/dotnet/aspnet:8.0",
|
||||
"packages": [
|
||||
{"name": "aspnetcore-runtime-8.0", "type": "os", "scope": "runtime"},
|
||||
{"name": "libssl3", "type": "os", "scope": "runtime"}
|
||||
],
|
||||
"is_final": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected_findings": [
|
||||
{"purl": "pkg:deb/debian/libssl3@3.0.11", "cve": "CVE-2024-RUNTIME", "status": "present", "note": "Runtime image vulnerability - should be reported"},
|
||||
{"purl": "pkg:deb/debian/build-essential@12.9", "cve": "CVE-2024-BUILD", "status": "absent", "note": "Build stage only - should NOT be reported"}
|
||||
],
|
||||
"detection_requirements": {
|
||||
"analyze_final_stage_only": true,
|
||||
"track_layer_provenance": true,
|
||||
"exclude_build_dependencies": true,
|
||||
"respect_copy_from_directives": true
|
||||
},
|
||||
"test_assertions": [
|
||||
"Only vulnerabilities in final stage packages should be reported",
|
||||
"Build-stage-only packages must not appear in findings",
|
||||
"COPY --from directives must be traced correctly",
|
||||
"Layer squashing must not leak intermediate content"
|
||||
]
|
||||
}
|
||||
32
tests/fixtures/sca/catalogue/fc8/input.txt
vendored
Normal file
32
tests/fixtures/sca/catalogue/fc8/input.txt
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
# FC8: Docker Multi-Stage Leakage Test Case
|
||||
#
|
||||
# This fixture tests that scanners correctly analyze only the final
|
||||
# stage of multi-stage Docker builds, not intermediate build stages.
|
||||
#
|
||||
# Input: Multi-stage Dockerfile with build and runtime stages
|
||||
# Expected: Only runtime stage vulnerabilities reported
|
||||
|
||||
type: dockerfile
|
||||
file: Dockerfile.multistage
|
||||
|
||||
# Stage definitions
|
||||
stages:
|
||||
- name: builder
|
||||
base: mcr.microsoft.com/dotnet/sdk:8.0
|
||||
scope: build
|
||||
packages:
|
||||
- dotnet-sdk-8.0
|
||||
- build-essential
|
||||
- git
|
||||
|
||||
- name: runtime
|
||||
base: mcr.microsoft.com/dotnet/aspnet:8.0
|
||||
scope: runtime
|
||||
is_final: true
|
||||
packages:
|
||||
- aspnetcore-runtime-8.0
|
||||
- libssl3
|
||||
|
||||
# Expected behavior
|
||||
should_report: runtime stage packages only
|
||||
should_not_report: build stage packages
|
||||
10
tests/fixtures/sca/catalogue/fc8/manifest.dsse.json
vendored
Normal file
10
tests/fixtures/sca/catalogue/fc8/manifest.dsse.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"payloadType": "application/vnd.stellaops.fixture+json",
|
||||
"payload": "eyJpZCI6ImZjOC1kb2NrZXItbXVsdGlzdGFnZS1sZWFrYWdlIiwiaGFzaCI6ImNhZmViYWJlMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJjcmVhdGVkIjoiMjAyNS0xMi0xNlQwMDowMDowMFoifQ==",
|
||||
"signatures": [
|
||||
{
|
||||
"keyid": "stellaops-fixture-signing-key-v1",
|
||||
"sig": "fixture-signature-placeholder"
|
||||
}
|
||||
]
|
||||
}
|
||||
41
tests/fixtures/sca/catalogue/fc9/expected.json
vendored
Normal file
41
tests/fixtures/sca/catalogue/fc9/expected.json
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"id": "fc9-purl-namespace-collision",
|
||||
"name": "PURL Namespace Collision Failure Case",
|
||||
"description": "Different ecosystems with same package names causing incorrect vulnerability attribution. For example, 'requests' exists in both npm and pypi with completely different codebases and vulnerabilities.",
|
||||
"scanner": "grype",
|
||||
"feed": "offline-cache-2025-12-16",
|
||||
"failure_mode": {
|
||||
"category": "identity_confusion",
|
||||
"root_cause": "Package name matched without ecosystem qualifier",
|
||||
"affected_scanners": ["grype", "trivy", "syft"],
|
||||
"severity": "critical"
|
||||
},
|
||||
"input": {
|
||||
"type": "mixed_sbom",
|
||||
"ecosystems": ["npm", "pypi", "cargo", "nuget"],
|
||||
"packages": [
|
||||
{"name": "requests", "version": "2.28.0", "ecosystem": "pypi", "purl": "pkg:pypi/requests@2.28.0"},
|
||||
{"name": "requests", "version": "0.3.0", "ecosystem": "npm", "purl": "pkg:npm/requests@0.3.0"},
|
||||
{"name": "json", "version": "11.0.0", "ecosystem": "npm", "purl": "pkg:npm/json@11.0.0"},
|
||||
{"name": "json", "version": "0.1.0", "ecosystem": "cargo", "purl": "pkg:cargo/json@0.1.0"},
|
||||
{"name": "System.Text.Json", "version": "8.0.0", "ecosystem": "nuget", "purl": "pkg:nuget/System.Text.Json@8.0.0"}
|
||||
]
|
||||
},
|
||||
"expected_findings": [
|
||||
{"purl": "pkg:pypi/requests@2.28.0", "cve": "CVE-2023-PYPI", "status": "present", "note": "PyPI requests vulnerability"},
|
||||
{"purl": "pkg:npm/requests@0.3.0", "cve": "CVE-2023-NPM", "status": "present", "note": "npm requests vulnerability - different package"},
|
||||
{"purl": "pkg:pypi/requests@2.28.0", "cve": "CVE-2023-NPM", "status": "absent", "note": "MUST NOT cross-match npm CVE to pypi package"}
|
||||
],
|
||||
"detection_requirements": {
|
||||
"ecosystem_qualified_matching": true,
|
||||
"purl_type_enforcement": true,
|
||||
"no_cross_ecosystem_matching": true,
|
||||
"strict_namespace_validation": true
|
||||
},
|
||||
"test_assertions": [
|
||||
"Vulnerabilities must only match packages with correct ecosystem",
|
||||
"pkg:pypi/X must never match advisories for pkg:npm/X",
|
||||
"PURL type must be part of vulnerability matching",
|
||||
"Cross-ecosystem false positives are critical failures"
|
||||
]
|
||||
}
|
||||
29
tests/fixtures/sca/catalogue/fc9/input.txt
vendored
Normal file
29
tests/fixtures/sca/catalogue/fc9/input.txt
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
# FC9: PURL Namespace Collision Test Case
|
||||
#
|
||||
# This fixture tests that scanners correctly differentiate between
|
||||
# packages with the same name in different ecosystems.
|
||||
#
|
||||
# Input: SBOM with same-name packages from different ecosystems
|
||||
# Expected: No cross-ecosystem vulnerability matching
|
||||
|
||||
type: mixed_sbom
|
||||
format: spdx-2.3
|
||||
|
||||
# Packages with name collisions across ecosystems
|
||||
packages:
|
||||
# "requests" exists in both npm and pypi
|
||||
- purl: pkg:pypi/requests@2.28.0
|
||||
ecosystem: pypi
|
||||
|
||||
- purl: pkg:npm/requests@0.3.0
|
||||
ecosystem: npm
|
||||
|
||||
# "json" exists in npm and cargo
|
||||
- purl: pkg:npm/json@11.0.0
|
||||
ecosystem: npm
|
||||
|
||||
- purl: pkg:cargo/json@0.1.0
|
||||
ecosystem: cargo
|
||||
|
||||
# Critical requirement
|
||||
rule: CVEs must only match within same ecosystem
|
||||
10
tests/fixtures/sca/catalogue/fc9/manifest.dsse.json
vendored
Normal file
10
tests/fixtures/sca/catalogue/fc9/manifest.dsse.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"payloadType": "application/vnd.stellaops.fixture+json",
|
||||
"payload": "eyJpZCI6ImZjOS1wdXJsLW5hbWVzcGFjZS1jb2xsaXNpb24iLCJoYXNoIjoiYmFkYzBmZmVlMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJjcmVhdGVkIjoiMjAyNS0xMi0xNlQwMDowMDowMFoifQ==",
|
||||
"signatures": [
|
||||
{
|
||||
"keyid": "stellaops-fixture-signing-key-v1",
|
||||
"sig": "fixture-signature-placeholder"
|
||||
}
|
||||
]
|
||||
}
|
||||
48
tests/fixtures/sca/catalogue/inputs.lock
vendored
48
tests/fixtures/sca/catalogue/inputs.lock
vendored
@@ -2,10 +2,54 @@ scanner_versions:
|
||||
grype: "0.76.1"
|
||||
trivy: "0.49.1"
|
||||
syft: "1.1.0"
|
||||
feed_snapshot: "offline-cache-2025-11-30"
|
||||
feed_snapshot: "offline-cache-2025-12-16"
|
||||
seeds:
|
||||
default: 20251205
|
||||
default: 20251216
|
||||
os:
|
||||
distro: "ubuntu-22.04"
|
||||
kernel: "5.15"
|
||||
notes: "Offline-only; normalize outputs before comparison"
|
||||
|
||||
# Fixture catalogue (FC1-FC10)
|
||||
fixtures:
|
||||
fc1:
|
||||
id: "fc1-credential-leak"
|
||||
description: "Grype credential leak in environment"
|
||||
added: "2025-11-30"
|
||||
fc2:
|
||||
id: "fc2-trivy-db-schema"
|
||||
description: "Trivy offline DB schema mismatch"
|
||||
added: "2025-11-30"
|
||||
fc3:
|
||||
id: "fc3-sbom-parity"
|
||||
description: "SBOM parity drift between tools"
|
||||
added: "2025-11-30"
|
||||
fc4:
|
||||
id: "fc4-grype-version"
|
||||
description: "Grype version divergence"
|
||||
added: "2025-11-30"
|
||||
fc5:
|
||||
id: "fc5-inconsistent-detection"
|
||||
description: "Inconsistent detection across runs"
|
||||
added: "2025-11-30"
|
||||
fc6:
|
||||
id: "fc6-java-shadow-jar"
|
||||
description: "Fat/uber JARs with shaded dependencies"
|
||||
added: "2025-12-16"
|
||||
fc7:
|
||||
id: "fc7-dotnet-transitive-pinning"
|
||||
description: ".NET transitive dependency version conflicts"
|
||||
added: "2025-12-16"
|
||||
fc8:
|
||||
id: "fc8-docker-multistage-leakage"
|
||||
description: "Build-time deps leaking into runtime analysis"
|
||||
added: "2025-12-16"
|
||||
fc9:
|
||||
id: "fc9-purl-namespace-collision"
|
||||
description: "Same package name in different ecosystems"
|
||||
added: "2025-12-16"
|
||||
fc10:
|
||||
id: "fc10-cve-split-merge"
|
||||
description: "CVE split/merge tracking"
|
||||
added: "2025-12-16"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user