Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/container-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ jobs:
CONTAINER_SCAN_MERGED_SARIF_OUTPUT: container-scan-platform-backend-merged.sarif

# SCA / CVE
TRIVY_IGNOREFILE: .github/scripts/suppress_trivy.yaml
OSV_IGNOREFILE: .github/scripts/suppress_osv_scanner.toml
TRIVY_IGNOREFILE: ci/suppress_trivy.yaml
OSV_IGNOREFILE: ci/suppress_osv_scanner.toml
TRIVY_SCA_SARIF_OUTPUT: sca-trivy-container.sarif
OSV_SCA_SARIF_OUTPUT: sca-osv-container.sarif

Expand All @@ -44,15 +44,15 @@ jobs:

- name: Setup tools
run: |
bash .github/scripts/setup-tools.sh \
bash ci/setup-tools.sh \
--install-tool trivy,osv-scanner,opengrep,hadolint,semgrep-rules

- name: Run SAST scanning
run: python .github/scripts/container_scan.py --scan-type sast
run: python ci/container_scan.py --scan-type sast

- name: Run SCA scanning
if: always()
run: python .github/scripts/container_scan.py --scan-type sca --image ${{ env.IMAGE_NAME }}
run: python ci/container_scan.py --scan-type sca --image ${{ env.IMAGE_NAME }}

- name: Upload Trivy SARIF to GitHub Security tab
id: upload_trivy
Expand Down Expand Up @@ -89,7 +89,7 @@ jobs:
- name: Merge all SARIF reports
if: always()
run: |
python .github/scripts/container_scan.py \
python ci/container_scan.py \
--merge-sarif "${{ env.TRIVY_SCA_SARIF_OUTPUT }}" "${{ env.OSV_SCA_SARIF_OUTPUT }}" "${{ env.OPENGREP_SAST_SARIF_OUTPUT }}" "${{ env.HADOLINT_SAST_SARIF_OUTPUT }}" \
--merge-output "${{ env.CONTAINER_SCAN_MERGED_SARIF_OUTPUT }}"

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/sast.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
semgrep-rules/generic semgrep-rules/problem-based-packs semgrep-rules/bash semgrep-rules/java auto
semgrep-rules/yaml semgrep-rules/package_managers p/default
OPENGREP_EXCLUDE: >-
*.sarif .github/scripts Dockerfile* .pre-commit-config.yaml docs/** README.md AGENTS.md
*.sarif ci/ Dockerfile* .pre-commit-config.yaml docs/** README.md AGENTS.md
OPENGREP_SARIF_OUTPUT: sast-semgrep-app.sarif

steps:
Expand All @@ -32,10 +32,10 @@ jobs:
python-version: '3.14.4'

- name: Setup tools
run: bash .github/scripts/setup-tools.sh --install-tool opengrep,semgrep-rules
run: bash ci/setup-tools.sh --install-tool opengrep,semgrep-rules

- name: Run SAST scanning
run: python .github/scripts/sast_scan.py
run: python ci/sast_scan.py

- name: Upload Semgrep SARIF to GitHub Security tab
id: upload_semgrep
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/sca.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ jobs:
security-events: write # required for uploading SCA results to github security
env:
SBOM_PATH: target/bom.json
TRIVY_IGNOREFILE: .github/scripts/suppress_trivy.yaml
OSV_IGNOREFILE: .github/scripts/suppress_osv_scanner.toml
TRIVY_IGNOREFILE: ci/suppress_trivy.yaml
OSV_IGNOREFILE: ci/suppress_osv_scanner.toml
TRIVY_SARIF_OUTPUT: trivy-platform-backend.sarif
OSV_SARIF_OUTPUT: osv-scanner-platform-backend.sarif
SCA_MERGED_SARIF_OUTPUT: SCA-platform-backend-merged.sarif
Expand All @@ -42,10 +42,10 @@ jobs:
run: mvn dependency:resolve -q

- name: Setup tools
run: bash .github/scripts/setup-tools.sh --install-tool trivy,osv-scanner --sbom-ecosystem maven
run: bash ci/setup-tools.sh --install-tool trivy,osv-scanner --sbom-ecosystem maven

- name: Run SCA tools
run: python .github/scripts/sca_scan.py
run: python ci/sca_scan.py

- name: Upload Trivy SARIF to GitHub Security tab
id: upload_trivy
Expand Down
18 changes: 9 additions & 9 deletions .github/README.md → ci/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ All three trigger independently and run in parallel; each uploads its own SARIF
## 3. Tool installation (`setup-tools.sh`)

```bash
bash .github/scripts/setup-tools.sh --install-tool <tool1,tool2,...|all> [--sbom-ecosystem maven|npm|none]
bash ci/setup-tools.sh --install-tool <tool1,tool2,...|all> [--sbom-ecosystem maven|npm|none]
```

`--install-tool` accepts a comma-separated list (or `all`):
Expand Down Expand Up @@ -88,7 +88,7 @@ Both steps run regardless of each other (`if: always()`), all four SARIF files a
`container_scan.py` is a single CLI shared by both scan types:

```
$ python3 .github/scripts/container_scan.py --help
$ python3 ci/container_scan.py --help
usage: sec-orchestrator [-h] [-s {sast,sca}] [-i IMAGE] [--merge-sarif SARIF_FILE [SARIF_FILE ...]] [--merge-output MERGE_OUTPUT]

Agnostic DevSecOps Container scanning Pipeline Orchestrator
Expand All @@ -107,9 +107,9 @@ options:
**Running it locally:**
```bash
docker build -t app:local .
bash .github/scripts/setup-tools.sh --install-tool trivy,osv-scanner,opengrep,hadolint,semgrep-rules
python .github/scripts/container_scan.py --scan-type sast
python .github/scripts/container_scan.py --scan-type sca --image app:local
bash ci/setup-tools.sh --install-tool trivy,osv-scanner,opengrep,hadolint,semgrep-rules
python ci/container_scan.py --scan-type sast
python ci/container_scan.py --scan-type sca --image app:local
```

## 5. Pipeline: Software Composition Analysis (SCA)
Expand All @@ -121,8 +121,8 @@ Both tools need to be installed first, same as Container Scanning, via `setup-to
**Running it locally:**
```bash
mvn dependency:resolve -q
bash .github/scripts/setup-tools.sh --install-tool trivy,osv-scanner --sbom-ecosystem maven # -> mvn org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom -> target/bom.json
python .github/scripts/sca_scan.py
bash ci/setup-tools.sh --install-tool trivy,osv-scanner --sbom-ecosystem maven # -> mvn org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom -> target/bom.json
python ci/sca_scan.py
```

`mvn dependency:resolve` pulls the full dependency tree into `.m2` first, so the CycloneDX plugin has something resolved to build the SBOM from.
Expand All @@ -137,8 +137,8 @@ Trivy and OSV-Scanner both run against the SBOM, findings are evaluated by `pars

**Running it locally:**
```bash
bash .github/scripts/setup-tools.sh --install-tool opengrep,semgrep-rules
python .github/scripts/sast_scan.py
bash ci/setup-tools.sh --install-tool opengrep,semgrep-rules
python ci/sast_scan.py
```

---
Expand Down
4 changes: 2 additions & 2 deletions .github/scripts/container_scan.py → ci/container_scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
IMAGE_NAME = os.getenv("IMAGE_NAME", "platform-backend:local")

# --- SCA / CVE (Trivy + OSV) ---
TRIVY_IGNOREFILE = os.getenv("TRIVY_IGNOREFILE", ".github/scripts/suppress_trivy.yaml")
OSV_IGNOREFILE = os.getenv("OSV_IGNOREFILE", ".github/scripts/suppress_osv_scanner.toml")
TRIVY_IGNOREFILE = os.getenv("TRIVY_IGNOREFILE", "ci/suppress_trivy.yaml")
OSV_IGNOREFILE = os.getenv("OSV_IGNOREFILE", "ci/suppress_osv_scanner.toml")
TRIVY_SCA_SARIF_OUTPUT = os.getenv("TRIVY_SCA_SARIF_OUTPUT", "sca-trivy-container.sarif")
OSV_SCA_SARIF_OUTPUT = os.getenv("OSV_SCA_SARIF_OUTPUT", "sca-osv-container.sarif")

Expand Down
2 changes: 1 addition & 1 deletion .github/scripts/parse_sarif.py → ci/parse_sarif.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ def evaluate(sarif_paths):
return EvaluationResult(
gate_failed=max_score >= 8,
gate_warn=5 <= max_score < 8,
)
)
2 changes: 1 addition & 1 deletion .github/scripts/sast_scan.py → ci/sast_scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
).split()
OPENGREP_EXCLUDE = os.getenv(
"OPENGREP_EXCLUDE",
"*.sarif .github/scripts Dockerfile* .pre-commit-config.yaml docs/** README.md AGENTS.md"
"*.sarif ci/ Dockerfile* .pre-commit-config.yaml docs/** README.md AGENTS.md"
).split()
OPENGREP_SARIF_OUTPUT = os.getenv("OPENGREP_SARIF_OUTPUT", "sast-opengrep-app.sarif")

Expand Down
26 changes: 13 additions & 13 deletions .github/scripts/sca_scan.py → ci/sca_scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@

# Configurable values
SBOM_PATH = os.getenv("SBOM_PATH", "target/bom.json")
TRIVY_IGNOREFILE = os.getenv("TRIVY_IGNOREFILE", ".github/scripts/suppress_trivy.yaml")
OSV_IGNOREFILE = os.getenv("OSV_IGNOREFILE", ".github/scripts/suppress_osv_scanner.toml")
TRIVY_IGNOREFILE = os.getenv("TRIVY_IGNOREFILE", "ci/suppress_trivy.yaml")
OSV_IGNOREFILE = os.getenv("OSV_IGNOREFILE", "ci/suppress_osv_scanner.toml")
TRIVY_SARIF_OUTPUT = os.getenv("TRIVY_SARIF_OUTPUT", "trivy-platform-backend.sarif")
OSV_SARIF_OUTPUT = os.getenv("OSV_SARIF_OUTPUT", "osv-scanner-platform-backend.sarif")
SCA_MERGED_SARIF_OUTPUT = os.getenv("SCA_MERGED_SARIF_OUTPUT", "SCA-platform-backend-merged.sarif")
Expand All @@ -36,7 +36,7 @@ def run_trivy():

def run_osv_scanner():
cmd = [
"osv-scanner", "scan", "source",
"osv-scanner", "scan", "source",
"--lockfile", SBOM_PATH,
"--config", OSV_IGNOREFILE,
"--format", "sarif",
Expand Down Expand Up @@ -73,41 +73,41 @@ def main():
sarif_files = {"trivy": TRIVY_SARIF_OUTPUT, "osv-scanner": OSV_SARIF_OUTPUT}
tool_status = {} # "PASSED" | "WARNING" | "FAILED" | "ERROR"
gate_failed = False

# Run each SCA tool and collect their exit codes
for name, tool_fn in tools.items():
exit_code = tool_fn()
logger.info("-" * 40)

path = sarif_files[name]
if exit_code != 0 and os.path.exists(path):
logger.error(f"{RED}[!] {name} exit code {exit_code} but wrote {path}{RESET}")
tool_status[name] = "ERROR"
gate_failed = True

merge_sarifs() # combined artifact only, not used for the gate decision

# Evaluate each SARIF file for gate decision
for name, path in sarif_files.items():
if name in tool_status:
continue # already flagged ERROR above, don't overwrite it

if not os.path.exists(path):
logger.error(f"{RED}[!] {name} SARIF missing: {path},tool failed to run (not a vulnerability){RESET}")
tool_status[name] = "ERROR"
gate_failed = True
continue

eval_result = evaluate(path)

if eval_result.gate_failed:
tool_status[name] = "FAILED" # this tool found CVSS >= 8.0
gate_failed = True
elif eval_result.gate_warn:
tool_status[name] = "WARNING" # this tool found 5.0 <= CVSS < 8.0
else:
tool_status[name] = "PASSED" # this tool found nothing >= 5.0

# Print summary of results
logger.info(f"\n{BOLD}========== SCA PIPELINE SUMMARY =========={RESET}")
for name, status in tool_status.items():
Expand All @@ -120,11 +120,11 @@ def main():
else:
logger.error(f"[{name}]: {RED}FAILED (CVSS >= 8.0 found){RESET}")
logger.info(f"{BOLD}=========================================={RESET}\n")

# Exit with non-zero code if any tool failed the gate
if gate_failed:
logger.error(f"{RED}One or more SCA tools failed the gate check.{RESET}")
sys.exit(1)

if __name__ == "__main__":
main()
main()
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[[IgnoredVulns]]
id = "GHSA-5jmj-h7xm-6q6v"
ignoreUntil = 2026-09-30
reason = "The proposed fix version 2.21.5 not yet released"
reason = "The proposed fix version 2.21.5 not yet released"
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
vulnerabilities:
- id: CVE-2026-54515
statement: "The proposed fix version 2.21.5 not yet released"
statement: "The proposed fix version 2.21.5 not yet released"