diff --git a/.github/workflows/osv-scanner-pr.yml b/.github/workflows/osv-scanner-pr.yml index 4d5c4475..c7238a97 100644 --- a/.github/workflows/osv-scanner-pr.yml +++ b/.github/workflows/osv-scanner-pr.yml @@ -39,3 +39,13 @@ jobs: # (medium_or_higher), not by failing this check. Keep the check green # so it only supplies the analysis; the ruleset decides blocking. fail-on-vuln: false + # RELIABILITY: resolve Maven parent POMs through Google's byte-identical + # Maven Central mirror instead of repo.maven.apache.org, which + # intermittently 429s during transitive resolution (e.g. + # spring-boot-starter-parent). Same maven2 layout, same bytes -> no + # coverage loss; transitive scanning stays fully enabled. See + # security-scan.yml for the full rationale. + scan-args: |- + --maven-registry=https://maven-central.storage-download.googleapis.com/maven2 + -r + ./ diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml index 7a077b05..05c96a33 100644 --- a/.github/workflows/security-scan.yml +++ b/.github/workflows/security-scan.yml @@ -57,6 +57,23 @@ jobs: security-events: write with: fail-on-vuln: true + # RELIABILITY: point Maven transitive (parent-POM) resolution at Google's + # byte-identical Maven Central mirror instead of repo.maven.apache.org. + # osv-scanner resolves parent POMs (e.g. spring-boot-starter-parent) over + # its own HTTP client (osv-scalibr pomxmlnet -> defaultRegistry.URL); the + # canonical Central host intermittently returns HTTP 429, which failed this + # required gate on APPROVED Maven PRs with "No issues found" (a network + # flake, not a real vuln). The mirror serves the same maven2 layout and the + # same bytes, so coverage is unchanged -- this ONLY swaps the default + # registry host. Repos' own pom.xml are still added on top + # (scalibr AddRegistry), and transitive scanning stays fully enabled (no + # --no-resolve). Caching ~/.m2 or a settings.xml would NOT help: + # osv-scanner never reads ~/.m2/repository and parses settings.xml only for + # auth, not . --maven-registry is the only effective lever. + scan-args: |- + --maven-registry=https://maven-central.storage-download.googleapis.com/maven2 + -r + ./ dependency-review: if: github.event.action != 'closed' diff --git a/.github/workflows/strix.yml b/.github/workflows/strix.yml index 9214c44f..071927b7 100644 --- a/.github/workflows/strix.yml +++ b/.github/workflows/strix.yml @@ -3,8 +3,55 @@ name: Strix Security Scan on: push: branches: [main, develop, master] + # Skip scans for changes that touch ONLY non-executable documentation and + # image assets. A change whose entire diff is these paths has no source, + # build, config, or workflow logic for a code security scanner to analyze, + # so skipping it loses no coverage while freeing shared runner capacity. + # Conservative by design: only file EXTENSIONS/paths that can never contain + # executable logic are listed (no source, no *.txt, no *.svg, no CODEOWNERS, + # no build scripts). A diff touching even one non-listed file still scans. + # The weekly full-tree schedule below re-scans protected branches with no + # path filter, backstopping every path. + paths-ignore: + - '**/*.md' + - '**/*.markdown' + - '**/*.rst' + - '**/*.png' + - '**/*.jpg' + - '**/*.jpeg' + - '**/*.gif' + - '**/*.webp' + - '**/*.bmp' + - '**/*.ico' + - 'LICENSE' + - 'LICENSE.*' + - 'COPYING' + - '.github/ISSUE_TEMPLATE/**' pull_request_target: types: [opened, synchronize, reopened, ready_for_review, closed] + # Same conservative doc/image-only skip for PR scans. GitHub evaluates these + # path filters against the PR's full base..head diff, so a PR is skipped only + # when EVERY changed file is a non-executable doc/image asset; any code, + # config, build, or workflow change still triggers the scan. The head.sha + # concurrency design (below) is unchanged. For PRs the merge scheduler + # manages, same-head Strix evidence is still forced at merge time via + # workflow_dispatch (which paths-ignore does not affect), so merged code + # never loses evidence. + paths-ignore: + - '**/*.md' + - '**/*.markdown' + - '**/*.rst' + - '**/*.png' + - '**/*.jpg' + - '**/*.jpeg' + - '**/*.gif' + - '**/*.webp' + - '**/*.bmp' + - '**/*.ico' + - 'LICENSE' + - 'LICENSE.*' + - 'COPYING' + - '.github/ISSUE_TEMPLATE/**' schedule: # Weekly scan on protected branches (Mondays at 03:00 UTC). - cron: '0 3 * * 1' @@ -61,7 +108,14 @@ jobs: strix: if: github.event_name != 'pull_request_target' || github.event.action != 'closed' - timeout-minutes: 120 + # The scan itself is hard-bounded to 30 min (the "Run Strix (quick)" step + # has timeout-minutes: 30 and exports STRIX_TOTAL_TIMEOUT_SECONDS=1800), and + # every other step is quick or self-bounded (self-test is 2 min). A healthy + # run finishes well under 50 min. The 120 cap only ever bit HUNG runs (e.g. + # a network stall in pip/git with no per-step timeout); 60 min still clears + # the realistic worst case with margin while freeing a stuck runner in half + # the time. Fail-closed: hitting the cap fails the run, never passes it. + timeout-minutes: 60 runs-on: ubuntu-latest env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true