StackSentry assesses your web application across four distinct deployment layers simultaneously. Missing any one layer gives you an incomplete picture.
The Four Layers
┌─────────────────────────────────────────────────────────────┐
│ Web Application │
│ Flask / Django / PHP / Any HTTP application │
└──────────────────────────┬──────────────────────────────────┘
│ HTTP
┌──────────────────────────▼──────────────────────────────────┐
│ Webserver (nginx / Apache) │
│ TLS config · Security headers · Rate limits │
└──────────────────────────┬──────────────────────────────────┘
│ Container runtime
┌──────────────────────────▼──────────────────────────────────┐
│ Docker Container │
│ User · Ports · Resource limits · Secrets │
└──────────────────────────┬──────────────────────────────────┘
│ SSH
┌──────────────────────────▼──────────────────────────────────┐
│ Linux Host │
│ SSH config · Firewall · Updates · Logging │
└─────────────────────────────────────────────────────────────┘
A misconfiguration at any layer can compromise the rest. A hardened Flask application inside a Docker container with --privileged is still exploitable if the container is compromised.
Module Pipeline
Inside StackSentry, data flows through six modules:
Scanners → Checks → Scoring → Storage → Reporting → Remediation
Scanners
Five scanner classes collect raw data without making any security judgements:
| Scanner | Data Source | Used By |
|---|---|---|
HttpScanner | HTTP requests to target URL | App + webserver checks |
SshScanner | SSH commands via Paramiko | Host checks + auto-fix |
DockerScanner | Docker SDK API queries | Container checks |
NginxScanner | nginx.conf static parsing | WS-CONF-HSTS, WS-CONF-CSP |
ComposeScanner | docker-compose.yml parsing | Container resource checks |
Checks
24 pure Python functions. Each accepts a scanner object and returns a CheckResult:
@dataclass
class CheckResult:
id: str # e.g. "APP-DEBUG-001"
layer: str # app | webserver | container | host
name: str
status: Status # PASS | FAIL | WARN | ERROR
severity: Severity # CRITICAL | HIGH | MEDIUM | LOW
details: str # specific finding from this scan
Every check has guard clauses at the top — if the required context (SSH credentials, Docker host) is not available, it returns WARN immediately rather than crashing or producing misleading results.
Scoring
ScanResult aggregates all CheckResult objects and computes:
- Pass rate (excluding infrastructure WARNs)
- Letter grade (A–F)
- Priority score per failing check
- Attack path count
- OWASP category breakdown
Storage
Every scan is persisted to ~/.stacksentry/history.db (SQLite). The DriftEngine compares the current scan against the previous one to surface regressions and improvements.
Reporting
The PdfGenerator produces a 14-section PDF report using ReportLab. JSON output is also available for CI/CD integration.
Remediation
Three levels of fix output:
- Static templates — pre-written shell scripts, Python/PHP code, nginx snippets
- LLM-generated patches — context-aware code via the Anthropic Claude API
- Auto-fix engine — applies fixes directly via SSH with validation
Why Separate Scanners from Checks?
This design means every check function is independently testable with a mock scanner object. No network connections are made during testing. The 321-test suite runs in 1.55 seconds because of this separation.
It also means you can run checks against locally provided configuration files without a live target — useful for CI/CD environments where you want to validate a deployment before it goes live.
Entry Point
The framework installs as a pip console script:
stacksentry = "sec_audit.cli:main"
This means stacksentry is available as a system command after pip install stacksentry — no need to navigate to a project directory or invoke Python directly.