Automated web application security configuration assessment and remediation
Project description
StackSentry ๐ก๏ธ
Automated web application security assessment, AI-powered remediation, and auto-fix.
StackSentry scans your web application stack โ Flask/Django/PHP app, Nginx/Apache webserver, Docker containers, and Linux host โ assigns a security grade, generates AI-powered fix scripts, and can apply fixes automatically via SSH or directly to your config files.
What it does
stacksentry -t https://your-app.com --mode full --patch --fix \
--ssh-host your-server-ip --ssh-user root --ssh-key ~/.ssh/id_ed25519 \
--dockerfile ./Dockerfile \
--compose-file ./docker-compose.yml
In one command, StackSentry:
- Runs 24+ security checks across 4 layers of your stack
- Assigns a security grade (AโF) with a percentage score
- Generates a professional PDF report with OWASP Top 5 mapping
- Creates AI-powered fix scripts organised per scan in
patches/ - Auto-applies fixes via SSH (HOST + WS) or directly to your config files (CONT + WS)
- Generates and installs SSH keys before applying
prohibit-passwordโ so you are never locked out - Prints stack-aware code snippets for APP layer checks (Flask, Django, Laravel, vanilla PHP)
- Tracks posture drift โ shows what regressed or improved since last scan
- Simulates what-if scenarios โ projects your grade after specific fixes
- Detects PHP/Apache/shared hosting stacks automatically and adjusts checks accordingly
Real-world results
StackSentry was tested against three live applications during development:
| Target | Stack | Before | After auto-fix | Checks fixed |
|---|---|---|---|---|
admin.vickkykruzprogramming.dev |
nginx/Ubuntu VPS | F (16.7%) | C (72.7%) | HSTS, security headers, server token, TLS, request limits, SSH hardening |
bblearn.londonmet.ac.uk |
Unknown/SPA (Blackboard LMS) | D (66.7%) | โ (no SSH) | Scan only โ CSRF PASS, admin WARN (login wall detected) |
sacoeteccscdept.com.ng |
PHP/Apache/shared hosting | F (27.3%) | โ (no SSH) | Scan only โ stack correctly detected from URL alone |
The VPS went from F (16.7%) to C (72.7%) with 0 attack paths after auto-fix.
Quick start
pip install stacksentry
# Basic HTTP scan
stacksentry -t https://your-app.com
# Full stack scan with PDF report
stacksentry -t https://your-app.com --mode full \
--ssh-host your-server-ip --ssh-user root --ssh-password yourpass \
-o report.pdf
# Dry-run โ see exactly what would change before applying
stacksentry -t https://your-app.com --mode full --fix --dry-run \
--ssh-host your-server-ip --ssh-user root --ssh-password yourpass
# Generate AI-powered fix scripts + auto-apply
stacksentry -t https://your-app.com --mode full --patch --fix \
--ssh-host your-server-ip --ssh-user root --ssh-password yourpass \
--dockerfile ./Dockerfile --compose-file ./docker-compose.yml
# Use SSH key after StackSentry generates one
stacksentry -t https://your-app.com --mode full --fix \
--ssh-host your-server-ip --ssh-user root \
--ssh-key ~/.stacksentry/keys/your-server_20260411.pem
# Compare against last scan (posture drift)
stacksentry -t https://your-app.com --compare-last
# Scan a PHP/shared hosting app
stacksentry -t https://your-php-app.com/index.php --mode full
# View full scan history
stacksentry -t https://your-app.com --history
Installation
From PyPI:
pip install stacksentry
From source:
git clone https://github.com/vickkykruz/stacksentry
cd stacksentry
pip install -e ".[dev]"
Optional โ SSH auto-fix:
pip install paramiko
Optional โ AI-powered patch generation:
Set your Anthropic API key:
export ANTHROPIC_API_KEY=sk-ant-your-key-here
Without the key, StackSentry uses static patch templates. With it, patches are tailored to your specific stack by Claude AI.
SSH key safety
When you run --fix with --ssh-password and HOST-SSH-001 fails (PermitRootLogin is yes), StackSentry does not blindly apply prohibit-password and risk locking you out. Instead it runs a 4-step pre-flight:
- Generates an Ed25519 SSH key pair locally (RSA 4096 fallback for older paramiko)
- Installs the public key on the server via your existing password session
- Verifies that key login actually works before touching sshd
- Only then applies
PermitRootLogin prohibit-passwordand restarts sshd
Keys are saved to ~/.stacksentry/keys/ with OS-appropriate permissions (chmod 600 on Linux/macOS, icacls on Windows). If key verification fails, the sshd config is never touched.
Running with --dry-run shows the exact key paths and all 4 steps before anything is applied.
Stack detection
StackSentry automatically detects your application stack from HTTP response headers, cookies, and URL patterns โ even when the server is unreachable:
| Signal | Detection |
|---|---|
.php in URL |
PHP detected |
X-Powered-By: PHP/8.x |
PHP + version |
PHPSESSID cookie |
PHP session |
Server: Apache |
Apache webserver |
Server: nginx |
nginx webserver |
csrftoken / sessionid cookie |
Django |
| PHP + Apache, no VPS tells | Shared hosting |
When PHP/shared hosting is detected:
- Admin paths expand to include
/phpmyadmin,/pma,/cpanel,/administrator - Patch templates output PHP (Laravel
@csrf, vanilla PHP token generation, CodeIgniter config) - Infrastructure WARNs from missing SSH/Docker are excluded from scoring
Auto-fix coverage
| Layer | Check | Auto-fix method |
|---|---|---|
| HOST | HOST-FW-001 โ Firewall enabled | โ
SSH (ufw enable) |
| HOST | HOST-SSH-001 โ SSH hardening | โ
SSH (key generation + prohibit-password) |
| HOST | HOST-UPDATE-001 โ Auto-updates | โ
SSH (unattended-upgrades) |
| HOST | HOST-PERM-001 โ SSH file permissions | โ
SSH (chmod) |
| HOST | HOST-LOG-001 โ Logging active | โ
SSH (rsyslog) |
| HOST | HOST-SVC-001 โ Minimal services | ๐ Manual guide |
| HOST | HOST-SVC-GUNICORN/UWSGI/MYSQL/REDIS | ๐ Manual guide |
| WS | WS-HSTS-001 โ HSTS header | โ
SSH or --nginx-conf |
| WS | WS-SEC-001 โ Security headers | โ
SSH or --nginx-conf |
| WS | WS-TLS-001 โ TLS 1.2+ | โ
SSH or --nginx-conf (Let's Encrypt aware) |
| WS | WS-SRV-001 โ Server token disclosure | โ
SSH or --nginx-conf |
| WS | WS-DIR-001 โ Directory listing | โ
SSH or --nginx-conf |
| WS | WS-LIMIT-001 โ Request size limits | โ
SSH or --nginx-conf |
| WS | WS-CONF-HSTS / WS-CONF-CSP | โ
SSH or --nginx-conf |
| CONT | CONT-USER-001 โ Non-root user | โ
--dockerfile |
| CONT | CONT-CONF-HEALTH โ HEALTHCHECK | โ
--dockerfile |
| CONT | CONT-RES-001 / CONT-COMP-RES | โ
--compose-file |
| CONT | CONT-SEC-001 โ Secrets in env | ๐ Manual guide |
| APP | APP-DEBUG-001 โ Debug mode | ๐ Flask/Django/PHP snippet |
| APP | APP-COOKIE-001 โ Secure cookies | ๐ Flask/Django/PHP snippet |
| APP | APP-CSRF-001 โ CSRF protection | ๐ Flask/Django/Laravel/PHP snippet |
| APP | APP-ADMIN-001 โ Admin endpoints | ๐ Flask/Django/PHP snippet |
| APP | APP-RATE-001 โ Rate limiting | ๐ Flask/Django/nginx snippet |
| APP | APP-PASS-001 โ Password policy | ๐ Framework snippet |
Legend:
- โ Fully automated โ StackSentry applies the fix, validates, and confirms
- ๐ Code snippet โ StackSentry detects your framework and prints the exact code to add
Every automated fix creates a timestamped backup, validates with nginx -t or sshd -t before applying, and is idempotent. If a fix fails validation, subsequent dependent fixes are skipped with a clear explanation rather than cascading silently.
Dry-run โ always preview before applying
Running --fix --dry-run shows the complete plan with every command that would run, without touching your server:
๐ DRY-RUN โ no changes will be made to the server or files.
3 check(s) will be fixed automatically
6 check(s) require manual action (APP layer)
๐ DRY-RUN PLAN โ commands that WOULD run:
๐ง [WEBSERVER] WS-HSTS-001 Would run 5 SSH command(s) on 159.198.66.20
$ mkdir -p /etc/nginx/snippets
$ nginx -t
$ systemctl reload nginx
๐ง [HOST ] HOST-SSH-001
โ ๏ธ PASSWORD โ KEY MIGRATION REQUIRED
Step 1: Generate Ed25519 key pair โ ~/.stacksentry/keys/server.pem
Step 2: Install public key on server
Step 3: Verify key login
Step 4: Apply PermitRootLogin prohibit-password
Would fix: 3 | Manual: 6
โ
Review complete. Run without --dry-run to apply.
Output formats
PDF report (-o report.pdf)
Professional report including executive summary, attack surface heatmap, OWASP Top 5 mapping, prioritised hardening plan (Day 1/7/30), 30-day simulation roadmap, generated patches table, auto-fix results, security posture history, and server fingerprint.
JSON (--json results.json)
Structured output for CI/CD pipelines. Includes all check results, scores, attack paths, generated patches with metadata, auto-fix results, and scan history.
Patch files (--patch)
Scripts written to patches/{target}_{date}_scan{N}/:
.shshell scripts for host/server fixes.pyPython scripts for Flask/Django app-layer guidance.phpPHP scripts for PHP/Laravel app-layer guidance.confnginx configuration snippetsREADME.mdwith severity-sorted application ordermanifest.jsonfor machine-readable processing
CLI reference
stacksentry -t URL [options]
Core:
--target, -t URL Target web application URL
--mode, -m MODE quick (HTTP only) | full (HTTP + Docker + SSH)
--output, -o PATH PDF report output path
--json, -j PATH JSON results output path
--verbose, -v Verbose debug output
Scanning:
--ssh-host HOST SSH target host/IP (enables host layer + auto-fix)
--ssh-user USER SSH username (default: root)
--ssh-password PASS SSH password
--ssh-key PATH SSH private key path
--docker-host URL Docker daemon endpoint
--nginx-conf PATH nginx.conf for static analysis and local auto-fix
--dockerfile PATH Dockerfile for static analysis and auto-fix
--compose-file PATH docker-compose.yml for static analysis and auto-fix
Reporting:
--plan Print prioritised hardening plan (Day 1/7/30)
--simulate CHECK_IDS What-if simulation (comma-separated check IDs)
--profile ROLE Narrative: student|devops|pentester|cto|generic
Patch generation:
--patch Generate AI-powered remediation fix scripts
--patch-dir DIR Output directory (default: patches/)
--no-llm Use static templates only (no API key needed)
Auto-fix:
--fix Auto-apply fixes using available context
--dry-run Preview all fixes without applying (safe to run first)
History:
--compare-last Show posture drift vs previous scan
--history Print scan history timeline and exit
--no-save Do not save this scan to history database
--db-path PATH Custom history database path
Telemetry:
--telemetry on|off|status Enable, disable, or check telemetry status
Using as a library
from sec_audit.results import ScanResult
from storage import ScanHistory
from storage.drift import DriftEngine
from remediation import PatchGenerator
from remediation.auto_fix import AutoFixer
# Generate patches
generator = PatchGenerator(use_llm=True)
patches = generator.generate_all(scan_result, output_dir="patches/")
# Auto-fix with full context
fixer = AutoFixer(
ssh_host="1.2.3.4",
ssh_password="...", # key will be generated automatically if needed
dockerfile="./Dockerfile",
compose_file="./docker-compose.yml",
dry_run=True, # preview only
)
results = fixer.fix_all(scan_result)
# History and drift
history = ScanHistory()
history.save(scan_result)
report = DriftEngine().compare(previous_scan, scan_result)
Architecture
stacksentry/
โโโ sec_audit/ CLI, config, results, scoring, narratives, telemetry
โโโ checks/ 24+ security check functions (4 layers)
โโโ scanners/ HTTP, SSH, Docker, Nginx, compose scanners
โโโ reporting/ PDF generator (ReportLab)
โโโ storage/ SQLite history, drift engine
โโโ remediation/ Patch generator, LLM integration, auto-fix engine
โโโ tests/ 321 tests, 0 failures
Running tests
pip install -e ".[dev]"
pytest tests/ -v
# 321 passed in ~1.5s
Telemetry
StackSentry collects anonymous usage data (scan counts, check grades, platform) to help prioritise development. It is opt-in only โ you are asked once on first run and can change your preference at any time:
stacksentry --telemetry status # check current setting
stacksentry --telemetry off # disable
stacksentry --telemetry on # enable
No personally identifiable information is collected. No code, URLs, or scan results are ever sent.
Roadmap
- Phase 1 โ 24+ checks, PDF/JSON reports, CLI
- Phase 2 โ History, drift detection, posture tracking
- Phase 3 โ AI-powered patch generation + auto-fix engine
- Phase 4 โ PyPI package, PHP/Apache support, SSH key safety, dry-run (current)
- Phase 5 โ SaaS dashboard, team accounts, CI/CD integrations,
--app-pathfor application source code auto-fix
Contributing
See CONTRIBUTING.md for the full guide including check schema, template registration, and test requirements.
License
MIT โ see LICENSE for details.
Built by Victor Chukwuemeka Onwuegbuchulem โ London Metropolitan University
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file stacksentry-1.0.0.tar.gz.
File metadata
- Download URL: stacksentry-1.0.0.tar.gz
- Upload date:
- Size: 14.9 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a679620172e0582c33c22dbd556fc6b5dca2ea689b14a81d673508dd6b190c1b
|
|
| MD5 |
a2dcd718bcbc104952c9e423165fb262
|
|
| BLAKE2b-256 |
25897c9200b247460abff7e1159da06c0cebd4d4ea94ad82265246a355f5217f
|
File details
Details for the file stacksentry-1.0.0-py3-none-any.whl.
File metadata
- Download URL: stacksentry-1.0.0-py3-none-any.whl
- Upload date:
- Size: 111.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4b06b643499faa61da20c423b8f9d75bd34bb1677ba900ca3108dd8187e4a9f8
|
|
| MD5 |
c7d40f62c744cd64e2189ea8e4e33c9b
|
|
| BLAKE2b-256 |
6da5d9e16d38330773e4ab15cbea47fe8e008a8b7f19e853d230041008b45cc9
|