Skip to main content

Automated web application security configuration assessment and remediation

Project description

StackSentry ๐Ÿ›ก๏ธ

Automated web application security assessment, AI-powered remediation, and auto-fix.

Tests Python License PyPI

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:

  1. Generates an Ed25519 SSH key pair locally (RSA 4096 fallback for older paramiko)
  2. Installs the public key on the server via your existing password session
  3. Verifies that key login actually works before touching sshd
  4. Only then applies PermitRootLogin prohibit-password and 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}/:

  • .sh shell scripts for host/server fixes
  • .py Python scripts for Flask/Django app-layer guidance
  • .php PHP scripts for PHP/Laravel app-layer guidance
  • .conf nginx configuration snippets
  • README.md with severity-sorted application order
  • manifest.json for 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-path for 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

stacksentry-1.0.0.tar.gz (14.9 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

stacksentry-1.0.0-py3-none-any.whl (111.4 kB view details)

Uploaded Python 3

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

Hashes for stacksentry-1.0.0.tar.gz
Algorithm Hash digest
SHA256 a679620172e0582c33c22dbd556fc6b5dca2ea689b14a81d673508dd6b190c1b
MD5 a2dcd718bcbc104952c9e423165fb262
BLAKE2b-256 25897c9200b247460abff7e1159da06c0cebd4d4ea94ad82265246a355f5217f

See more details on using hashes here.

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

Hashes for stacksentry-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4b06b643499faa61da20c423b8f9d75bd34bb1677ba900ca3108dd8187e4a9f8
MD5 c7d40f62c744cd64e2189ea8e4e33c9b
BLAKE2b-256 6da5d9e16d38330773e4ab15cbea47fe8e008a8b7f19e853d230041008b45cc9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page