-
Notifications
You must be signed in to change notification settings - Fork 6
ci(security): security-gates workflow (split 2/4 of #1317) #1463
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
SharedQA
wants to merge
4
commits into
constructorfabric:main
from
SharedQA:claude/split-security-gates
Closed
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
8d55f7b
ci(security): security-gates workflow (split 2/4 of #1317)
cc4d9f2
Merge branch 'main' into claude/split-security-gates
SharedQA 978bed3
ci(security): address review — no-silent-pass, full fetch depth, cont…
2af3061
Merge branch 'main' into claude/split-security-gates
SharedQA File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,165 @@ | ||
| # Security gates — MANDATORY, BLOCKING. | ||
| # | ||
| # Every job here is a required status check on `main` (see | ||
| # scripts/ci/enforce-quality-gates.sh). None of these jobs may use | ||
| # `continue-on-error` or `allow_failure` semantics: a finding either gets | ||
| # fixed, or gets an explicit reviewed suppression in-repo | ||
| # (.trivyignore / .semgrepignore / audit.toml). Silent bypass is not a state. | ||
| # | ||
| # DOCUMENTED EXCEPTION (ratchet-in): the `sast` (Semgrep) job is REPORT-ONLY for | ||
| # now — `semgrep scan` runs WITHOUT `--error`, so findings are surfaced but do | ||
| # not block. This is the single sanctioned non-blocking gate while the p/default | ||
| # baseline is triaged (owner: QA/TAF). Exit condition: add `--error` to the | ||
| # semgrep step to make it hard-fail once the baseline is clean. Every OTHER job | ||
| # here blocks. | ||
| # | ||
| # Rationale: both company reference pipelines (gitlab.constr.dev 931666, | ||
| # 929528) carry Trivy scans with allow_failure that have been red for days. | ||
| # The Constructor/Virtuozzo CI/CD Master Plan §2 mandates hard-fail gates. | ||
| # | ||
| # All third-party actions and the SAST container image are pinned to immutable | ||
| # commit SHAs / digests (supply-chain hygiene — this gate practises what it preaches). | ||
|
|
||
| name: Security Gates | ||
|
|
||
| on: | ||
| pull_request: | ||
| branches: [main] | ||
| workflow_dispatch: | ||
| schedule: | ||
| # Nightly deep sweep (full history / full repo), per Master Plan §2: | ||
| # PR runs scan only the diff; the cron run scans everything. | ||
| - cron: "0 1 * * *" | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| concurrency: | ||
| group: security-gates-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| secrets-scan: | ||
| name: secrets-scan | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 15 | ||
| steps: | ||
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
| with: | ||
| # Full history: TruffleHog diffs base.sha..head.sha on PRs, and a | ||
| # shallow clone (e.g. 50) drops the base commit on any PR with more | ||
| # commits than the depth — the secrets scan then errors or scans | ||
| # incompletely. Correctness of a secrets gate beats the CI minutes. | ||
| fetch-depth: 0 | ||
| persist-credentials: false | ||
| - name: TruffleHog (verified secrets are a hard failure) | ||
| uses: trufflesecurity/trufflehog@1aa1871f9ae24a8c8a3a48a9345514acf42beb39 # v3.82.13 | ||
| with: | ||
| base: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || '' }} | ||
| head: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || '' }} | ||
| extra_args: --results=verified,unknown | ||
|
|
||
| sast: | ||
| name: sast | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 20 | ||
| container: | ||
| image: semgrep/semgrep:1.131.0@sha256:6bd07d7b166b097e1384f41b94a62d8c8a26a4fff8713992c296e053310da01f | ||
| steps: | ||
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Semgrep scan (report-only — ratchet to blocking once baseline triaged) | ||
| # report-only during ratchet-in: p/default surfaces pre-existing findings (JWT ValidateLifetime, | ||
| # Dockerfile USER, …) tracked in TAF for owner triage. Re-add --error to block once the baseline is clean. | ||
| run: semgrep scan --config p/default --exclude-rule generic.secrets.security.detected-generic-secret | ||
|
|
||
| deps-audit: | ||
| name: deps-audit | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 20 | ||
| steps: | ||
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Install cargo-audit | ||
| uses: taiki-e/install-action@375e0c7f08a66b8c2ba7e7eef31a6f91043a81b0 # v2.44.38 | ||
| with: | ||
| tool: cargo-audit@0.22.2 # >=0.22 parses CVSS 4.0 advisories (RUSTSEC-2026-0124) | ||
| - name: Rust dependency audit (RUSTSEC advisories block) | ||
| working-directory: src/backend | ||
| # Waivers tracked in constructorfabric/insight#1339 — remove each as it is fixed: | ||
| # RUSTSEC-2023-0071 (rsa "Marvin", no upstream fix), RUSTSEC-2024-0436 (paste), | ||
| # RUSTSEC-2026-0173 (proc-macro-error2) — last two unmaintained, all transitive. | ||
| run: cargo audit --deny warnings --ignore RUSTSEC-2023-0071 --ignore RUSTSEC-2024-0436 --ignore RUSTSEC-2026-0173 | ||
| - name: Set up Python | ||
| uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 | ||
| with: | ||
| python-version: "3.12" | ||
| - name: Python dependency audit (known CVEs block) | ||
| run: | | ||
| pip install --quiet 'pip-audit==2.10.1' | ||
| rc=0 | ||
| # Transitive advisories we cannot fix from here — same suppression | ||
| # policy as the Rust audit above (fix, or tracked in-repo waiver). | ||
| # Every connector depends on airbyte-cdk (>=7.23.1,<8.0.0), whose | ||
| # latest 7.x (7.23.2) HARD-PINS nltk==3.9.1 and caps cryptography | ||
| # <47.0.0, so the upstream fixes (nltk 3.9.4, cryptography 48.0.1) are | ||
| # unreachable until airbyte-cdk bumps them. Waivers tracked in | ||
| # constructorfabric/insight#1339 — remove each as the CDK fixes it. | ||
| IGNORES=( | ||
| # nltk 3.9.1 (airbyte-cdk pin: nltk==3.9.1) | ||
| --ignore-vuln PYSEC-2026-96 | ||
| --ignore-vuln PYSEC-2026-97 | ||
| --ignore-vuln PYSEC-2026-98 | ||
| --ignore-vuln PYSEC-2026-99 | ||
| --ignore-vuln GHSA-rf74-v2fm-23pw | ||
| --ignore-vuln CVE-2026-33230 | ||
| --ignore-vuln CVE-2026-33231 | ||
| # cryptography 46.0.7 (airbyte-cdk cap: cryptography<47.0.0) | ||
| --ignore-vuln GHSA-537c-gmf6-5ccf | ||
| ) | ||
| # Audit every Python project manifest in the ingestion tree. | ||
| n=0 | ||
| while IFS= read -r f; do | ||
| n=$((n + 1)) | ||
| echo "::group::pip-audit $f" | ||
| case "$f" in | ||
| *requirements*.txt) pip-audit "${IGNORES[@]}" -r "$f" || rc=1 ;; | ||
| *pyproject.toml) (cd "$(dirname "$f")" && pip-audit "${IGNORES[@]}" .) || rc=1 ;; | ||
| esac | ||
| echo "::endgroup::" | ||
| done < <(find src/ingestion -name 'pyproject.toml' -o -name 'requirements*.txt' | grep -v node_modules) | ||
| # A gate that audits nothing is a silent bypass — fail if the discovery | ||
| # found no manifests (tree moved / glob broke) rather than passing green. | ||
| if [ "$n" -eq 0 ]; then | ||
| echo "::error::no Python manifests found under src/ingestion — nothing audited; refusing to pass" | ||
| exit 1 | ||
| fi | ||
| exit $rc | ||
|
SharedQA marked this conversation as resolved.
|
||
|
|
||
| trivy-config: | ||
| name: trivy-config | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 15 | ||
| steps: | ||
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Trivy IaC & Dockerfile misconfiguration scan (CRITICAL/HIGH block) | ||
| uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 | ||
| with: | ||
| scan-type: config | ||
| scan-ref: . | ||
| severity: CRITICAL,HIGH | ||
| exit-code: "1" | ||
| trivyignores: .trivyignore | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| - name: Trivy filesystem vulnerability scan (CRITICAL/HIGH block) | ||
| uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 | ||
| with: | ||
| scan-type: fs | ||
| scan-ref: . | ||
| severity: CRITICAL,HIGH | ||
| exit-code: "1" | ||
| ignore-unfixed: true | ||
| trivyignores: .trivyignore | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # Documented trivy-config waivers — tracked in constructorfabric/insight#1340. | ||
| # The gate stays blocking for every other misconfiguration class; remove each | ||
| # line as the underlying issue is fixed. | ||
| # container runs as root — build/test/tooling images | ||
| AVD-DS-0002 | ||
| # apt-get without --no-install-recommends — toolbox build image | ||
| AVD-DS-0029 | ||
| # frontend Deployment missing securityContext — prod hardening backlog | ||
| AVD-KSV-0118 | ||
| # frontend Deployment root FS not read-only — prod hardening backlog | ||
| AVD-KSV-0014 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.