MIT Network Audit docs
How it works

Why you can trust it

A trust tool is only worth the trust you can place in it. You are right to ask the obvious follow-up question: the auditor watches my other modules — but who watches the auditor? If MIT Network Audit could quietly be obfuscated, store your email bodies, have its log rewritten, break your network when it misbehaves, or phone home on the side, then it would be just one more black box you have to take on faith — and that is exactly the situation it exists to end.

9 min read

A trust tool is only worth the trust you can place in it. You are right to ask the obvious follow-up question: the auditor watches my other modules — but who watches the auditor? If MIT Network Audit could quietly be obfuscated, store your email bodies, have its log rewritten, break your network when it misbehaves, or phone home on the side, then it would be just one more black box you have to take on faith — and that is exactly the situation it exists to end.

So this module is built on a small set of non-negotiable invariants: properties that are true by construction, not by promise. Each one is enforced in code and in the build pipeline, not left to good intentions. This page walks through all six, in plain terms: what the invariant is, and why it matters to you.

These are not settings you can weaken

Everything below is structural. None of these six properties is a checkbox an admin — or MIT — can flip off in passing. Where a thing is impossible, we say impossible, and we mean it is enforced by the build gate or by the data model, not by policy. The few honest exceptions (an optional, locked-down forensic mode) are called out plainly in Security & boundaries.


1. Open source, never obfuscated

The invariant. MIT ships its commercial modules — MailDesk, the license locker — obfuscated, so you cannot read the bytecode. This module is the one component shipped in the clear: open source, readable and runnable line by line. It is never obfuscated, and the build pipeline fails if any obfuscation artifact ever appears in a release.

Why it matters to you. This is the whole foundation. You cannot independently verify a claim if you cannot read the thing making it. Because this module is open, you — or your own security team — can read every line that captures, attributes, redacts, and records traffic, and confirm for yourself that it does what this documentation says. The obfuscated modules can be checked from the outside precisely because the thing doing the checking is fully in the open. The release gate makes "open source" a property of the shipped artifact, not just of the repository — so the code you run is the code you can read.

Open source is the feature

For most software, being open is a licensing choice. Here it is the entire mechanism. An obfuscated auditor would prove nothing — you would simply have swapped one black box for another. The clarity is the product.


2. No bodies — by structure, not by setting

The invariant. The private contents of your traffic — the email body, the document, the AI prompt, the API payload — are never stored. This is not a redaction option that could be turned off: the captured event (NetEvent) has no body field at all. There is nowhere to put a body. What is kept is metadata only: direction, channel, protocol, method, host, URL path, query keys, source and destination IP and port, status, request and response sizes, timings, masked headers (the names are kept, the values are masked), a salted HMAC fingerprint, and the attributed module, author and call site.

Why it matters to you. The single thing you most want to confirm is that your actual content is not being copied out and warehoused. With most logging tools you would have to trust a redaction setting to hold — and a setting can be misconfigured, or changed. Here, redaction is structural: even if someone wanted to log a body, the data structure that records every event has no slot to hold one. The salted fingerprint lets two identical payloads be recognised as identical for analysis, but it cannot be reversed back into the content. You get a complete, attributable record of who talked to whom, how much, and when — without your sensitive content ever being part of that record.


3. Append-only, hash-chained, and signed — tamper-evident

The invariant. The audit log (network.egress_log) is append-only: it rejects write and unlink — even when called as sudo — with the single exception of the retention vacuum. Every row is linked into a hash chain: each row's row_hash is a SHA-256 that folds in the previous row's hash (prev_hash) plus a database-unique serial (chain_seq). On top of that, a daily job (_sign_head) HMAC-signs the current head of the chain into Odoo's configuration so that even truncating the log — deleting recent rows — is detectable, because the signed head outlives the rows it covers. The Verify chain action recomputes the entire chain (using a constant-time comparison) and names the first tampered row, if any.

Why it matters to you. A log you can edit invisibly is no evidence at all. Because the rows are chained, you cannot change, reorder, or remove one without breaking every hash that follows it — and Verify chain will point straight at the break. Because the chain head is signed daily and kept separately, even quietly trimming the tail of the log is caught: the signed head remembers a position the deleted rows can no longer satisfy. The practical consequence is strong and deliberate: even MIT cannot rewrite this history undetectably. The signing key is a per-database secret generated on first use and never present in the source code, so the proof is anchored to your instance, not to ours.

The vacuum is the one writer — and it cannot erase your proof

The only path allowed to remove rows is the retention vacuum, governed by Audit retention (days) in the settings. By design it never deletes at or after the signed head, so the one mechanism that can prune the log can never prune away the evidence the signed head is vouching for. See Settings & forensic capture.


4. Fail-open — the auditor never breaks your network

The invariant. The auditor is wired to fail open. Any exception that happens while capturing, attributing, redacting, or recording a call is swallowed — it never propagates back into the network operation being observed. If some part of the auditor were to fail, the audited network call still completes exactly as it would have without the auditor present.

Why it matters to you. Security tooling that sits in the path of every connection can become the most dangerous thing on the server: if it can throw, it can take production down with it. That trade-off is unacceptable for a tool whose only job is to build trust. So the rule is absolute — the auditor must never be the reason a network call fails. In the worst case, the cost of an internal auditor fault is a missing log row, never a broken request. Your email keeps syncing, your integrations keep working, your customers never see an error that traces back to the watcher. Transparency is added; reliability is not subtracted.

Fail-open is honest about its trade-off

Failing open means the auditor would rather miss a record than break your traffic. We chose that direction on purpose, and we are upfront about it: this tool exists to observe and prove, not to enforce. If you need traffic blocked, that is a firewall's job, not this module's — see Security & boundaries.


5. Zero self-egress by design

The invariant. The module makes no outbound network calls of its own. It does not phone home, check in, or report anything back to MIT. And it holds itself to this rule the same way it holds your other modules to theirs: if the Trust Report ever sees a network call attributed to mit_network_audit itself, that is treated as an alarm, not a footnote.

Why it matters to you. It would be a bad joke if the tool you installed to prove your data isn't leaving to MIT were itself quietly talking to MIT. So it doesn't — and, crucially, it is subject to its own audit, so you don't have to take that on faith either. The Self-egress chip on the Trust Report is the live readout of this invariant; in a healthy install it reads 0. If it were ever anything else, the report escalates to alarm rather than letting it pass. The auditor is not exempt from the audit — and that self-policing is itself something you can read on screen, every time you open the report.

You can watch this invariant directly

The Self-egress N trust chip exists for exactly this reason. N is the count of calls ever attributed to the auditor module — and you want it to read 0. See Verdicts explained for what each verdict state means and what to do if the count is ever non-zero.


6. The interceptor core has no Odoo imports

The invariant. The trust-critical core — the interceptor/ package that actually captures events, masks headers, and applies the redaction policy — is pure Python with zero Odoo imports. The build pipeline enforces this: it greps the core for any import odoo and fails the gate if one appears. All the Odoo coupling lives in a separate, clearly fenced layer (glue/ and the model and view code) — never in the core.

Why it matters to you. This is what lets you trust the auditor without having to trust the whole stack. The part of the code that decides what is captured and what is masked is small, self-contained, and free of the large, complex Odoo framework — so it can be read, reasoned about, and even run as a standalone library, on its own terms. You do not have to audit the entire Odoo runtime to satisfy yourself that the core behaves as described; the surface you have to trust is deliberately tiny and deliberately isolated. A smaller trusted core is an easier trusted core to verify — which is the point of the whole module.


The six invariants at a glance

The invariant Why it matters to you
Open source, never obfuscated You can read the code that does the watching — and the build fails on any obfuscation artifact, so the artifact you run is the one you can read.
No bodies — structural Your email and document contents are never stored, because the event record has no field to hold them. Redaction can't be misconfigured away.
Append-only, hash-chained, signed head The log is tamper-evident end to end. Even MIT cannot rewrite or truncate history undetectably — Verify chain names the break.
Fail-open always The auditor can never break your network. The worst case is a missing log row, never a failed request.
Zero self-egress by design The module never phones home, and it audits itself — any self-egress is an alarm you can see on the Trust Report.
Interceptor core has no Odoo imports The trust-critical core is small, pure, and standalone — so you can trust the auditor without trusting the entire Odoo stack.

Where the honest limits live

These six invariants are what the module guarantees. Being a trust tool means being just as clear about what it does not do — it observes rather than blocks, it proves what it can see rather than claiming to be unbeatable, and there is one optional, off-by-default, officer-only forensic mode where bodies can be stored under audit. All of that is laid out plainly in Security & boundaries.