# Security Scanning (Phase 4.1 §24) `infra/ci/gitea-workflows/build-and-test.yml`'s `security-scan` job. All free, open-source, no account/signup required for any of them — no paid scanner was added. ## What's scanned | Tool | Checks | Scope | |---|---|---| | `npm audit --audit-level=high` | Known-vulnerable dependencies | Every first-party Node service | | [gitleaks](https://github.com/gitleaks/gitleaks) | Committed secrets (keys, tokens, credentials) | Whole repo | | [hadolint](https://github.com/hadolint/hadolint) | Dockerfile best-practice/security lint | Every first-party Dockerfile | | [shellcheck](https://www.shellcheck.net/) | Shell script correctness/security | `infra/**/*.sh` | | [trivy](https://github.com/aquasecurity/trivy) | OS/library CVEs in a built container image | `platform-api` image (representative — same base/layers as the other Node services) | ## Severity policy - **CRITICAL / HIGH** — fails the build (`security-scan` blocks `build-images`, which blocks `deploy-staging`, which blocks production promotion — see the job dependency chain in the workflow file). - **MEDIUM / LOW** — reported in the job output, never blocks. A build that's permanently red over a low-severity transitive dependency finding nobody can immediately fix trains everyone to ignore red builds, which is worse than not scanning at all. `npm audit --audit-level=high` and trivy's `--severity HIGH,CRITICAL` both implement this directly at the tool level, not via manual triage. ## What's NOT in the automated job (and why) - **Dedicated IaC security linting** (checkov/tflint) — not added. `infra/scripts/validate-compose.sh`, `infra/firewall/validate-firewall.sh`, `ansible-playbook --syntax-check`, and `tofu validate` (all in the `regression` job) already catch structural/syntax problems in the infra code; a dedicated security-policy linter for Terraform/Ansible is a reasonable Phase 5 addition once there's a real cloud footprint to misconfigure, not before. - **DAST/penetration testing** — out of scope for CI; this is a build-time gate, not a running-system test. Covered separately by `docs/PRODUCTION_VALIDATION_CHECKLIST.md`'s security section once real hardware exists. - **SAST beyond hadolint/shellcheck** — the codebase is small enough (a handful of first-party Node services) that `npm audit` + secret scanning + Dockerfile/shell lint cover the realistic risk surface; a dedicated SAST tool (Semgrep, CodeQL) is a reasonable addition once the codebase or team grows enough to justify the added CI time. ## Local reproduction Every check above can be run locally with the exact same free tools — no CI-only dependency. See the `security-scan` job's steps in `infra/ci/gitea-workflows/build-and-test.yml` for the exact commands (they're copy-pasteable).