--rules-bundle — out-of-band fingerprint rule updates¶
Most fingerprint detectors ship as rules embedded in the AgentHound binary
(sdk/rules/builtin/fingerprints/*.yaml). AgentHound provides a
--rules-bundle <path> override so operators can pick up rule fixes without
rebuilding the collector. Jupyter's stronger default detector is code-backed,
but an exact id: jupyter, service_kind: jupyter bundle rule can replace it.
The operator is responsible for verifying the cosign signature on the bundle BEFORE pointing AgentHound at it. Verification is optional by design — the loader does not call cosign automatically and does not refuse unsigned bundles. Always run
cosign verify-blobagainst the tarball yourself (see below) before pointing AgentHound at it.
Quick start¶
# Download a published bundle.
gh release download rules-v2026.06.01 \
--repo adithyan-ak/agenthound \
--pattern 'agenthound-rules-*.tar.gz*'
# Verify the cosign signature BEFORE running anything.
cosign verify-blob \
--bundle agenthound-rules-rules-v2026.06.01.tar.gz.sigstore.json \
--certificate-identity-regexp 'https://github.com/.*' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
agenthound-rules-rules-v2026.06.01.tar.gz
# Use the bundle in any command that runs fingerprinters.
agenthound --rules-bundle ./agenthound-rules-rules-v2026.06.01.tar.gz scan 10.0.0.0/24
# Or point at a directory of YAML files (during development / lab work).
agenthound --rules-bundle ./my-custom-rules/ scan 10.0.0.0/24
# Env var alternative.
AGENTHOUND_RULES_BUNDLE=./bundle.tar.gz agenthound scan 10.0.0.0/24
Override semantics¶
The bundle merges into the embedded rule set with same-id rules from the bundle winning:
| Embedded rule | Bundle rule | Effective rule |
|---|---|---|
id: ollama |
(absent) | embedded |
id: ollama |
id: ollama |
bundle (override wins) |
| Jupyter native detector | id: jupyter, service_kind: jupyter |
bundle rule replaces the native detector |
This is what you want for hot-fixing a shipped detector without rebuilding the
collector. A bundle does not register a new fingerprinter module or scanner
dispatch target: arbitrary additive IDs are not executable merely because they
load. Jupyter overrides must use the reserved jupyter ID; another Jupyter ID
is reported in ruleset.errors and excluded from effective semantics. The
override must emit exactly [JupyterServer, AIService] in that order; node
identity, endpoint, service kind, and detector-provenance properties remain
collector-owned even if a bundle tries to set them.
Bundle format¶
A bundle is one of:
- A directory containing
*.yamlfiles (one rule per file). Non-yaml files and sub-directories are skipped. - A
.tar.gzarchive containing one or more*.yamlregular-file entries (the archive path prefix does not matter — the loader acceptsfoo.yaml,fingerprints/foo.yaml, or any other layout). Non-yaml entries, directories, and symlinks are skipped.
Each YAML file follows the same shape as the embedded rules at sdk/rules/builtin/fingerprints/:
id: ollama
name: Ollama (CVE-2026-XXXXX hotfix)
description: refines the Ollama version regex to catch the new patch series
version: 2
service_kind: ollama
probes:
- method: GET
path: /api/version
matchers:
- type: http_status
status_code: 200
- type: json_path
path: "$.version"
regex: '^\d+\.\d+\.\d+(-rc\d+)?$'
captures:
version: "$.version"
emit:
node_kinds:
- OllamaInstance
- AIService
properties:
service_kind: ollama
auth_method: none
is_anonymous_loot: "true"
version: "{capture:version}"
Rule IDs SHOULD be unique within a bundle. MergeFingerprintRules deduplicates by ID with last-write-wins semantics — if the same ID appears twice in one bundle, the last one parsed silently overwrites the earlier one (there is no load-time conflict error). Across the bundle + embedded merge, any bundle rule always wins over an embedded rule with the same ID.
Release cadence¶
Bundles are published by the rules-bundle.yml GitHub Actions workflow. Triggers:
workflow_dispatch— manual release, used for ad-hoc rule fixes.on: push: tags: ['rules-v*']— pushing arules-vYYYY.MM.DDtag automatically cuts a release.
There is no on: schedule trigger. Bundles are content-driven — a no-changes month produces no bundle. An empty release would confuse cosign verification on the consumer side.
The release artifacts:
agenthound-rules-<tag>.tar.gz— the bundle.agenthound-rules-<tag>.tar.gz.sha256— checksum.agenthound-rules-<tag>.tar.gz.sigstore.json— cosign keyless bundle (signature + certificate, cosign v3 format).
Troubleshooting¶
Bundle doesn't load at all. Check the path. agenthound --rules-bundle <path> surfaces the error from LoadFingerprintBundle if the path doesn't exist or doesn't unpack. Check the format with tar -tzf <bundle>.tar.gz showing one or more *.yaml entries.
Bundle loads but my override doesn't take effect. Same-id-wins requires the
bundle's rule ID to match the shipped detector ID exactly. Jupyter specifically
requires id: jupyter, service_kind: jupyter, and ordered node kinds exactly
[JupyterServer, AIService]. The scan artifact's ruleset.entries records the
rule or native detector that actually ran; ruleset.errors reports unsupported
Jupyter rules instead of presenting them as effective.
Bundle loads but a rule is silently dropped. The loader skips files that fail YAML parsing. Sanity-check bundle files with yamllint — agenthound rules validate uses the detection-rule schema (sdk/rules/rule.go) rather than the fingerprint-rule schema (sdk/rules/fingerprint.go), so it will not accept a fingerprint YAML. The tar.gz reader also caps per-entry size at 1 MiB (fingerprint YAMLs are tiny; larger entries are treated as suspicious and skipped). The directory reader has no per-file size cap.
Cosign verification fails. The --certificate-identity-regexp in the example matches GitHub Actions OIDC. If you forked the repo and re-released, your cert identity will differ — adjust the regex. Time skew can cause verification failures if your machine clock is off; sync NTP.
See also¶
sdk/rules/bundle.go— implementation ofLoadFingerprintBundleandMergeFingerprintRules..github/workflows/rules-bundle.yml— the release pipeline.agenthound scanoperator guide — the network scanner that consumes fingerprint rules.