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.