Security inspection and policy gateway
Duckbill™ treats inbound mail as untrusted. Rendering, fetching, and side effects go through application services in @inbox-agent/application before any provider adapter runs.
Source: MAIL-35, MAIL-34, MAIL-108, MAIL-107, MAIL-87, MAIL-86. Pipeline §§31–35, §§57–62, §§114–118; 01 AI §8 / §12; 03 NFR §3; 04 MVP §3.
Untrusted HTML
sanitizeUntrustedHtml is the only HTML render path. Script, iframe, form, object, meta-refresh, and event-handler markup are stripped. Remote images are not preserved, so tracking pixels do not auto-load. If the sanitizer throws or residual unsafe markup remains, the result is plain text (html: null). Raw provider HTML is never returned.
SSRF and attachments
inspectUrl / assertSafeFetchUrl deny localhost, RFC1918 and link-local ranges, IPv6 unique-local and loopback, cloud metadata hosts, and non-http(s) schemes. Redirect targets are inspected independently.
Stream 04 already stores attachment scan_state values unknown and held (migration 0014_attachment_hold_states.sql). Scanner or fetch failure holds the item. scanFailureDisposition records unknown / held and never clean. Quarantined or held items fail mayAutoArchive — ordinary automation does not archive them.
Policy gateway
evaluatePolicy returns ALLOW or DENY in this MVP (APPROVAL_REQUIRED is reserved) and never invokes an adapter (adapterInvoked: false). Actors are USER, RULE, AI, and SYSTEM.
- AI cannot authorize
send,delete,archive,label,markRead,setFlag, ormove. Those decisions areDENYwithPOLICY_DENIED. - User send/delete require
ENABLE_SEND/ENABLE_DELETE(still default off). The command service still refuses send/delete; flippingENABLE_SENDis not authorization. - User archive/label/markRead/setFlag/move is a safe write and may
ALLOW, then still requires aMailCommand(ADR 0025). - An approved, active deterministic rule may
ALLOWarchive/label. Unapproved send/delete are denied.
Denied calls use the POLICY_DENIED API envelope from @inbox-agent/api-contracts.
Deterministic rules
Conservative backend rules match sender, sender domain, subject substring, or List-Id. Evaluation emits COMMAND_REQUEST records that still pass the policy gateway. Matching a rule never calls a provider adapter.
AGENT_SUGGESTED rules start as DRAFT and cannot be created ACTIVE. Activation requires explicit approval. Security and user rules outrank system defaults and skip AI. Simple list / create / pause is the MVP surface — there is no visual rules builder.
