Skip to main content
BLACKLIGHTrfxnforged in prod

# no one is coming.

>_ defend.

BLACKLIGHT

>_ Agentic Defense. Human Trust. Attacker Speed.

Built with Opus 4.7 · HackathonAnthropic × Cerebral Valley · Apr 21–28

Curator

Opus 4.7

1M context

Time to defense

8 hr → 10 min

APSB25-94 case

Skills

65 files

20 domains

Substrate

CentOS 6 → 24.04

15 yrs of tooling

Why now

From 2.3 years to 10 hours.

Time-to-exploit has collapsed by four orders of magnitude in eight years. The defender's tooling did not. The chart below tracks the average gap between CVE disclosure and confirmed weaponized exploitation across 3,532 paired CVE-exploit records.

Mean time-to-exploit (TTE)

source: zerodayclock.com
2018
2.3 years
2019
1.9 years
2020
1.3 years
2021
10.8 months
2022
9.7 months
2023
4.9 months
2024
56 days
2025
23 days
2026
10 hours
Based on 3,532 CVE-exploit pairs from CISA KEV, VulnCheck KEV and XDB. 10% trimmed mean. Lower is worse for defenders.

And it isn't theoretical

Marimo RCE CVE-2026-39987 exploited within 10 hours of disclosure.

The Hacker News, Apr 10 2026

From CVE to RCE in Hours: The Collapse of the Exploitation Window.

HiveSecurity, 2026

Surge in vulnerability exploits dominates 2026 cyber intrusions.

Gopher Security, Mar 23 2026

WordPress plugin vulnerability exposes sensitive data from 800,000+ sites.

Cyber Security News, Mar 31 2026

The premise

Collapse the gap between
attacker speed and defender shift hours.

Without rip-and-replace. Without agent sprawl. Without walled gardens. Just the tools your team already trusts, responding at attacker speed.

Attackers are agentic-minutes ahead.

APSB25-94 dropped on a Saturday at 03:42 UTC. Eight hours later the on-call team had run grep, find, modsec scrapes, ClamAV passes, APF drops, and crontab audits across forty hosts, by hand. The exploit took minutes. The defense took a shift.

Critical infrastructure is buried in legacy.

Millions of production servers won't be modernized. Millions more belong to orgs that will never have a dedicated security team or an enterprise XDR. The substrate is real, it is critical, and it is staying.

The tooling is already there.

ModSecurity, iptables, nftables, APF, CSF, LMD, ClamAV, YARA, fail2ban: fifteen years of Linux defensive tooling sits on every host. They predate blacklight and will outlive it. We don't replace them. We direct them.

Architecture

Three layers. Hard boundaries. No new substrate.

The Runner executes. The agent reasons and prescribes. The host primitives are the hands. Each layer is the only one that touches its surface, the contract is enforced by code, not convention.

Layer 01

Runner

bl on the host

bash 4.1+ · curl · jq · ~one file

Six runtime verbs: observe, consult, run, defend, clean, case. No daemons. No services. Invoked per operator thought; exits when done. The Runner never decides what action to take. It executes what the Curator prescribes, gated by safety tiers.

Surface

bl observebl consultbl runbl defendbl cleanbl case

Layer 02

Curator

Managed Agent session

Anthropic-hosted · Opus 4.7 · 1M context

Named curator agent (bl-curator), tool environment with apache2 + mod_security2 + yara + duckdb, two memory stores (bl-skills read-only, bl-case read-write). Persistent case state across days, the Curator already holds the hypothesis, the prior evidence, and the pending steps.

Surface

bl-curatorbl-curator-envbl-skills (ro)bl-case (rw)report_stepsynthesize_defensereconstruct_intent

Layer 03

Substrate

Defensive primitives on the host

What you already trust

apachectl + mod_security, APF, CSF, iptables, nftables, LMD, ClamAV, YARA, Apache / nginx logs, journalctl, crontab, find, stat. blacklight directs the Substrate, it does not install, replace, or re-abstract it. The primitives predate blacklight and will outlive it.

Surface

ModSecAPFCSFiptablesnftablesLMDClamAVYARAfail2ban

Layer boundary rules

  • Runner → Never decides what action to take. Executes the Curator's prescriptions under safety-tier gates and reports results.
  • Curator → Never touches the host filesystem or primitives directly. Reasons, authors, prescribes, never applies.
  • Substrate → Untouched by blacklight source. No new rule engines, no new manifests, only native usage of existing primitives.

Walkthrough

APSB25-94 polyshell, root-caused and contained in under ten minutes.

Magento store. Double-extension webshell hidden in the media cache. One operator, one host, four commands. Eight man-hours of manual IR collapses into agentic-minutes on the substrate the defender already runs.

01

Collect Apache logs and check the filesystem

$ bl observe log apache --around /var/www/html/pub/media/catalog/product/.cache/a.php --window 6h
$ bl observe fs --mtime-since --since 2026-03-20T00:00:00Z --under /var/www/html --ext php
blacklight: obs-0001 apache log records → bl-case/CASE-2026-0001/evidence/obs-0001-apache.transfer.json (3 records)
{"ts":"2026-03-22T14:23:51Z","host":"magento-prod-01","source":"apache.transfer","record":{"client_ip":"203.0.113.42","method":"POST","path":"/pub/media/catalog/product/.cache/a.php","status":200,"path_class":"php_in_cache","is_post_to_php":true}}
 
blacklight: obs-0002 fs records → bl-case/CASE-2026-0001/evidence/obs-0002-fs.mtime-since.json (1 record)
{"ts":"2026-04-25T00:00:00Z","host":"magento-prod-01","source":"fs.mtime-since","record":{"path":"/var/www/html/pub/media/catalog/product/.cache/a.php","mtime":"2026-03-21T23:58Z","ext":"php"}}
02

Open a case and consult the curator

$ bl consult --new --trigger "APSB25-94 double-extension webshell, obs-0001 obs-0002"
blacklight: CASE-2026-0001 opened
blacklight: curator session wake enqueued
blacklight: pending step s-0001 ready
verb: observe.modsec
tier: read-only
reason: confirm rule coverage before prescribing defensive payload
Run: bl run s-0001
03

Execute the curator-prescribed step

$ bl run s-0001
blacklight: s-0001 observe.modsec [read-only], running
modsec rule hit on REQUEST_URI @rx /\.php/[^/]+\.(jpg|png|gif) id:920450
blacklight: result written to case memstore
blacklight: pending step s-0043 ready
verb: defend.modsec
tier: suggested
reason: obs-0001 + obs-0002 + s-0001 confirm polyshell staging pattern
diff: +SecRule REQUEST_FILENAME "@rx \.php/[^/]+\.(jpg|png|gif)$" \
"id:941999,phase:2,deny,log,msg:'polyshell double-ext staging'"
Confirm and apply? [y/N]
04

Apply the ModSec rule

$ bl run s-0043 --yes
blacklight: s-0043 defend.modsec [suggested], applying
apachectl -t ... OK
rule installed: /etc/apache2/mods-enabled/bl-CASE-2026-0001-941999.conf
apache2ctl graceful ... OK
blacklight: ledger event defend_applied written
blacklight: CASE-2026-0001 defense step complete

Features

What makes blacklight work.

Curator with persistent case state

On first setup, blacklight provisions a Managed Agent (bl-curator), a tool environment, and two memory stores in the operator's Anthropic workspace. Case state, hypothesis, evidence, pending steps, accumulates in those stores across days of investigation. The curator already holds context next time you call. No re-prompting, no context reconstruction.

Managed Agents/var/lib/bl/state/30-day checkpoint

Three-tier model routing

Opus 4.7 for forensic synthesis across 250–400k token evidence bundles. Sonnet 4.6 for tier-gated step execution and bundle summaries. Haiku 4.5 for lightweight false-positive classification before signature append. Curator calls are infrequent and expensive by design; step calls are frequent and cheap by design.

Opus 4.7 · curatorSonnet 4.6 · stepsHaiku 4.5 · FP gate

Five action tiers, agent-authored, runner-enforced

Read-only, reversible-low, reversible-high, destructive, unknown. The agent classifies every step; the Runner enforces the gate based on verb class plus tier, never trust from the agent alone. Destructive steps require explicit per-operation --yes; unknown verbs deny by default.

read-only · autosuggested · diff-confirmeddestructive · backup-first

Skills as knowledge, read-only at the API

65 markdown files across 20 defensive domains, APSB25-94 exploit chains, ModSec grammar, webshell families, hosting-stack quirks, Linux forensics, false-positive heuristics. Loaded into bl-skills as read-only memory at session creation. Attacker-supplied log content cannot rewrite operator knowledge mid-investigation.

bl setup --syncskills/<domain>/*.mdread-only memstore

Evidence-as-state, not prompts

Every observation is JSONL on the wire, apache.transfer, modsec audit, fs mtime cluster, journalctl extracts. Bundles are tar+gzip with a summary.md the curator reads first. Raw logs never enter context directly; the curator drills into JSONL via grep/jq/duckdb tool-use on demand.

JSONL recordssummary.md ≤ 2KBduckdb · jq · grep

Defense-in-depth before apply

ModSec rules pass apachectl -t in the curator's sandbox before promotion. Firewall blocks check an internal CDN safe-list and ASN cache. YARA/LMD signatures clear a benign-corpus FP gate. Every clean operation writes a backup and supports --undo. Quarantine, never delete.

apachectl -tCDN safe-listFP corpus/var/lib/bl/backups/

Trust the gate, not the agent

When the Runner caught the curator in the act.

G-01action-tiers.md · Failure modes

Curator under-classified clean.cron as auto

Synthetic test: the curator emits a destructive crontab edit with action_tier=auto. Verb-class re-asserts and forces diff-confirm regardless of agent-asserted tier.

$ bl run s-0042
blacklight: pre-validate s-0042 verb=clean.cron tier=auto
blacklight: verb-class override → tier=destructive (clean.* always)
blacklight: agent-asserted tier rejected; diff-confirm gate engaged
blacklight: ledger event tier_override case=CASE-2026-0042 step=s-0042
Apply? [y/N/diff-full/explain/abort]
G-02security-model.md · Agent output validation

Curator emitted a verb that doesn't exist

Hallucinated dispatch: the curator proposes verb=clean.kernel-module, which is not in the Runner's verb table. Pre-validation rejects without prompting.

$ bl run s-0091
blacklight: pre-validate s-0091 verb=clean.kernel-module
blacklight: ERR unknown verb (not in dispatch table)
blacklight: tier=unknown → deny by default
blacklight: ledger event verb_unknown case=CASE-2026-0091
Hint: bl run s-0091 --unsafe --yes (discouraged; surfaces session warning)
exit 67 STEP_SCHEMA_FAIL
G-03action-tiers.md · Reversible, high-impact

Synthesized ModSec rule failed configtest

Sandbox-side `apachectl -t` runs against the curator's rule before the Runner ever sees it. Broken anchor never reaches the host.

blacklight: synthesize_defense → modsec rule s-0017
blacklight: sandbox apachectl -t ...
AH00526: Syntax error on line 1 of bl-CASE-2026-0017-941999.conf
SecRule: invalid operator @rx_unanchored
blacklight: rule rejected; not promoted to /etc/apache2/mods-enabled/
blacklight: ledger event defend_modsec_rejected reason=configtest_fail
G-04action-tiers.md · Reversible, low-risk + skills/false-positives

YARA signature matched the FP corpus

Proposed signature scans the benign-corpus before append. One match against a backup-artifact pattern and the signature is dropped on the floor.

blacklight: synthesize_defense → yara sig s-0103
blacklight: FP gate scanning /var/lib/bl/fp-corpus/ (842 files)
match: backup-artifact-patterns/wp-backup-2024.tar.gz.bak
blacklight: signature rejected; FP gate trip > 0
blacklight: ledger event defend_sig_rejected reason=fp_gate_trip
blacklight: curator notified; will iterate or abandon

Each example is exercised by a synthetic test in the BATS suite or a sandbox pre-flight that runs before the Runner sees the curator's emit. Full matrix in /blacklight/docs/action-tiers.

Skills bundle

20 domains. 65 markdown files. Browse them.

Skill authoring is an operator-voice discipline, not technical writing. Each file opens with a scenario, names a non-obvious rule, gives a concrete public example, and describes a failure mode. If the only available draft would be generic IR boilerplate, the file ships later, never as slop.

bl-skills/<domain>/*.md

read_only memstore

≤ 50 KB total bundle

apsb25-94

Exploit chain, indicators, and double-extension polyshell signature for the live Adobe advisory.

magento-attacks

Admin-path enumeration, writable-path footprints, and post-exploit persistence patterns specific to Magento.

modsec-grammar

Rules-101, transformation cookbook, anchor discipline. Authored from public ModSecurity docs and CRS.

apf-grammar

APF basics, deny-pattern conventions, RAB tuning so blocks survive a flush.

webshell-families

Polyshell, ANSI-cron persistence, gsocket argv-spoof, the shapes that haunt shared hosting.

obfuscation

chr-ladder, base64+gzinflate, eval-string concat. Layer separation for the intent reconstructor.

linux-forensics

Persistence patterns, network forensics, ANSI-obscured cron, operator literacy assumed.

ir-playbook

Case lifecycle and kill-chain reconstruction. The agent's procedural anchor for any new case.

ioc-aggregation

IP clustering, URL-pattern extraction, file-pattern extraction → YARA synthesis.

defense-synthesis

ModSec patterns, firewall rules, sig-injection, how the curator authors a payload that survives ops review.

false-positives

Backup-artifact patterns, vendor-tree allowlists. The discipline that keeps signatures in production.

hosting-stack

cPanel anatomy, CloudLinux CageFS quirks. The substrate of millions of production servers.

shared-hosting-attack-shapes

What hosting-stack attacks look like at scale. Tenant blast-radius and pivot patterns.

legacy-os-pitfalls

Pre-systemd, pre-/usr-merge, bash<4.2. The pitfalls that make CentOS 6 a 2026 substrate.

ride-the-substrate

The discipline of using existing primitives natively, not re-implementing them in a new abstraction.

agentic-minutes-playbook

Sweep-mode posture, retrospective fleet review against a fresh CVE, without opening a formal case.

remediation

Quarantine over delete, capture before kill, diff before apply. The five disciplines of bl clean.

timeline

Mtime cluster reasoning, log-stream alignment, ANSI-stripped event chronology.

actor-attribution

Observed vs dormant capability separation. What the sample does today vs what it could do tomorrow.

ic-brief-format

Severity vocabulary, brief template. The artifact bl case close renders to Files API on close.

How it got built

Forged in a hackathon. Authored with the model it ships on.

blacklight is a submission to the Anthropic / Cerebral Valley “Built with 4.7” hackathon. The Runner is bash, the curator is Opus 4.7, and the codebase was authored in Claude Code against the same Managed Agents API the Runner calls in production.

Lineage, R-fx Networks defensive OSS

    LMDLinux Malware Detect, tens of thousands of installs. Shell-native scanner. Order-of-magnitude faster in v2.0.1.APFAdvanced Policy Firewall, hundreds of thousands of installs. iptables-based with intuitive policy syntax.BFDBrute Force Detection, modular log parser, paired with APF for reactive blocking.blacklightThe agentic-defensive-era release in that family. Same Linux substrate. Same install discipline. Same operator vocabulary.

The closer

GREP
DESERVES
COMPANY.

installcurl-pipe-bash safe
$ curl -fsSL https://raw.githubusercontent.com/rfxn/blacklight/main/install.sh | sudo bash
bootstrap workspaceone-time per workspace
$ export ANTHROPIC_API_KEY="sk-ant-..."
$ bl setup
  • requires: bash 4.1+ · curl · jq
  • compat: CentOS 6 → Ubuntu 24.04
  • CI: Debian 12 + Rocky 9, BATS
  • on host: no daemons, no services

Every Linux defender has been carrying the same toolkit for a decade and a half, and carrying it alone. The substrate works. The substrate is staying. What it doesn't have is an agent who reads the logs at the same speed they're generated.

blacklight. an agentic layer on the defensive stack you already run.

ModSec · iptables · nftables · APF · CSF · LMD · ClamAV · YARA · fail2ban.