name: Security # Scans run alongside CI on every PR and on pushes to the long-lived branches. # This is the DETECTIVE layer (backstop). The PREVENTIVE layer is the local # pre-commit hook — this catches anything that slipped past it (e.g. --no-verify) # and scans the full history, not just the staged diff. on: push: branches: [main, develop] pull_request: jobs: secrets: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # full history so gitleaks scans every commit - name: Secret scan (gitleaks) # Run the binary directly — the container-mode runner has no Docker socket, # so `docker run` isn't available inside a job. run: | GITLEAKS_VERSION=8.18.4 curl -sSL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" -o /tmp/gitleaks.tar.gz tar -xzf /tmp/gitleaks.tar.gz -C /tmp gitleaks /tmp/gitleaks detect --source=. --redact --verbose --exit-code=1 dependencies: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-dotnet@v4 with: dotnet-version: '10.0.x' - name: Restore run: dotnet restore InboxIntel.sln - name: .NET vulnerable packages (fail on any) # Match dotnet's own "has the following vulnerable packages" line rather # than raw severity words, so package/project names can't false-positive. run: | dotnet list InboxIntel.sln package --vulnerable --include-transitive 2>&1 | tee vuln.txt if grep -q "has the following vulnerable" vuln.txt; then echo "::error::Vulnerable NuGet packages detected — see the table above." exit 1 fi echo "No vulnerable NuGet packages." - uses: actions/setup-node@v4 with: node-version: '20' - name: npm audit (production deps, fail on high/critical) # Only production dependencies ship to users; dev-only toolchain advisories # (Vite/PostCSS/etc.) shouldn't block a merge. working-directory: frontend run: npm audit --omit=dev --audit-level=high # RECOMMENDATIONS #9: SAST. Semgrep community rules for C#/JS + OWASP/secrets patterns — # catches injection/crypto-misuse classes the other gates (gitleaks, dep-audit, tests) # don't look for. Advisory at first (not a required check); promote once tuned. sast: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 # The runner image lacks pip, and a semgrep job-container lacks the node that # actions/checkout needs — so install pip via apt on the standard image. # Gitea's Act runner has no sudo binary but already runs as root, so call # apt-get directly; pip install --user needs no pipx. - name: Install semgrep run: | apt-get update -qq && apt-get install -y -qq python3-pip python3 -m pip install --user --break-system-packages semgrep || python3 -m pip install --user semgrep - name: Semgrep scan run: | export PATH="$HOME/.local/bin:$PATH" semgrep scan --config p/csharp --config p/javascript --config p/security-audit --exclude 'frontend/dist' --exclude '**/bin' --exclude '**/obj' --error --quiet