
Research
/Security News
77 Firefox Extensions Linked to Crypto Wallet and Credential Theft
Socket uncovered 77 linked Firefox extensions, including 40 that steal wallet secrets or credentials and 37 deceptive sports-score shells.
aileron
Advanced tools
Flight recorder for AI agents: tamper-evident audit logging, policy enforcement, and incident reports
Aileron is a flight recorder for AI agents.
Not another tracer. Aileron produces a tamper-evident, replayable record of every tool call your agents make - evidence you can verify offline, not telemetry you have to trust.
aileron verify says exactly where
the chain broke.allow / alert / block actions, applied before execution via the
MCP stdio proxy or the SDK decorator. A blocked tool call never runs; the
attempt is logged anyway.$ pip install aileron
$ aileron demo # scripted fake-agent session (no network, no keys needed)
demo: wrote 8 events to demo.chain.jsonl
demo: chain VERIFIED (8 events)
demo: blocked shell call by rule aileron-001
demo: 2 anomaly alert(s) emitted
$ aileron verify demo.chain.jsonl
OK: 8 events verified in demo.chain.jsonl
$ aileron report demo.chain.jsonl -o incident.html # open it in a browser
The demo runs in the default digest-only mode: the destructive shell call is blocked by a content rule and flagged by the behavioral baseline, yet the journal on disk contains only argument digests - never the raw command.
| Feature | What you get |
|---|---|
| Hash-chained journal | Append-only JSONL; each event's prev_hash links to the previous event's SHA-256 hash; genesis is 0x00…00 |
| Signed checkpoints | Ed25519 signature over the chain tip, verifiable offline against the public key (aileron sign-checkpoint / verify-checkpoint). Checkpoints cover a prefix: appending later events never invalidates them; truncating or rewriting the signed prefix does |
| Policy rules | 32 bundled rules covering credential theft, cloud metadata abuse, exfiltration, supply chain, persistence, anti-forensics, database destruction, and prompt-injection artifacts. Sigma-like YAML; substring, regex, and dotted-key matchers. Rules are evaluated against the full call in memory, so content rules fire even in digest-only mode |
| Behavioral anomaly detection | Rolling baselines flag first-seen tools, rate spikes (>3x baseline), and novel tool-call sequences - live via the SDK (baseline=) or offline via aileron detect |
| MCP stdio proxy | Sits between any MCP client and server; logs and mediates every tools/call before it reaches the child process |
| OTel GenAI export | Events export as gen_ai.*-aligned span dicts (aileron export) for your existing collector |
| HTML incident reports | Single file, inline CSS, no external assets, verification badge (VERIFIED / TAMPERED at seq N) |
| Privacy by default | Tool arguments/results are recorded as digests only, unless you opt in with --capture-content |
@track decoratorfrom aileron import ChainLog, track, PolicyBlocked, bundled_rules_dir
from aileron.policy import load_rules
log = ChainLog("run.chain.jsonl") # capture_content=False by default
rules = load_rules(bundled_rules_dir()) # or load_rules("rules") after `aileron init`
@track(log=log, rules=rules)
def shell(cmd: str) -> str:
... # your tool implementation
shell("ls /tmp") # -> tool_call event, status=ok, args recorded as digest
shell("rm -rf /") # -> PolicyBlocked raised; blocked attempt is logged
Rules see the full arguments in memory at decision time; the journal still
stores digests only. Turn on capture_content=True only when you want raw
arguments persisted for forensics.
track_agent sessionfrom aileron import track_agent
with track_agent("research-agent", framework="langchain", log=log):
shell("ls /tmp") # inherits the session's agent identity and session_id
# agent_start / agent_end events bracket the run automatically
Wrap any MCP server. Every tools/call is logged and policy-checked before
the child process sees it:
$ aileron init # seeds a ./rules directory with starter rules
$ aileron proxy --log run.chain.jsonl --rules rules -- \
npx -y @modelcontextprotocol/server-filesystem /tmp
A blocked call returns a JSON-RPC error (-32000: blocked by aileron rule <id>) to the client; the child is never invoked.
Verified against real MCP servers, not just test doubles. Aileron has been
run in front of the official @modelcontextprotocol/server-filesystem
(secure-filesystem-server 0.2.0, 14 tools) and @modelcontextprotocol/server-memory
(0.6.3, 9 tools): the handshake completes, tools list normally, real calls work,
a blocked write never reaches the server, and the journal verifies. That check
ships as a test (tests/test_real_mcp_server.py, run with
AILERON_LIVE_MCP=1).
Mediation costs sub-millisecond median overhead per tools/call, verified
on commodity hardware - see Performance.
The proxy speaks both newline-delimited and Content-Length-framed
JSON-RPC. Content rules
(tool.arguments_contains, _regex) work in the default digest-only mode -
--capture-content changes what is persisted, not what is enforced. Calls
still in flight when the child dies are journaled with status=error, so a
crash never erases the attempt.
Aileron sits in front of MCP servers. It is also one. Point it at a directory of journals and an assistant can read the record for you:
$ aileron serve --root ./journals
Three tools, all read only: verify_journal (is this record intact),
query_events (what happened, filtered by tool, status, or time), and
explain_rule (what does aileron-130 catch).
There is no write, delete, or sign tool, and there should never be. The agent being recorded is the untrusted party, so giving it a way to edit the journal would hand the suspect the evidence locker.
Four things follow from that, and they are the reason this is more than a
wrapper around aileron verify:
--root and only .jsonl opens. Otherwise
verify_journal(path) is an arbitrary file read.IGNORE PREVIOUS INSTRUCTIONS... is evidence to report, not an
instruction to follow.capture_content governs what the journal
stores. It never widens what this server hands back, and errors never echo
file contents.# a policy rule (see the bundled rules/examples/destructive-shell.yml)
id: aileron-001
title: Block destructive shell commands
severity: high
match:
type: tool_call
tool.name: shell
tool.arguments_contains: ["rm -rf", "DROP TABLE", ":(){ :|:& };:"]
action: block
Dry-run rules against a recorded session: aileron rules test rules/ run.chain.jsonl
agent ──tool call──► [ SDK @track ] ──┐
[ MCP proxy ] ──┼─► policy decide (allow/alert/block)
│ │ block? ──► call never executes,
MCP client ──JSON-RPC──► proxy ───────┘ │ attempt still logged
▼
append to chain log (JSONL)
event 0 event 1 event N
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ seq: 0 │ │ seq: 1 │ │ seq: N │
│ prev: 0000… │─►│ prev: H(e0) │─► … ──►│ prev: H(eN-1)│
│ hash: H(e0) │ │ hash: H(e1) │ │ hash: H(eN) │──► Ed25519 checkpoint
└──────────────┘ └──────────────┘ └──────────────┘ signature over tip
H(e) = sha256(canonical_json(e \ hash))
aileron verify → recompute every hash + link (exit 2 on tamper)
aileron verify-checkpoint → re-verify chain tip against Ed25519 signature
Tampering with any event breaks the hash link at the first modified
sequence; verify reports first_bad_seq and exits non-zero. The journal
is local-only and self-contained - verification needs no network and no
trusted third party.
Aileron adds sub-millisecond median overhead per tools/call, verified on
commodity hardware. Every number below is reproducible with one command:
$ python scripts/benchmark.py
Method. scripts/benchmark.py drives an identical
stdio MCP child server two ways - directly, and through aileron proxy - and
subtracts. The delta is the proxy's true cost, so you never have to trust an
absolute figure. The absolute baseline is printed alongside it so the
subtraction can be checked. 2,000 sequential calls per configuration after 200
discarded warmup calls; rules loaded; digest-only journaling. Overhead covers
JSON-RPC parsing, policy evaluation, hash-chain append, re-serialization, and
the extra process hop.
tools/call (milliseconds)Linux x86_64 - GitHub Actions ubuntu-latest (2 shared vCPU), Python
3.12.13. Re-measured by CI on every push:
| tool arguments | direct (baseline) median | + proxy & rules median | added median | added p95 |
|---|---|---|---|---|
| 64 B | 0.051 | 0.315 | 0.264 | 0.280 |
| 4 KB | 0.064 | 0.370 | 0.306 | 0.353 |
| 32 KB | 0.171 | 0.800 | 0.629 | 0.668 |
macOS arm64 - Apple M2 Pro, Python 3.13.7, idle machine. Each row is the worst of three passes, so these are pessimistic rather than cherry-picked:
| tool arguments | direct (baseline) median | + proxy & rules median | added median | added p95 |
|---|---|---|---|---|
| 64 B | 0.0133 | 0.1003 | 0.0870 | 0.183 |
| 4 KB | 0.0290 | 0.1811 | 0.1521 | 0.250 |
| 32 KB | 0.1375 | 0.5227 | 0.3852 | 0.468 |
All values are milliseconds. Every row comes from a single run, so
added = (proxy & rules) − direct holds exactly and you can check the
subtraction. The tool reports mean / median / p95 / p99; these tables quote
median and p95.
Medians are stable across runs (64 B measured 0.087 / 0.085 / 0.087 ms over three passes); p95 is not - tail latency on a desktop OS swings with scheduling, and a single pass can look 40% better or worse than its neighbour. Treat the median as the number and the p95 as an order of magnitude. Linux is roughly 3× slower than the Mac because a shared-vCPU CI runner is the slower machine - those are the conservative figures, and the ones CI enforces.
Caveats, stated plainly. These are sequential stdio round-trips - one call in flight at a time, which is how an agent actually calls tools. This is not a concurrent-client benchmark; a many-client run is on the roadmap. Overhead grows with argument size because hashing, digesting, and re-serialization are all linear in payload. For context, a real MCP server call is typically 10–1000 ms, so mediation costs well under 1% of it. Measure on your own hardware before quoting a number.
CI enforces this: a job fails if median overhead regresses more than 2× against
scripts/benchmark_baseline.json, so
performance cannot decay silently.
aileron export emits gen_ai.operation.name /
gen_ai.tool.name / gen_ai.agent.name span attributes plus
aileron.event.hash, so Aileron sits beside your existing tracing
stack as the evidence layer, not instead of it.@track is a plain
decorator; track_agent accepts a free-form framework= label. No
framework dependency is required.capture_content=True / --capture-content. You get a verifiable record
of what happened without persisting secrets or PII by accident.
Policy rules and the anomaly detector still see the full call in memory
at decision time - capture only controls what is persisted, never what
is enforced.@track wraps the functions you
decorate; code paths you don't instrument are not recorded. For
enforcement that agent code cannot skip, use the MCP proxy - mediation
happens in a separate process on the tool-call path.rm -rf, id_rsa, exfil patterns); they will not
reliably detect novel malicious reasoning. Detection-of-effect
complements detection-of-intent tools (garak, PromptGuard); it does not
replace them.aileron-rules community rule repo - Sigma-for-agents: community
detection rules mapped to the OWASP Agentic Security Initiative's threat
taxonomy, CI-validated against recorded incident traces.Contributions are welcome - see CONTRIBUTING.md. Good
starting points: new detection rules under src/aileron/rules/examples/ and new
framework adapters under examples/. DCO sign-off, no CLA. Security
issues: see SECURITY.md.
Apache License 2.0 - see LICENSE.
FAQs
Flight recorder for AI agents: tamper-evident audit logging, policy enforcement, and incident reports
We found that aileron demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Socket uncovered 77 linked Firefox extensions, including 40 that steal wallet secrets or credentials and 37 deceptive sports-score shells.

Security News
NIST disclosed an unreleased AI tool called V-etalon and opened a broad inquiry into NVD modernization after years of automation plans produced no public enrichment system.

Security News
In his AI Council 2026 talk, Feross Aboukhadijeh covers recent package compromises, vulnerability discovery, and a more automated security model.