The Problem

Web crawlers, automated scanners, and opportunistic attackers waste resources probing exposed services. Distinguishing malicious traffic from legitimate crawlers is noisy and reactive. Krawl solves this by giving attackers a fake attack surface—decoy apps, fake credentials, and honeypot paths—so you can detect, track, and ban malicious IPs without risking real infrastructure.

What This Does

Krawl is a Python-based deception server. It serves thousands of realistic decoy pages (.env.html, .aws__credentials.html, fake admin panels) from src/templates/deception/, plus spider-trap pages that generate infinite random links. It logs every interaction, scores IP reputation, and can auto-ban via firewall integrations.

The project includes a real-time dashboard (src/routes/dashboard.py), an API (src/routes/api.py), background tasks (src/tasks/), and optional AI-generated deception pages (src/generative_ai.py). Deployment is flexible: Docker Compose, Kubernetes via Helm (helm/), or bare Python with Uvicorn.

How It Is Wired

Execution starts at src/app.py, which initializes the FastAPI app and mounts routes. Middleware in src/middleware/deception.py intercepts requests, checks the banlist, and serves decoy content. The src/routes/honeypot.py handles the actual deception responses. Every request touches src/database/access_logs.py to record the hit.

The import graph shows a mostly flat structure: 55 internal modules with only 2 import edges, and no circular dependencies. The only hub is src/templates/template_loader.py (2 modules import it), which loads HTML templates. This means the codebase is highly decoupled—each module is self-contained, but the trade-off is that the src/database/ modules (analytics, ip_stats) are oversized (790+ lines) and hard to change without wide ripple effects.

External effects: SQLite/PostgreSQL/MariaDB writes via src/database/core.py, firewall commands via src/firewall/iptables.py and src/firewall/nftables.py, and outbound LLM calls in src/generative_ai.py. The scripts/migrate_sqlite_to_*.py files handle database migrations.

How To Use It

Setup (from README):

git clone https://github.com/moses-y/Krawl
cd Krawl
docker compose up -d

For Kubernetes: helm install krawl ./helm (see helm/values.yaml).

Configuration: Edit config.yaml for wordlists, paths, and deception settings. Environment variables override these (documented in README). The .env.example.html is a decoy, not a real config.

Running: docker compose up is the primary path. Bare Python: uvicorn src.app:app from the repo root, but you'll need Redis and a database configured first.

Real-World Use

Deploy Krawl behind a reverse proxy alongside production services (see docs/reverse-proxy.md). Route all unknown paths to Krawl—legitimate crawlers hit decoys, get logged, and can be auto-banned via the banlist.txt integration. An attacker probing /.env gets a fake file with realistic credentials, triggering a canary token alert, and their IP lands on the banlist within minutes.

Code Health & Issues

Static analysis found 37 findings (6 high, 31 medium). Key issues:

  • High - Duplicated code: 177 repeated 6-line blocks across 16 files, notably scripts/migrate_sqlite_to_mariadb.py and scripts/migrate_sqlite_to_postgres.py. Extract shared helpers.
  • High - Deep nesting: 22 instances, max depth 8 in src/database/core.py and src/generative_ai.py. Flatten with guard clauses.
  • Medium - Broad exception handling: 7 instances of bare except in src/database/ip_stats.py, src/metrics_counters.py. Catch specific exceptions.
  • Medium - Oversized files: src/database/analytics.py (790 lines) and src/database/ip_stats.py. Split by responsibility.

Security audit findings: unpinned GitHub Actions (use commit SHAs), no lockfile (pyproject.toml), CI never runs tests (8 test files, no test command), continue-on-error on a correctness step, no non-root user in Dockerfile, and 1 test file covering 60 source files (ratio 0.017). Committed secrets are decoys—the audit confirms they're template files, not real credentials.

The Bottom Line

Krawl is a functional, well-documented deception tool with solid deployment options. The codebase is decoupled and easy to navigate, but the lack of a lockfile, untested CI, and oversized database modules are real risks if you plan to modify it. Use it if you want a self-hosted honeypot with minimal effort; budget time for CI fixes and test coverage before trusting it in production.