Intermediate Application & Code

Static analysis (SAST) — tools, false positives, CI integration

SAST (Static Application Security Testing) examines source code — or bytecode — without executing the application. It is the first automated line of defense in the development cycle: it catches problems early, when the cost of fixing them is lowest.

How SAST Works

The tool traverses the syntactic tree of the code and applies rules that detect insecure patterns:

Source code
    │
    ▼
Parser / AST (Abstract Syntax Tree)
    │
    ▼
Rules engine (taint analysis, dataflow, pattern matching)
    │
    ▼
Findings report (vulnerability, line, severity)

Taint analysis tracks data from untrusted sources (HTTP input) to dangerous sinks (SQL query, exec, eval). If data reaches a sink without sanitization, the tool raises a finding.

LanguageFree / OSSCommercial
PythonBandit, SemgrepCheckmarx, Veracode
JavaScript/TSESLint security plugin, SemgrepSnyk Code
JavaSpotBugs + FindSecBugsSonarQube
GoGosec, Semgrep—
PHPPHPCS Security AuditSnyk Code
Multi-langSemgrepSonarQube, Checkmarx

Example with Bandit (Python)

# Install
pip install bandit

# Scan directory
bandit -r ./src -ll

# Typical output
>> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection via string-based query construction.
   Severity: Medium   Confidence: Medium
   Location: src/db.py:42

Example with Semgrep

# Install
pip install semgrep

# Run with security ruleset
semgrep --config=p/owasp-top-ten ./src

# Output
src/auth.py:87: ERROR: Use of MD5 for password hashing detected.

False Positives — How to Handle Them

SAST has a false positive rate. A generic rule may flag secure code. Strategies:

  1. Triage by severity — focus on HIGH/CRITICAL first.
  2. Inline suppression — mark the finding as accepted with a justification comment:
result = hashlib.md5(data).hexdigest()  # nosec B324 — non-crypto hash used for cache key
  1. Rule tuning — disable rules that generate noise in your project context.
  2. Human review — SAST surfaces candidates; the developer confirms whether it is a real vulnerability.

Never suppress findings without reading them. A masked false positive can hide a real vulnerability.

CI/CD Integration

SAST should run on every pull request and block merging when critical findings are detected.

# .github/workflows/sast.yml
name: SAST

on: [pull_request]

jobs:
  bandit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run Bandit
        run: |
          pip install bandit
          bandit -r ./src -ll --exit-zero-on-skipped -f json -o bandit-report.json
      - name: Upload report
        uses: actions/upload-artifact@v4
        with:
          name: bandit-report
          path: bandit-report.json

To block merges on critical findings, use --severity-level high and let the command return a non-zero exit code.

SAST Limitations

  • Does not detect runtime vulnerabilities (race conditions, server misconfiguration).
  • Does not test data flow between services (requires DAST or manual analysis).
  • Quality depends on the rules: bad rules mean high noise or high miss rate.

SAST is complementary — it does not replace human code review or dynamic testing.