Overview
The security scanning workflow (security-scan.yml) is the first line of defense for the GovTech platform. It runs on all pull requests and pushes to main/staging branches, blocking merges if vulnerabilities are detected.
File: .github/workflows/security-scan.yml
Workflow Triggers
Security Jobs
The workflow consists of 4 independent jobs running in parallel:Job 1: Secret Scanning (Gitleaks)
Purpose: Detect hardcoded credentials, API keys, and secrets in code and git history.Configuration
What It Detects
- AWS access keys and secret keys
- API tokens (GitHub, Stripe, Slack, etc.)
- Database connection strings with passwords
- Private SSH keys
- JWT secrets
- OAuth client secrets
Scan Scope
Failure Behavior
Gitleaks exits with code 1 when secrets are found, automatically failing the job and blocking the PR merge.Enterprise Features
Job 2: SAST - Static Application Security Testing (Semgrep)
Purpose: Analyze source code for security vulnerabilities and insecure patterns.Configuration
Rule Sets
| Config | Detects |
|---|---|
--config=auto | Language-specific best practices |
--config=p/nodejs | Node.js security patterns (command injection, path traversal) |
--config=p/react | React XSS, unsafe dangerouslySetInnerHTML |
--config=p/jwt | Weak JWT algorithms (HS256 with hardcoded secret) |
--config=p/secrets | Hardcoded credentials in code |
--config=p/owasp-top-ten | OWASP Top 10 vulnerabilities |
Scan Targets
Output Formats
Two scan runs:-
JSON output (security-scan.yml:54-65):
Stored as artifact for later analysis.
-
CLI output (security-scan.yml:68-76):
Prints human-readable results to workflow logs.
Failure Mode
Artifacts
Job 3: Dependency Vulnerability Scan (npm audit)
Purpose: Detect known vulnerabilities (CVEs) in npm dependencies.Configuration
Critical Fix
Before (insecure):Audit Levels
| Level | Description |
|---|---|
info | Informational, not exploitable |
low | Low risk, may fail in edge cases |
moderate | Medium risk, exploitable with effort |
high | High risk, easily exploitable |
critical | Remote code execution, data breach |
Dependency Installation
npm ci: Clean install from package-lock.json (reproducible builds)--prefer-offline: Use npm cache, faster CI runs
Separate Scans
Backend and frontend dependencies are audited independently:Job 4: Infrastructure as Code Scan (Checkov)
Purpose: Scan Terraform and Kubernetes manifests for security misconfigurations.Configuration
Terraform Checks
Directory:terraform/
Detects:
- Unencrypted S3 buckets
- Security groups allowing 0.0.0.0/0 on sensitive ports
- RDS instances without encryption
- IAM policies with wildcard permissions (
*) - Public EC2 instances without proper security
Kubernetes Checks
Directory:kubernetes/
Detects:
- Containers running as root
- Missing resource limits (CPU/memory)
- Privileged containers
- Host network/IPC/PID sharing
- Secrets stored as plaintext ConfigMaps
Soft Fail Mode
External Modules
Security Workflow Summary
File Location:.github/workflows/security-scan.yml
Execution Flow:
Blocking Jobs:
- Secret Scanning (Gitleaks)
- SAST (Semgrep)
- Dependency Scan (npm audit)
- IaC Scan (Checkov) - soft_fail: true
Security Tools Reference
Gitleaks
Version: v2 (gitleaks-action) Documentation: https://github.com/gitleaks/gitleaks Configuration: Uses default ruleset (detects 300+ secret patterns) Custom Rules: Can add.gitleaks.toml to repository for custom patterns
Semgrep
Version: Latest (returntocorp/semgrep container) Documentation: https://semgrep.dev/docs Custom Rules: Can add.semgrep.yml or .semgrep/ directory
Registry: https://semgrep.dev/explore (10,000+ community rules)
npm audit
Version: Built into Node.js 20 Database: National Vulnerability Database (NVD) + GitHub Security Advisories Update Frequency: Real-time via npm registryCheckov
Version: Latest (bridgecrewio/checkov-action@master) Documentation: https://www.checkov.io/ Checks: 1,000+ built-in policies for AWS, Azure, GCP, Kubernetes Frameworks Supported:- Terraform
- CloudFormation
- Kubernetes
- Helm
- Dockerfile
Compliance Mapping
| Regulation | Requirement | Implementation |
|---|---|---|
| NIST 800-53 | SA-11 Developer Security Testing | Semgrep SAST, npm audit |
| NIST 800-53 | RA-5 Vulnerability Scanning | All 4 jobs |
| PCI DSS | 6.3.2 Code Review | Semgrep, Gitleaks |
| PCI DSS | 6.2 Security Patches | npm audit |
| CIS Benchmarks | 5.2 Secret Management | Gitleaks |
| CIS Benchmarks | 5.4 Image Scanning | Trivy (in CI workflows) |
Artifact Retention
| Artifact | Retention | Purpose |
|---|---|---|
semgrep-results.json | 30 days | Security audit trail |
Best Practices
Secret Management
Do:- Use GitHub Secrets for all credentials
- Use OIDC for cloud provider authentication
- Store secrets in AWS Secrets Manager/Parameter Store
- Use environment variables, never hardcode
- Commit .env files
- Hardcode API keys in code
- Store secrets in Terraform state
- Use weak JWT secrets
Dependency Management
Do:- Run
npm audit fixregularly - Pin dependency versions in package-lock.json
- Review security advisories weekly
- Use Dependabot for automated updates
- Use
|| trueto bypass audit failures - Ignore CRITICAL vulnerabilities
- Use outdated dependencies
- Disable audit checks
Code Security
Do:- Review Semgrep findings before merge
- Use parameterized queries (prevent SQL injection)
- Sanitize user input (prevent XSS)
- Use strong JWT algorithms (RS256)
- Use
eval()orexec()with user input - Trust user input without validation
- Store passwords in plaintext
- Use weak cryptographic algorithms
Troubleshooting
Gitleaks False Positives
Problem: Gitleaks flags test fixtures or mock data as secrets. Solution: Add.gitleaks.toml: