refactor: reduce complexity hot paths and streamline README #6
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
| 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: Start PHP service only | |
| run: docker compose up -d --no-deps php | |
| - name: Install dependencies | |
| run: | | |
| PHP_CONTAINER="$(docker compose ps -q php)" | |
| docker exec "$PHP_CONTAINER" composer install --no-interaction --prefer-dist | |
| - name: Run must-pass security tests | |
| run: | | |
| PHP_CONTAINER="$(docker compose ps -q php)" | |
| docker exec "$PHP_CONTAINER" php vendor/bin/phpunit --colors=never --no-coverage --do-not-fail-on-warning --do-not-fail-on-risky --filter '/^.*AuthApiTest::testResolveApiTokenPrecedenceHeaderCookieAndQuery$/' | |
| docker exec "$PHP_CONTAINER" php vendor/bin/phpunit --colors=never --no-coverage --do-not-fail-on-warning --do-not-fail-on-risky --filter '/^.*AuthApiTest::testResolveApiTokenRejectsMalformedHeaderTokenAndFallsBackToCookie$/' | |
| docker exec "$PHP_CONTAINER" php vendor/bin/phpunit --colors=never --no-coverage --do-not-fail-on-warning --do-not-fail-on-risky --filter '/^.*RequestResponseSecurityContractTest::testCookiePayloadMatrixAndSecurityInterplay$/' | |
| docker exec "$PHP_CONTAINER" 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) | |
| run: | | |
| PHP_CONTAINER="$(docker compose ps -q php)" | |
| docker exec "$PHP_CONTAINER" composer audit --no-interaction | |
| - name: Enforce hardening gate (P2) | |
| run: | | |
| PHP_CONTAINER="$(docker compose ps -q php)" | |
| docker exec -e PSFS_SECURITY_STRICT=1 "$PHP_CONTAINER" php scripts/security/hardening_gate.php | |
| - name: Enforce quality gate | |
| run: | | |
| PHP_CONTAINER="$(docker compose ps -q php)" | |
| docker exec "$PHP_CONTAINER" 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 |