My lunch-break response to ARTEX: a host intrusion sentinel A draft, unreleased host intrusion sentinel called ARTEX pairs a per-machine Python agent that scores running programs and their network connections in code with a Cloudflare Worker service that re-scores signals, stores cases encrypted and returns operator decisions and learned weights. The tool was built in response to FBI FLASH-20261113-001 on agentic intrusion frameworks and targets web shells, loaders, remote-access implants, Windows-to-Windows movement, Active Directory attacks and automated-operator pacing, with four response modes (kill, decide, pause, report) and a default of decide when a model is configured or kill when it is not. The author states the project is a draft that has not been released and directs readers to a 'What has and has not been tested' section before relying on it. A host intrusion sentinel you run yourself. A small agent on each machine watches running programs and their network connections, scores what it sees in code, and reports the cases that look like an attack to a service you deploy in your own Cloudflare account. By default it also ends a hostile program, and everything that program started, on the spot. It was built in response to FBI FLASH-20261113-001 on agentic intrusion frameworks, and it is aimed at the things those tools do on a machine: web shells, loaders, remote-access implants, movement between Windows machines, Active Directory attacks, and the pace and repetition of an automated operator. Status: draft, not yet released. Read "What has and has not been tested" before relying on it. each machine your Cloudflare account ┌──────────────────────────────┐ HTTPS out ┌─────────────────────────────────┐ │ agent/sentinel agent.py │ ────────────► │ server/src/worker.mjs Worker │ │ sensors → scoring → cases │ ◄──────────── │ cases, decisions, learning │ │ pause / stop if approved │ decisions, │ D1 database, optional AI │ └──────────────────────────────┘ weights └─────────────────────────────────┘ - The agent reads the operating system's own process and connection tables. It captures no packets and reads no file contents. It opens no port. Scoring happens on the machine. - Only cases leave the machine : a program that reached the SUSPECT or HOSTILE level, with the signals that fired, the programs that started it, and the addresses it talked to. A command line never leaves the machine; the agent reports which pattern matched, not the text. - The service checks every field, scores the signals again the level is never taken from the device , stores the case encrypted, raises an alert, and hands back two things: the operator's decision on a program that agent paused, and the learned signal weights. - It acts, within limits. It never touches operating-system processes, security software, container runtimes, remote access sshd , the web server itself, or the browser, mail or document program a person is working in: it ends the harmful thing those programs started, not the programs. It never signals a process that has already exited. | Mode | What the agent does about a hostile program | Choose it when | |---|---|---| | kill | ends it and everything it started, at once, then reports what it did | an intruder's minutes matter more than a wrongly stopped job | | decide | freezes it at once, then the service's decision model says stop, release or hold | you have a model and want a false alarm to cost seconds, not a program | | pause | freezes it reversible and waits for an operator to stop or release it | a wrong stop would be an outage | | report | nothing; it only reports | you are evaluating, or another tool responds | Set the ceiling for the whole deployment with the service variable RESPONSE MODE , and a machine's own mode with --mode at enrolment. A machine gets the lower of the two. The default. With RESPONSE MODE left empty, a deployment with a model configured runs decide , and one without runs kill . Agents ask for kill unless told otherwise. How decide works. The agent freezes the program the moment it is judged hostile, so the attack is already stopped while the decision is made. The service asks the model once, with an eight-second limit, and answers in the same exchange: - stop when the model recommends it with high confidence: the agent ends the program. - release only if you set DECISION RELEASE to high-confidence , the model is highly confident, and no locked signal is involved a published indicator, credential theft, a directory attack . The agent lets it run and leaves it alone afterwards. A model's release does not mark the program as yours and teaches nothing. - hold in every other case: it stays frozen until an operator decides. If the model fails or times out, DECISION FALLBACK decides: kill the default or hold . An agent that hears nothing from the service at all for twenty seconds applies the same fallback by itself. Kill is not reversible. In kill mode a false alarm ends a legitimate program; decide exists to avoid exactly that. The agent acts only on specific launch chains with almost no honest use, or on cases whose evidence spans three categories, and a program an operator marks "ours" is never touched again. Even so: run pause or report first on machines where a wrong stop is costly, and watch what it would have done. If you run report or pause , run the AI analyst as well see "The AI part" . In those modes nothing ends an attack until a person reads the case, and an automated intruder works in minutes. A second, independent model reading every case and recommending stop or release shortens that wait; keep it separate from whatever AI your organisation already uses, so one compromised or confused system is not judging its own work. | Area | Signals | |---|---| | Email and lures | scripts started by mail, document and browser programs; programs run out of attachments and archives; shortcut and paste-this-command launches | | Web applications | a shell or interpreter started by a web server; download-and-run and reverse-shell commands; who-am-I commands | | Loaders and implants | system tools used as loaders MSBuild, cmstp, regsvr32, rundll32, mshta ; programs in temporary folders talking to the internet; regular call-home timing; fan-out scanning | | Windows domains | credential dumping and Kerberoasting commands; domain enumeration; shells inside WinRM, WMI and PsExec sessions; and, when the agent runs with administrator rights, Security-log patterns for Kerberoasting, DCSync, failed sign-in bursts, cleared logs and privileged group changes | | Automated operators | a stream of different commands at machine pace under one foothold; near-copy retries; the same command started twice at once | | Web requests | read from the web server's own access log nginx, Apache, IIS : directory fuzzing, injection-shaped requests and whether the application answered them, walking through record numbers, sign-in guessing, calls to a server-side script with a command parameter, and bursts of application failures on requests that carry a body | | Web folders | a server-side script that appears in a web folder after the agent started, with no release around it | | Tunnels | Chisel by name; SoftEther by its program names with its install folder or its ports; Tor by its client, by any program sending traffic through the local Tor proxy, and by inbound connections from the Tor Project's published exit nodes | | Attempts from outside | bursts on SSH, Remote Desktop, WinRM, SMB, VNC and Telnet | | Published indicators | the addresses and domain listed in FBI FLASH-20261113-001, as a scored signal with the FBI's caveat that addresses get reassigned; never an automatic block | | Antivirus | new Windows Defender detections become cases | | Cloud credentials | a web server process reaching for the cloud metadata service, where instance credentials are handed out | | Cloud control planes | from audit records you forward: credentials added to applications and service principals, ownership, role and consent grants, weakened Conditional Access and federation settings Microsoft Entra ; permission mapping by dry-run, key pairs, public addresses, large volumes, role-bearing instances, access keys made for other users, administrator policies AWS CloudTrail ; validation dry-runs, publishing credentials and storage keys Azure activity log ; and any of it from an address in the FLASH | Signals are weighted and grouped into categories. A case is called HOSTILE only when the evidence spans at least three categories, so no single rule decides it. Needs Node.js 22.5 or newer and Python 3.9 or newer. python cd server export SENTINEL ENROLL KEY=$ python3 -c "import secrets;print secrets.token hex 24 " export SENTINEL ADMIN TOKEN=$ python3 -c "import secrets;print secrets.token hex 24 " node local.mjs in-memory database, for evaluation only In another terminal, with the same two variables set: python3 agent/sentinel agent.py --state-dir ./state enroll --server http://127.0.0.1:8787 python3 agent/sentinel agent.py --state-dir ./state run curl -H "Authorization: Bearer $SENTINEL ADMIN TOKEN" http://127.0.0.1:8787/v1/devices curl -H "Authorization: Bearer $SENTINEL ADMIN TOKEN" "http://127.0.0.1:8787/v1/cases?state=open" Copy server/wrangler.example.jsonc to server/wrangler.jsonc , then follow the commands at the top of that file: create the D1 database, load schema.sql , set the three secrets, deploy. Three secrets are required and each must be at least 32 characters: | Secret | What it is for | |---|---| | DATA KEY | encrypts case evidence at rest AES-256-GCM | | ENROLL KEY | lets a machine enrol; share it only with the people who install agents | | ADMIN TOKEN | lets an operator read cases and make decisions | Optional: ALERT WEBHOOK URL receives a JSON alert for each new case. The alert text is written by the service from the signal ids; text from a device is never placed in an alert. | Where | How | |---|---| | Linux systemd | sudo SENTINEL ENROLL KEY=