When AI Writes Your Firewall, Check the Math
A Python developer with "AI Solutions Architect" in their GitHub bio pushes 8,500 lines of eBPF Rust in a single commit. The commit author is "Blackwall AI." The .gitignore lists .claude/. The README reads like marketing copy, and the author later confirms the AI handled the "marketing glaze." Four days later, the repo has 119 stars.
This is the new normal. People are shipping real projects in languages they don't primarily work in, at speeds that weren't possible two years ago. The question isn't whether AI-assisted code can be good. It's whether you can tell the difference between code that's good and code that looks good.
I went to find out.
What Is Blackwall?
Blackwall is an eBPF/XDP firewall with an LLM-powered honeypot, written in Rust. Named after the AI containment barrier in Cyberpunk 2077. It runs packet filtering at kernel level via aya (pure Rust eBPF, no C, no libbpf), tracks per-IP behavioral profiles through a state machine that escalates from New to Normal to Probing to EstablishedC2, does JA4 TLS fingerprinting and deep packet inspection, and includes a tarpit that uses a local LLM through Ollama to simulate a compromised Ubuntu server. The idea is that when the behavioral engine flags an IP as hostile, traffic gets redirected to the honeypot, which pretends to be a real machine while logging everything the attacker does.
One maintainer. Two commits. 119 stars in four days. MIT license.
The Snapshot
| Project | blackwall |
| Stars | ~119 at time of writing |
| Maintainer | Solo (xzcrpw), shipped everything in one commit |
| Code health | 8,544 lines, 123 tests, zero unwrap() in production, real bugs in the glue code |
| Docs | AI-generated README that oversells, no architecture docs |
| Contributor UX | No CONTRIBUTING.md, no CI, no PR history to judge from |
| Worth using | Not yet, but worth reading |
Under the Hood
Six crates in a Cargo workspace. common holds #[repr(C)] shared types between kernel and userspace with explicit padding fields. blackwall-ebpf has the XDP programs. blackwall is the userspace daemon. tarpit is the honeypot. blackwall-controller coordinates distributed nodes. xtask handles eBPF cross-compilation.
The eBPF code is the strongest part. Every pointer dereference has a bounds check before access, which is not just good practice but a hard requirement: the BPF verifier will reject your program otherwise, and getting this right in Rust via aya is harder than it sounds. The entropy estimation uses a 256-bit bitmap instead of a histogram, which is a clever adaptation for eBPF's 512-byte stack limit. The TLS ClientHello parser handles session IDs, cipher suites, compression methods, extensions, SNI extraction, ALPN, and GREASE filtering. If you want to see how to write correct eBPF in Rust, this is a solid reference.
The behavioral engine is clean too. Seven phases from New through EstablishedC2, monotonically increasing in suspicion with an explicit demotion path to Trusted. The state machine uses deterministic thresholds for fast-path decisions, with optional LLM classification as a slow path. Constants are well-named and consistent: SUSPICION_INCREMENT at 0.15, SUSPICION_MAX at 1.0, SUSPICION_DECAY at 0.02. Trusted promotion requires the score to stay below 0.1 across 300 seconds and 100+ packets.
The tarpit is where things get creative. It runs four protocol handlers: SSH (backed by the LLM pretending to be a bash shell), HTTP (fake WordPress), MySQL (wire protocol responses), and DNS (canary records). The SSH honeypot's system prompt is detailed enough to be convincing. It specifies hostname, kernel version, filesystem layout, installed services, and includes example command/output pairs so the LLM knows to respond with raw terminal output instead of "Sure, here's the output of ls."
Now for the bugs. The project ships with "think": false in its Ollama requests, but some models emit <think> blocks anyway. The stripping code handles exactly one block:
if let Some(start) = content.find("<think>") {
if let Some(end) = content.find("</think>") {
let after = &content[end + 8..];
after.trim_start().to_string()
If the model emits two <think> blocks, the second one passes through to the attacker, leaking the LLM's reasoning about how to respond. A security tool with a security bug.
The DPI path matching is aggressive. It flags any HTTP path starting with /wp-, /adm, /cm, or /cg as suspicious, which would catch /admiral-insurance or /cmarket. The random_window_size() function in the tarpit's anti-fingerprinting module computes a value and discards it (let _window = random_window_size()). TCP window randomization is advertised in the README but doesn't actually happen. The iptables DNAT rules that redirect traffic to the honeypot persist after a SIGKILL because Drop cleanup gets skipped. Several modules (distributed, antifingerprint, canary) carry #[allow(dead_code)] annotations, meaning they're defined but not wired into anything.
No CI. No GitHub Actions. The README claims "Clippy: zero warnings (-D warnings)" but nothing enforces it. The entire development history is two commits: "release: blackwall v1" and "images."
The Contribution
The suspicion score scale mismatch was the clearest bug to fix. The behavioral engine operates on a 0.0 to 1.0 scale. Increments are 0.15, max is 1.0, decay is 0.02 per evaluation, and trusted promotion requires < 0.1. But the DPI event handler in process_events was adding 15.0 and capping at 100.0. A completely different scale. Any IP that triggered a single DPI detection got a suspicion score of 15.0+, making trusted promotion effectively unreachable. At a decay rate of 0.02 per tick, it would take roughly 750 ticks to come back under 0.1.
The fix was small: export SUSPICION_INCREMENT and SUSPICION_MAX from the behavior module and use them in the DPI handler, matching the pattern already used by apply_escalation in the transition logic. Three files, 11 insertions, 5 deletions. All 19 behavior tests pass.
Getting into the codebase was easy despite the size. The workspace structure keeps things separated, the naming is consistent, and the behavioral engine is self-contained enough that you can understand the state machine without reading the eBPF code. Finding the bug was a matter of grepping for suspicion_score and noticing that one callsite looked nothing like the others.
PR #3 got a response the same day. The maintainer had independently found the same bug during a major architectural rewrite and closed the PR to avoid merge conflicts with the new core. "Nice catch on the scale mismatch, man." He shipped v2.0.0 hours later, overhauling the behavioral engine and moving to native eBPF DNAT. Someone else's detailed bug report got a similar response: all findings would be addressed in the rewrite. Both are now closed.
The Verdict
Blackwall is interesting as both a codebase and a case study. The eBPF work is genuinely competent. The behavioral engine is well-designed. The honeypot concept is creative. But it shipped in one commit with no CI, no development history, and bugs in the code that connects the components together. The strongest parts (kernel programs, type contracts, state machine) look like they were built carefully. The weakest parts (DPI integration, think-tag stripping, dead code) look like they were assembled and not tested end-to-end.
That's not a criticism of using AI to write code. It's a criticism of shipping without integration testing, regardless of who or what wrote it. The eBPF verifier forces you to be correct in the kernel programs. Nothing forces you to be correct in the glue.
If you work with eBPF, the XDP programs and the aya patterns are worth studying. If you're interested in honeypot design, the tarpit's multi-protocol approach and LLM integration are genuinely novel. The maintainer shipped a v2.0.0 rewrite the same week, which suggests the integration bugs are being addressed. If you want to run this in production, give the new version a serious read first. The architecture has changed significantly, and it hasn't had time to accumulate the kind of real-world testing you want from something sitting between attackers and your network.
Go Look At This
Blackwall on GitHub. Read the eBPF code even if you skip the rest.
If you want to contribute, the v2.0.0 rewrite is a fresh starting point. Our suspicion score fix and the bug report are both closed, addressed in the rewrite. The new codebase still has no CI, and the <think> tag stripping likely still needs work. The 35 MB of PNG assets are still there.
This is Review Bomb #N, a series where I find under-the-radar projects on GitHub, read the code, contribute something, and write it up. If you know a project that deserves more eyeballs, drop it in the comments.