MIT Network Audit docs
Security

Security & boundaries

This module exists to be trusted, so it owes you the most honest page in the whole documentation set: not only what it can prove, but exactly where its proof stops. A transparency tool that oversold itself would defeat its own purpose. So this page does two things plainly. First, it tells you who can see what — because a log that proves where your data goes is only worth anything if the wrong people cannot quietly read it or rewrite it. Second, it draws a frank line under wha

7 min read

This module exists to be trusted, so it owes you the most honest page in the whole documentation set: not only what it can prove, but exactly where its proof stops. A transparency tool that oversold itself would defeat its own purpose. So this page does two things plainly. First, it tells you who can see what — because a log that proves where your data goes is only worth anything if the wrong people cannot quietly read it or rewrite it. Second, it draws a frank line under what this module proves and what it does not — what its deep capture genuinely demonstrates, and the specific case it makes no claim about.

If you have not yet read how the capture works, How it works covers the interception layers; this page assumes you know that every inbound and outbound network call is recorded as metadata in an append-only, hash-chained journal.


Who can see what

There are two roles, and they are deliberately narrow. The point of the separation is that reading the shape of your traffic and reading the contents of a captured body are two very different privileges, and the module treats them that way.

Group What it can read What it cannot do
Network egress log: audit group The full audit — every captured event's metadata: direction, channel, destination host/IP/port, method, status, sizes, timing, masked headers, and the attribution (which addon made the call). This is the group that reads the Trust Report and the Audit Log. Read captured bodies. The audit group sees the shape of traffic, never any payload.
Network Forensic Officer Everything the audit group can read, plus the contents of captured request/response bodies — the only role that can. (This is the privileged role. Body capture itself is off by default and every body read is logged — see below.)

Two privileges, deliberately split

Seeing that a call happened, where it went, and how big it was is one thing — that is the everyday audit, and it never exposes a payload. Seeing the actual content of a captured body is a far stronger privilege, reserved for the Network Forensic Officer alone. Keeping these two apart is the whole reason the normal audit can be read widely inside your organisation without anyone worrying that "reading the log" means "reading the mail".

Bodies are off by default — and reading one is itself logged

By design, no body is stored at all. The captured event has no body field; the journal keeps only metadata, a size, masked headers, and a salted fingerprint. That is structural — there is simply nowhere for a payload to live in the ordinary log.

There is exactly one deliberately walled-off exception: forensic body capture, meant for a legal case where you genuinely need to retain request/response bodies as evidence. It is built to be the opposite of a quiet back door:

  • Off by default. Nothing captures bodies unless a Forensic Officer turns it on.
  • Officer-only. Storing bodies and reading them are gated to the Network Forensic Officer role; the records live in the Captured Bodies view (network.egress_body), separate from the normal Audit Log.
  • Every read is recorded. Each time a captured body is read, that read is itself written to the append-only journal. There is no way for even the officer to look at a stored body without leaving an immutable trace that they did so.

Forensic body capture exists — and that is the honest thing to say

It would be easy to leave this feature out of the documentation and let "bodies are never stored" stand as an unqualified claim. We will not. The feature is real, it does store bodies when an officer enables it, and you should know it exists, that it ships off, that only the Network Forensic Officer can use it, and that every body read is logged. For the everyday operator who never enables it, the practical truth remains: the audit holds metadata only.

Append-only — enforced in code and in the database

The log being readable is only half of the trust story; it also has to be impossible to rewrite. The audit log model (network.egress_log) rejects write and unlink — even when called with sudo, the Odoo escalation that normally overrides access rules. The single exception is the retention vacuum, the scheduled cleanup that removes rows older than your configured window, and which never deletes at or after the signed head.

Append-only is a database guarantee too, where deployed

This is not only an application rule that a determined operator could patch around. Where the module is deployed, append-only is also enforced at the PostgreSQL level — the underlying table is protected against UPDATE and DELETE. "No one can rewrite history" is engineered as a property of the system, not asserted as a promise. The hash chain on top makes any tampering attempt detectable, and verifying & exporting the chain lets you confirm it yourself.

For where these groups are assigned and how forensic body capture is turned on (and audited), see Settings & forensic capture.


What this proves — and what it does not

This is the part a less honest tool would skip. The module is powerful, but it is a transparency and detection tool, and it is worth being exact about the difference between "we did not observe X" and "X is impossible".

What it proves

It proves what it can observe, and it observes a great deal. The capture is deep — it reaches all the way down to the socket layer. Outbound traffic is wrapped at the common library level (requests, urllib/http.client, httpx, imap/smtp/pop3, and the raw TLS socket), and underneath all of those sits a socket-level backstop (socket.connect), so even a library the module does not specifically know about still leaves a destination row. Inbound HTTP is captured by a WSGI middleware in front of your Odoo. Every captured call is attributed back to the Odoo module that made it, by walking the live call stack to its ir.module.module.

Put together, that lets you independently confirm the one claim the whole product is built around: that the only MIT-bound traffic is small license-validation metadata, and that your other modules — MailDesk, your integrations — talk only to your own providers (your Gmail or IMAP server, your own OpenAI/LLM key, your Microsoft 365), not to MIT. And because the record is append-only and hash-chained, you can prove that finding to a third party, not merely assert it.

What it does not

Three boundaries, stated plainly.

  • It is not a formal sandbox. Deep as the capture is, it is not a mathematical guarantee against an adversary who manages to bypass a layer it does not hook — for example, code that reaches the network by a path beneath even the socket interception. An all-clear verdict is strong, honest evidence; it is not a proof that no such path could exist anywhere. We would rather say that out loud than oversell it.

  • It does not block traffic. It is not a firewall. The module observes, attributes, and proves — it does not stop a call from happening. A verdict tells you what happened and lets you prove it; acting on a bad one (investigating, escalating, changing a configuration) remains a human decision. If you need to prevent egress, that is a job for your network controls, not for this module.

  • It stores metadata, not payloads. This is a feature, but it is also a boundary: the audit can tell you that a call went to a destination and how many bytes moved, but — outside the off-by-default forensic body capture above — it cannot tell you the contents of that call. Size, timing, destination, and attribution are usually enough to recognise a routine license ping versus an unexplained upload, but the auditor is honest about not reading the payload.

How the boundaries actually help you in practice

These limits are exactly why the attribution and byte-size columns matter so much. The module cannot promise "nothing could ever leak by any path", but it can show you, line by line and provably, which module reached which destination and how much moved — which is precisely the evidence you need to spot something that does not belong. Read a verdict as that kind of evidence, not as an absolute seal. The verdicts page walks through how to act on each one.


A note on the auditor itself

The strongest expression of "what this module does not do" is what it does to itself. mit_network_audit makes no outbound network calls of its own — zero self-egress is a design rule. The Trust Report carries a Self-egress chip that should always read 0, and the report raises an alarm the moment it ever sees a call attributed to the auditor module. The one component shipped in the clear, never obfuscated, is also the one component built never to phone home — and engineered so that if it ever did, you would see it immediately. That is what makes the rest of the page worth trusting.