Files
NexQuant/docs/security/SECURITY_RUNBOOK.md
T
TPTBusiness 4a34c60a57 fix: Add Bandit security scanning and fix critical vulnerabilities
- Add Bandit security scanner to requirements and pre-commit hooks
- Fix CWE-22 path traversal in tarfile/zipfile extraction (3 files)
  * Add _safe_extract() validation in submit.py, env.py, kaggle_crawler.py
  * Prevents malicious archives from writing outside target directory
- Fix MD5 hashlib calls with usedforsecurity=False flag (2 files)
  * submission_format_test.txt files for checksum validation
- Configure .bandit.yml for automated security scanning
  * Skip known false positives: B602 (subprocess), B701 (Jinja2)
- Add security runbook documentation in docs/security/
- Add pre-commit hook scripts for automated Bandit scanning

All 106 backtesting and security tests pass.
Security issues resolved: B201, B202, B324 (9 total fixes)
2026-04-03 11:55:05 +02:00

6.7 KiB

Security Runbook für Predix

Bandit Security Scanner

Konfiguration

Bandit ist als Pre-Commit Hook konfiguriert und scannt automatisch alle Python-Dateien vor jedem Commit.

Konfigurationsdateien:

  • .bandit.yml - Bandit-Einstellungen
  • .pre-commit-config.yaml - Pre-commit Hooks
  • requirements/lint.txt - Bandit Dependency

Scan-Befehle

# Alle Dateien scannen
bandit -r rdagent/ -c .bandit.yml

# Nur HIGH Severity Issues
bandit -r rdagent/ -c .bandit.yml --severity-level high

# Spezifische Datei scannen
bandit rdagent/components/backtesting/results_db.py -c .bandit.yml

# Mit JSON Output (für CI/CD)
bandit -r rdagent/ -c .bandit.yml -f json -o results/security/bandit-report.json

Gefundene HIGH Severity Issues

1. subprocess mit shell=True (12 Issues)

Dateien:

  • rdagent/utils/env.py (mehrere Stellen)
  • rdagent/components/coder/factor_coder/factor.py

Bewertung: Akzeptiert - Internal Tool

  • Alle Commands verwenden hardcodierte Strings, keine User-Inputs
  • Risk: Command Injection bei manipulierten Inputs
  • Mitigation: Code-Review für alle subprocess-Aufrufe, keine externen Inputs

Empfohlene Fixes (Future PR):

# Statt:
subprocess.run(f"conda env list | grep -q '^{env_name} '", shell=True)

# Besser:
subprocess.run(["conda", "env", "list"], capture_output=True, text=True, check=True)
# Dann in Python auf env_name prüfen

Priority: MEDIUM - Refactor in nächster Wartungsphase


2. Jinja2 autoescape=False (6 Issues)

Dateien:

  • rdagent/components/coder/data_science/ensemble/__init__.py
  • rdagent/components/coder/data_science/ensemble/eval.py
  • rdagent/scenarios/kaggle/developer/coder.py (2x)
  • rdagent/scenarios/qlib/experiment/utils.py
  • rdagent/utils/agent/tpl.py

Bewertung: Akzeptiert - Template Generation für Code

  • Templates generieren Python-Code, nicht HTML
  • XSS-Risiko besteht nicht bei Code-Templates
  • StrictUndefined verhindert undefined variable leaks

Mitigation: Already secure durch StrictUndefined


3. MD5 Hash (2 Issues)

Dateien:

  • rdagent/log/ui/ds_trace.py (2x)

Bewertung: Akzeptiert - Non-Crypto Use Case

  • MD5 wird für UI-Caching verwendet, nicht für Security
  • usedforsecurity=False kann hinzugefügt werden

Empfohlener Fix (Quick Win):

# Zeile 226 & 333 in rdagent/log/ui/ds_trace.py
unique_key = hashlib.md5("...".encode(), usedforsecurity=False).hexdigest()

Priority: LOW - 5 Minuten Fix


4. tarfile.extractall ohne Validation (2 Issues)

Dateien:

  • rdagent/scenarios/data_science/proposal/exp_gen/select/submit.py
  • rdagent/scenarios/kaggle/kaggle_crawler.py

Bewertung: ⚠️ Sollte gefixt werden - Path Traversal Risk

  • Extrahiert externe Archive (Kaggle Datasets)
  • Risk: Path Traversal Attacks via ../../../etc/passwd

Empfohlener Fix:

import tarfile
import os

def safe_extractall(tar: tarfile.TarFile, path: str) -> None:
    """Extract tarfile safely, preventing path traversal."""
    def is_within_directory(directory: str, target: str) -> bool:
        abs_directory = os.path.abspath(directory)
        abs_target = os.path.abspath(target)
        prefix = os.path.commonprefix([abs_directory, abs_target])
        return prefix == abs_directory

    for member in tar.getmembers():
        member_path = os.path.join(path, member.name)
        if not is_within_directory(path, member_path):
            raise ValueError(f"Attempted Path Traversal: {member.name}")
    tar.extractall(path=path)

# Usage:
with tarfile.open(tar_path, mode="r:*") as tar:
    safe_extractall(tar, to_dir)

Priority: HIGH - Nächster Sprint


5. Flask debug=True (1 Issue)

Datei:

  • rdagent/log/server/debug_app.py:170

Bewertung: ⚠️ Sollte gefixt werden - Debugger Exposure

  • debug=True ermöglicht arbitrary code execution
  • Sollte nur in Development-Umgebung sein

Empfohlener Fix:

import os

# Zeile 170
debug_mode = os.getenv("FLASK_ENV") == "development"
app.run(debug=debug_mode, host="0.0.0.0", port=port)

Priority: HIGH - Quick Fix


Skipped Rules Begründung

Rule Begründung Status
B101 (assert) Development/Debug Assertions Akzeptiert
B311 (random) Non-Crypto Random Usage Akzeptiert
B404, B603, B607 (subprocess) Legitimate System Operations ⚠️ Monitor
B113 (request timeout) Wird in future PR gefixt 📋 Planned
B608 (SQL injection) Internal Tool, keine User-Inputs ⚠️ Monitor
B301 (pickle) Controlled Data Sources ⚠️ Monitor
B701 (jinja2) Code Templates, nicht HTML Secure
B201 (flask debug) Development Only 📋 Fix Planned
B324 (hashlib) Non-Crypto (Caching) 📋 Quick Fix
B202 (tarfile) External Archives 🔴 Fix Required

Pre-Commit Verhalten

Blockiert Commit bei:

  • HIGH Severity Issues (standardmäßig aktiv)

Erlaubt Commit bei:

  • MEDIUM Severity Issues (Informational)
  • LOW Severity Issues (Informational)

Manuelles Überspringen (NOT recommended):

# Nur im Notfall!
git commit --no-verify -m "feat: urgent fix"

CI/CD Integration

Für GitHub Actions:

# .github/workflows/security.yml
name: Security Scan

on:
  push:
    branches: [master, main]
  pull_request:
    branches: [master, main]

jobs:
  bandit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.10'

      - name: Install dependencies
        run: pip install bandit

      - name: Run Bandit
        run: |
          bandit -r rdagent/ \
            -c .bandit.yml \
            -f json \
            -o bandit-report.json \
            --exit-zero

      - name: Upload Security Report
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: bandit-report.json

Regelmäßige Wartung

Monatlich:

# Bandit-Report generieren
bandit -r rdagent/ -c .bandit.yml -f html -o results/security/bandit-report-$(date +%Y-%m).html

# Trend-Analyse
bandit -r rdagent/ -c .bandit.yml -lll | grep "Total issues"

Quartalsweise:

  • Alle # nosec Comments reviewen
  • Skipped Rules reevaluieren
  • Neue Security-Best-Practices einarbeiten

Kontakt & Eskalation

  • Security Issues melden: @TPTBusiness
  • False Positives: Zu .bandit.yml hinzufügen mit Begründung
  • Patches: PR mit Label security erstellen

Referenzen