SAST: Static Application Security Testing
SAST (Static Application Security Testing) analyzes source code without execution — finds vulnerabilities at development stage. SQL injection, XSS, hardcoded secrets, unsafe functions — before reaching production.
SAST Tools
Semgrep — fast, rules for 30+ languages, can write custom rules:
# Installation
pip install semgrep
# Scan with security audit rules
semgrep scan --config=p/security-audit \
--config=p/owasp-top-ten \
--config=p/typescript \
--json > semgrep-results.json
# Custom rule: find direct SQL concatenation
cat > rules/sql-injection.yml << 'EOF'
rules:
- id: raw-sql-concatenation
patterns:
- pattern: |
"SELECT ... " + $VAR
- pattern: |
`SELECT ... ${$VAR}`
message: "Potential SQL injection: use parameterized queries"
severity: ERROR
languages: [typescript, javascript]
EOF
semgrep scan --config=rules/sql-injection.yml src/
GitHub Advanced Security (CodeQL):
# .github/workflows/codeql.yml
name: CodeQL
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 0 * * 1' # Weekly
jobs:
analyze:
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
strategy:
matrix:
language: [javascript-typescript]
steps:
- uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
queries: security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Analyze
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{ matrix.language }}"
Secret Scanning
# Gitleaks: find secrets in code and git history
docker run --rm -v $(pwd):/path \
zricethezav/gitleaks:latest detect \
--source /path \
--report-format json \
--report-path /path/gitleaks-report.json
# truffleHog: analyze git history
trufflehog git file://. --json > secrets-report.json
# GitHub Actions: pre-commit hook for secrets
- name: Check for secrets
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}
ESLint Security Plugins
npm install --save-dev eslint-plugin-security \
eslint-plugin-no-unsanitized \
@microsoft/eslint-plugin-sdl
// .eslintrc.json
{
"plugins": ["security", "no-unsanitized", "@microsoft/sdl"],
"extends": [
"plugin:security/recommended",
"plugin:@microsoft/sdl/required"
],
"rules": {
"security/detect-object-injection": "error",
"security/detect-non-literal-regexp": "warn",
"security/detect-possible-timing-attacks": "error",
"no-unsanitized/method": "error",
"no-unsanitized/property": "error"
}
}
CI/CD Integration
# .github/workflows/sast.yml
name: SAST
on: [push, pull_request]
jobs:
semgrep:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: returntocorp/semgrep-action@v1
with:
config: >-
p/security-audit
p/owasp-top-ten
p/typescript
auditOn: push
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
secrets-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SAST Rule: don't block PRs on every warning — only on HIGH and CRITICAL. Everything else goes to security debt backlog.
Setting up Semgrep + CodeQL + Gitleaks in CI/CD — 1–2 business days.







