daemonaudit
Who can hurt your AI agent — and how badly.
daemonaudit is a red/blue security audit for self-hosted AI agent daemons. It finds the
secrets, the open doors and the weak policies on the machine your agent runs on, then tells
you the attack paths and the blast radius: what an attacker gets, from where, and
which single fix kills the whole chain.
Supports Hermes Agent and OpenClaw. Both are found automatically; a box running both gets one report. Generic MCP configs are on the roadmap.
Install
uvx daemonaudit scan --red # zero-install run
pipx install daemonaudit # or: pip install daemonaudit
Requires Python ≥ 3.10. Dependencies: psutil, rich, pyyaml. Linux, macOS and Windows.
From a clone: python -m pip install -e '.[dev]'.
What it looks like
| Hermes demo home | OpenClaw demo home |
|---|---|
Both are daemonaudit scan --red against a deliberately-broken demo home with fake credentials — build your own with python scripts/demo_home.py [--openclaw].
Why not just the built-in audit?
Framework auditors ask "is my config right?". daemonaudit asks "what does an attacker
standing here actually get?" — and it looks at the host, not just the config: backups,
transcripts, sqlite state, process environments, listening sockets, and the skills you installed.
Then it chains the findings: an exposed port plus an unsandboxed backend plus keys in the
environment is one attack path, and it names the one hop whose fix breaks it.
Use
daemonaudit scan # passive audit (safe anywhere): secrets, perms, policy, skills, listeners
daemonaudit scan --red # + active probes against THIS host, attack paths, blast radius
daemonaudit scan --html report.html # a self-contained HTML report (also --json)
daemonaudit scan --home /path/to/.hermes # or /path/to/.openclaw — the framework is recognised from the directory
daemonaudit checks # list every check (and which framework each implementation covers)
--red adds three probes that only ever touch localhost: it connects to the daemon's own
listeners to see which answer without a password, reads the daemon's process environment, and
reads the vault the way any process running as you could — to measure the real local blast radius.
What it checks
21 checks in seven areas — SEC secrets outside the vault · PERM file permissions · NET listeners and sockets · POL policy (approvals, sandbox, who may talk to the agent, exposure, webhooks, debug leaks, content guards, credential passthrough, literal secrets) · SKILL risky skills and context files · ADV freshness · RED localhost probes. The same check id means the same class of weakness on every framework; each framework has its own implementation where the config differs.
Full check matrix — what each id reads on Hermes and on OpenClaw
| id | Hermes | OpenClaw |
|---|---|---|
| SEC-001 secrets outside the vault | config, backups, state.db, transcripts, logs |
sessions/*.jsonl, state/openclaw.sqlite, agents/*/agent/models.json, workspace, backups — vault files (openclaw.json, .env, credentials/, auth-profiles.json, openclaw-agent.sqlite, devices/) are never "sprawl" |
| PERM-001/002/003 permissions | vault/state readable by others, weaker backups, writable/executable state | same, plus $include files and the gateway log in /tmp/openclaw |
| NET-001/002 listeners & sockets | api server / webhook / CDP ports | gateway port (gateway.port, default 18789) and the browser control port |
| POL-001 approval bypass | HERMES_YOLO_MODE, HERMES_EXEC_ASK, --yolo in units |
tools.exec security=full + ask=off (incl. the trusted-operator default, graded MEDIUM), exec-approvals.json askFallback/autoAllowSkills, interpreters without strictInlineEval |
| POL-002 approvals config | approvals.mode, cron/one-shot auto-approve, broad allowlists |
broad exec allowlist patterns, tools.elevated wildcards, /bash, interpreters as safeBins |
| POL-003 host execution | terminal.backend: local without a write root |
sandbox.mode: off / non-main per agent scope (defaults and every agents.list[] override), tools.exec.host drift, dangerous Docker binds/network/seccomp |
| POL-004 allow-all users | *_ALLOW_ALL_USERS |
dmPolicy: open, allowFrom: ["*"], groupPolicy: open, name matching, session.dmScope: main with several senders |
| POL-005 exposed / unauthenticated service | API server host/key/CORS | gateway.bind, gateway.auth.mode, short tokens, Tailscale funnel, Control-UI device-auth/origins bypasses, trusted-proxy misconfig, gateway.tools.allow, node commands, mDNS full |
| POL-006 webhooks & dashboard | WhatsApp/Telegram webhook secrets, dashboard auth | hooks.token missing/short/reused, hooks.path: /, caller-chosen session keys, Telegram/Zalo webhook secrets, admin-http-rpc without auth |
| POL-007 debug leaks | redaction off, request dumps, OAuth trace, Langfuse | logging.redactSensitive: off, trace logging, OPENCLAW_DEBUG_MODEL_PAYLOAD, gateway token in a service unit, OTel export |
| POL-008 content guards | private-URL fetch, tirith, project plugins | browser SSRF policy, allowUnsafeExternalContent, plugins without plugins.allow, prompt-injecting plugins, acpx approve-all |
| POL-009 credential passthrough | terminal.env_passthrough, credential file mounts |
master keys in skills.entries.*.env / internal hooks, credentials handed to the sandbox |
| POL-010 literal secrets in config | mcp_servers.*.env |
mcp.servers.*.env, plus every other literal credential in openclaw.json that could be a SecretRef |
| SKILL-001 risky skills & context files | ~/.hermes/skills, bundled-skill detection, required_environment_variables |
every skill root OpenClaw loads (managed, workspace, ~/.agents/skills, extra dirs, hooks), metadata.openclaw.requires.env, bundled skills from the npm package, all workspace context files |
| ADV-001 freshness | .update_check cache, acked advisories |
update.checkOnStart, security.audit.suppressions, CLI/config version drift |
| RED-001/002/003 probes | unauthenticated HTTP, process env, vault | same; the Control UI / /health paths are expected to answer anonymously and are reported as such, not as findings |
Where OpenClaw's own openclaw security audit has a matching checkId, the finding names it. daemonaudit adds what that audit does not look at: the host (transcripts, sqlite, backups, process environments, listeners), the skills you installed, and the chaining into attack paths.
Each finding says why it matters, the exact fix, and a command to verify it.
Principles
- Read-only. It never changes your system.
- Zero network egress. Nothing leaves the box. The active probes connect to localhost only, and refuse any target that isn't this host.
- Redacted by construction. The report can show you
sk-ant-…4f2a; it cannot show you the key. Nothing that leaves the process — terminal, JSON, HTML — contains a raw credential. - No false passes. A check that can't run says skipped, never ok. A config file that doesn't parse skips every check that reads it — it never evaluates defaults and calls them a pass. A scan that couldn't complete exits non-zero.
Exit codes (for cron / CI)
| code | meaning |
|---|---|
| 0 | clean, and every check completed |
| 1 | findings (low/medium) |
| 2 | high or critical findings |
| 3 | no supported daemon found (use --home) |
| 4 | no findings, but a check was skipped/errored/incomplete — not a clean bill |
| 5 | the tool itself failed (--debug for a scrubbed traceback) |
Precedence 2 > 1 > 4 > 0. INFO-only findings don't affect the exit code.
Roadmap
- v0.1 — Hermes: secrets, permissions, policy, skills, exposed services, localhost red probes, attack-path report. Linux · macOS · Windows.
- v0.2 — OpenClaw adapter: same checks, same attack-path rules, both daemons in one report. v0.2.1 closes the "config doesn't parse → pass" hole on both frameworks and aligns
$include, config-path and per-agent sandbox handling with OpenClaw's own rules (CHANGELOG). - next — generic MCP config adapter, traversal-aware permission grading, the framework's own executable tree, canary-injection probe, local-LLM (Ollama) semantic skill review, guided remediation with rollback, richer Windows ACL model, continuous monitoring / drift alerts.
Development
pytest runs the suite (Linux/macOS/Windows in CI). The design invariants live in
AGENTS.md; the plan and history in BUILD.md; releases in
CHANGELOG.md. Built with a two-model workflow — one model builds, another reviews
and writes adversarial fixtures; the review rounds are under reviews/.
License
MIT — see LICENSE.
Metadata
Release files for daemonaudit 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| daemonaudit-0.2.1.tar.gz | 165.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| daemonaudit-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 269.7 kB
Release files / daemonaudit-0.2.1.tar.gz
| Download URL | daemonaudit-0.2.1.tar.gz |
|---|---|
| Size | 165.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7f9201d7584f95731bbaf9c74f3c06bf98c4b1441c22f9cd8a10e4f54ebe2ef2
|
|
BLAKE2b-256 checksum How to use checksums |
01360e2642d9a79f3167abc888b7de7a34e42b367a15bba13eed22a436248c22
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 31, 2026.
Transparency logRelease files / daemonaudit-0.2.1-py3-none-any.whl
| Download URL | daemonaudit-0.2.1-py3-none-any.whl |
|---|---|
| Size | 104.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e57af67889793c9eca42f7f03016841755759ba51691d0df1e5d503145ec346c
|
|
BLAKE2b-256 checksum How to use checksums |
1299f08998cf0fe1bbf819cbf345f9a5828941f741849aa5a4787a72326522e1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 31, 2026.
Transparency log