Skip to content

Introduce RuntimeScenarioExecutor & MetadataEngineConfig #39

Introduce RuntimeScenarioExecutor & MetadataEngineConfig

Introduce RuntimeScenarioExecutor & MetadataEngineConfig #39

name: Security Pipeline
on:
pull_request:
push:
branches:
- master
- main
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
security-core-gates:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup PHP 8.3 (no Docker)
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
coverage: none
tools: composer:v2
extensions: curl, gmp
- name: Install dependencies
env:
COMPOSER_MEMORY_LIMIT: -1
run: composer install --no-interaction --prefer-dist --no-progress
- name: Run must-pass security tests
run: |
php vendor/bin/phpunit --colors=never --no-coverage --do-not-fail-on-warning --do-not-fail-on-risky --filter '/^.*AuthApiTest::testResolveApiTokenPrecedenceHeaderCookieAndQuery$/'
php vendor/bin/phpunit --colors=never --no-coverage --do-not-fail-on-warning --do-not-fail-on-risky --filter '/^.*AuthApiTest::testResolveApiTokenRejectsMalformedHeaderTokenAndFallsBackToCookie$/'
php vendor/bin/phpunit --colors=never --no-coverage --do-not-fail-on-warning --do-not-fail-on-risky --filter '/^.*RequestResponseSecurityContractTest::testCookiePayloadMatrixAndSecurityInterplay$/'
php vendor/bin/phpunit --colors=never --no-coverage --do-not-fail-on-warning --do-not-fail-on-risky --filter '/^.*RequestResponseSecurityContractTest::testCheckCorsSetsHeadersForAllowedOriginOnGet$/'
- name: Run dependency audit (SCA)
env:
COMPOSER_MEMORY_LIMIT: -1
run: composer audit --no-interaction
- name: Enforce hardening gate (P2)
env:
PSFS_SECURITY_STRICT: '1'
run: php scripts/security/hardening_gate.php
- name: Enforce quality gate
run: php scripts/security/quality_gate.php
- name: Upload quality gate report
if: always()
uses: actions/upload-artifact@v4
with:
name: security-quality-gate
path: security/reports/quality-gate.json
if-no-files-found: ignore
- name: Upload hardening gate report
if: always()
uses: actions/upload-artifact@v4
with:
name: security-hardening-gate
path: security/reports/hardening-gate.json
if-no-files-found: ignore
security-static-analysis:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run Semgrep (SAST)
run: |
mkdir -p security/reports
docker run --rm -v "$PWD":/src semgrep/semgrep:latest \
semgrep --config p/owasp-top-ten --error \
--exclude-rule=generic.nginx.security.request-host-used.request-host-used \
--sarif --output /src/security/reports/semgrep.sarif /src
- name: Run Gitleaks (secret scanning)
run: |
mkdir -p security/reports
docker run --rm -v "$PWD":/repo zricethezav/gitleaks:latest \
detect --source /repo --no-git --redact --config /repo/.gitleaks.toml \
--report-format json --report-path /repo/security/reports/gitleaks-report.json
- name: Upload Gitleaks report
if: always()
uses: actions/upload-artifact@v4
with:
name: security-gitleaks
path: security/reports/gitleaks-report.json
if-no-files-found: ignore
- name: Generate SBOM (CycloneDX)
run: |
mkdir -p security/reports
docker run --rm -v "$PWD":/repo anchore/syft:latest \
/repo -o cyclonedx-json=/repo/security/reports/sbom.cyclonedx.json
- name: Upload Semgrep SARIF
if: always()
uses: actions/upload-artifact@v4
with:
name: security-semgrep
path: security/reports/semgrep.sarif
if-no-files-found: ignore
- name: Upload SBOM
if: always()
uses: actions/upload-artifact@v4
with:
name: security-sbom
path: security/reports/sbom.cyclonedx.json
if-no-files-found: ignore