> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Inbound media threat scan and quarantine model

> How Orbit scans inbound MMS and email attachment BYTES for malware before they reach an agent or the message store — the clean/suspicious/malicious bands, the allow/review/quarantine recommendations, and what a quarantined attachment means for your inbox.

# Inbound media threat scan and quarantine model

Every inbound MMS attachment and every inbound email attachment passes through
a byte-level threat scan before it is forwarded to an agent inbox, a vision
agent turn, or archived into the message store. This page explains the scan
model: what it inspects, how a verdict is banded, what each channel does with
a blocked attachment, and how to read the quarantine marker on a message.

This is the inbound counterpart of outbound composition checks. URL
reputation, covered in
[`POST /messages/url-scan`](/api-reference/endpoints/messaging), grades the
destination URLs in a body you send; the threat scan below inspects the media
BYTES a sender uploads to you — a different trust boundary.

## Where inbound media crosses the trust boundary

Two inbound paths hand a sender-controlled payload to something a customer
trusts:

* **MO SMS/MMS attachments** — an MMS arrives carrying media URLs. Orbit
  downloads the bytes and, for image attachments, forwards them to the
  [vision agent turn](/concepts/ai-agent-architecture) so the agent can reason
  over what the picture shows. That download-then-forward step is where a
  malicious payload would otherwise ride straight into the agent inbox.
* **Inbound email attachments** — when an inbound email lands, its
  attachments are archived to the tenant media bucket and surfaced in the
  message detail view (see the
  [inbound email parse guide](/guides/inbound-email-parse)). Archiving means
  re-hosting sender-controlled bytes on a durable URL, so a poisoned part
  would otherwise become a shareable link inside your inbox.

Both paths scan the decoded bytes **before** that forward/archive step, at the
one place the payload crosses from "bytes a stranger sent" to "content an
agent or a teammate opens." Message body text that accompanies the media still
processes — only the attachment itself is gated.

## The scan model

The engine is a deterministic, offline heuristic scorer. It needs no external
credential and no third-party feed to run, and its additive weights and band
thresholds are pinned by tests so the verdict for a given payload never drifts.
It inspects three signal families:

**File signatures (magic bytes).** The first bytes of the payload are matched
against known-dangerous families, up to the first 512 KB of the attachment:

* The EICAR standard anti-virus test signature — every AV engine flags it; an
  attachment carrying it is quarantined identically to real malware.
* Native executables: Windows PE/MZ headers, Linux ELF headers, macOS Mach-O
  and Java class headers.
* Windows `.lnk` shell-link launchers, and script `#!` shebangs.
* OLE2 compound documents (legacy macro-capable Office) and OOXML packages
  carrying an embedded `vbaProject.bin` (macro payload).
* PDFs with active content: `/JavaScript`, `/Launch`, `/OpenAction`,
  `/EmbeddedFile`.
* Markup payloads (SVG, HTML, XHTML/XML) embedding `<script>` blocks, inline
  event handlers, `javascript:` URIs, or PHP code.

**Declared metadata.** The declared Content-Type and the filename extension
are scored independently: a declared executable/installer/script type
(`application/x-msdownload`, `application/x-sh`, Java archive, MSI, PHP, …)
or an extension like `.exe`, `.scr`, `.bat`, `.ps1`, `.jar`, `.apk` is a
strong signal on its own. Macro-enabled Office extensions (`.docm`, `.xlsm`,
`.pptm`, …) score lower but still flag. Archive containers (`.zip`, `.dmg`, …)
are a mild signal — common in smuggling chains.

**Spoofing.** The cross-signal checks catch the classic delivery tricks:

* The declared type says `image/jpeg` but the magic bytes are an executable,
  archive, or document (`magic-type-mismatch`).
* The declared type is binary media but the bytes are markup
  (`html-disguised-as-media`).
* Deceptive double extensions — `invoice.pdf.exe`, `photo.jpg.scr` — where a
  safe-looking decoy extension sits in front of the real one.

**External verdicts.** When the platform operator wires a real AV engine
(ClamAV, VirusTotal, or a similar feed), its verdict is injected as the
dominant signal — a `malicious` external verdict maxes the score. The
heuristic layer remains the always-on baseline beneath it, exactly as the
URL-reputation model treats external verdicts.

## Bands and recommendations

Each finding adds points; the composite score caps at 100 and maps to three
bands:

| Band         | Score  | Recommendation | Default handling                          |
| ------------ | ------ | -------------- | ----------------------------------------- |
| `clean`      | 0–24   | `allow`        | Forwarded / archived normally             |
| `suspicious` | 25–59  | `review`       | Forwarded with a warn-log advisory        |
| `malicious`  | 60–100 | `quarantine`   | Dropped before it reaches the agent/store |

The verdict carries a transparent finding list — for every signal, a
machine-readable code, a severity, the points it contributed, and a human
explanation — so you (or we) can see exactly why a verdict landed without
reading the payload.

Three outcomes follow from the bands:

1. **Quarantine (malicious).** The attachment is dropped. On the vision-agent
   path the agent turn still proceeds with the text-only body; on the email
   path the part is never uploaded to the media bucket. Quarantined bytes are
   never re-hosted, and the block is recorded with finding codes only — no
   payload and no sender content — so the audit trail stays PII-safe.
2. **Suspicious.** The attachment is still delivered, but a warn log is
   emitted with the band, score, and finding codes so a security reviewer can
   pull the record. This is an advisory, not a block.
3. **Clean.** Delivered exactly as before the model existed.

## Channel behavior split

The same engine gates both inbound paths; the divergence is in what "dropped"
looks like per channel.

**MMS / vision-agent path.** The scan runs on the downloaded attachment bytes
inside the inbound webhook pipeline, after
[inbound message routing](/concepts/inbound-message-routing) has resolved the
tenant and the AI enrichment chain selected the target. A quarantine verdict
only affects the media object: the message, its metadata, and a text-only
agent turn all proceed — the payload is never forwarded to the
[vision agent](/concepts/ai-agent-architecture).

**Inbound email path.** Each attachment part of an inbound email is scanned
individually in the background archiver. A part with action `quarantine` is
dropped; a part with action `allow` (clean or advisory-suspicious) is archived
to the tenant bucket with the standard 7-day signed URL and surfaced in the
message detail view. Dropped parts are recorded on the message's
`metadata.email_attachments_quarantined` list — filename, declared
content-type, size, score, band, and finding codes — so the block is visible
on the audit trail without re-hosting anything dangerous.

## Observability

* The `inbound_media_threat_quarantined_total` counter increments per dropped
  MMS attachment, labeled by channel, with an `email_inbound_attachment_skipped_total`
  counter for the email path (`reason: threat_quarantined`).
* Every quarantine and every suspicious hit emits a warn log carrying the
  band, composite score, and finding codes.

There is deliberately **no tenant-facing config knob**: the gate is a platform
baseline control, like the generic upload allow-list, not a per-org toggle.
Organizations that want stricter verdicts can have the operator wire an
external AV verdict feed into the scan — that feed then dominates the
heuristic baseline, without any change to the channel behavior above.

## The customer contract

**A quarantined attachment is not a lost message.** The envelope, sender,
body text, and any remaining attachments all route and resolve normally —
only the blocked part is absent. When an inbox shows a message that references
a media object that never renders, check for the quarantine marker before
reprocessing the message.

**Reading the marker.** On inbound email messages, open the message's
`metadata.email_attachments_quarantined` list. Each entry names the dropped
part (filename, declared type, size), the score and band, and the machine
codes of the findings that tripped it — enough to decide whether to ask the
sender to resend in a safer format. `metadata.email_attachments` carries only
the parts that survived.

**How this differs from the other content gates.** Threat scanning is about
the payload bytes, not the content's policy posture. RCS and WhatsApp
content-policy moderation (which judges what the content *says*, e.g.
prohibited categories) runs on a different surface entirely, and URL
reputation on composed outbound bodies runs through the composes-side
[`POST /messages/url-scan`](/api-reference/endpoints/messaging) endpoint.
None of these layers substitute for the others.

## Cross-references

* [Inbound message routing](/concepts/inbound-message-routing) — the
  tenant-level distribution rules upstream of this gate.
* [Inbound message resolution](/concepts/inbound-message-resolution) — the
  tenant-ownership step that runs before routing.
* [AI agent architecture](/concepts/ai-agent-architecture) — the vision-agent
  turn the MMS gate protects.
* [Inbound email parse guide](/guides/inbound-email-parse) — the archival
  pipeline the email gate sits in.
* [`POST /messages/url-scan`](/api-reference/endpoints/messaging) — the
  outbound URL-reputation counterpart.
