@blamejs/exceptd-skills 0.16.10 → 0.16.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,700 @@
1
+ {
2
+ "_meta": {
3
+ "id": "mail-server-hardening",
4
+ "version": "1.0.0",
5
+ "last_threat_review": "2026-06-02",
6
+ "threat_currency_score": 93,
7
+ "changelog": [
8
+ {
9
+ "version": "1.0.0",
10
+ "date": "2026-06-02",
11
+ "summary": "Initial seven-phase inbound mail-server protocol-hardening playbook. Covers the server-side protocol trust failures that sender-authentication (SPF/DKIM/DMARC) does not address: SMTP smuggling via non-standard end-of-data, STARTTLS receive-buffer command/response injection, IMAP/POP3 bare-CR-LF and ManageSieve PUTSCRIPT injection, uncapped Sieve redirect mail-routing exfiltration, unauthenticated open relay, mailbox-DAV path traversal + XXE, cleartext AUTH before STARTTLS, and missing auth rate-limiting / greylisting. Distinct from the email-security-anti-phishing skill (which covers sender authentication, not inbound protocol hardening). Maps to the SMTP-smuggling (CVE-2023-51764/51765/51766) and STARTTLS-injection (CVE-2021-38371/33515) catalog entries. Closes the GRC loop against NIST 800-53 SI-2, ISO 27001 A.8.8, NIS2 Art.21 network-security, and PCI-DSS 4.0 6.3.3."
12
+ }
13
+ ],
14
+ "owner": "@blamejs/platform-security",
15
+ "air_gap_mode": false,
16
+ "scope": "service",
17
+ "preconditions": [
18
+ {
19
+ "id": "mail-server-source-or-config-read",
20
+ "description": "Agent must read the operator's mail-server source and/or runtime configuration to inspect SMTP/IMAP/POP3/ManageSieve protocol handling, STARTTLS, relay authorization, Sieve, and mailbox-DAV. A host with neither marks the playbook visibility_gap=no_mail_server_inventory.",
21
+ "check": "agent_has_filesystem_read == true OR agent_has_mail_config == true",
22
+ "on_fail": "halt"
23
+ }
24
+ ],
25
+ "mutex": [],
26
+ "feeds_into": [
27
+ {
28
+ "playbook_id": "secrets",
29
+ "condition": "finding.includes_cleartext_credential_exposure == true"
30
+ },
31
+ {
32
+ "playbook_id": "framework",
33
+ "condition": "analyze.compliance_theater_check.verdict == 'theater'"
34
+ }
35
+ ]
36
+ },
37
+ "domain": {
38
+ "name": "Inbound mail-server protocol hardening",
39
+ "attack_class": "email-phishing",
40
+ "atlas_refs": [],
41
+ "attack_refs": [
42
+ "T1190",
43
+ "T1071.003",
44
+ "T1557",
45
+ "T1040",
46
+ "T1110",
47
+ "T1114"
48
+ ],
49
+ "cve_refs": [
50
+ "CVE-2023-51764",
51
+ "CVE-2023-51766",
52
+ "CVE-2021-38371",
53
+ "CVE-2021-33515"
54
+ ],
55
+ "cwe_refs": [
56
+ "CWE-77",
57
+ "CWE-93",
58
+ "CWE-22",
59
+ "CWE-611",
60
+ "CWE-863",
61
+ "CWE-400"
62
+ ],
63
+ "frameworks_in_scope": [
64
+ "nist-800-53",
65
+ "iso-27001-2022",
66
+ "nis2",
67
+ "pci-dss-4",
68
+ "soc2"
69
+ ]
70
+ },
71
+ "phases": {
72
+ "govern": {
73
+ "jurisdiction_obligations": [
74
+ {
75
+ "jurisdiction": "EU",
76
+ "regulation": "NIS2 Art.23",
77
+ "obligation": "notify_regulator",
78
+ "window_hours": 24,
79
+ "clock_starts": "detect_confirmed",
80
+ "evidence_required": [
81
+ "mail_listener_inventory",
82
+ "open_relay_or_spoofing_evidence"
83
+ ]
84
+ },
85
+ {
86
+ "jurisdiction": "EU",
87
+ "regulation": "GDPR Art.33",
88
+ "obligation": "notify_regulator",
89
+ "window_hours": 72,
90
+ "clock_starts": "detect_confirmed",
91
+ "evidence_required": [
92
+ "mailbox_data_exposure_estimate",
93
+ "sieve_redirect_exfil_evidence"
94
+ ]
95
+ }
96
+ ],
97
+ "theater_fingerprints": [
98
+ {
99
+ "pattern_id": "spf-dkim-dmarc-equals-secure-mail",
100
+ "claim": "We have SPF, DKIM, and DMARC, so our mail server is secure.",
101
+ "fast_detection_test": "Those are SENDER-authentication controls. Ask whether the inbound listener rejects non-standard end-of-data (SMTP smuggling) and drains the STARTTLS buffer — sender-auth is bypassed at the protocol layer."
102
+ },
103
+ {
104
+ "pattern_id": "tls-enabled-equals-no-cleartext",
105
+ "claim": "STARTTLS is enabled, so credentials are protected.",
106
+ "fast_detection_test": "Opportunistic STARTTLS still allows AUTH before the handshake unless explicitly gated. Confirm AUTH is refused until TLS is active and the pre-handshake buffer is drained."
107
+ },
108
+ {
109
+ "pattern_id": "not-an-open-relay-because-config-says-so",
110
+ "claim": "Relay is restricted in our config.",
111
+ "fast_detection_test": "Test it: from an unauthenticated session, RCPT TO an external domain. A config flag is not evidence the listener enforces it."
112
+ }
113
+ ],
114
+ "framework_context": {
115
+ "gap_summary": "Org mail controls center on sender authentication (SPF/DKIM/DMARC) and transport TLS. None prescribe the server-side protocol hardening — strict end-of-data, STARTTLS buffer drain, relay authorization, command-injection refusal — that SMTP smuggling, STARTTLS injection, and open-relay abuse exploit.",
116
+ "lag_score": 70,
117
+ "per_framework_gaps": [
118
+ {
119
+ "framework": "nist-800-53",
120
+ "control_id": "SI-2",
121
+ "designed_for": "flaw remediation via patch cadence",
122
+ "insufficient_because": "mail-protocol hardening is configuration posture (end-of-data handling, buffer drain, relay rules) the patch process does not surface."
123
+ },
124
+ {
125
+ "framework": "nis2",
126
+ "control_id": "Art.21(2)",
127
+ "designed_for": "network security of essential services",
128
+ "insufficient_because": "assumes SPF/DKIM/DMARC + TLS suffice; SMTP smuggling and STARTTLS injection defeat them at the protocol layer."
129
+ }
130
+ ]
131
+ },
132
+ "skill_preload": [
133
+ "mail-server-hardening",
134
+ "email-security-anti-phishing",
135
+ "webapp-security",
136
+ "framework-gap-analysis",
137
+ "compliance-theater",
138
+ "policy-exception-gen"
139
+ ]
140
+ },
141
+ "direct": {
142
+ "threat_context": "A mail server's inbound protocol surface is a trust boundary that sender-authentication does not protect. SMTP smuggling (non-standard end-of-data) delivers spoofed mail past SPF/DKIM/DMARC; STARTTLS injection executes attacker plaintext after the handshake; an open relay lends the operator's reputation to spammers; uncapped Sieve redirect silently exfiltrates mail; mailbox-DAV traversal/XXE reads the store. These are configuration and parser-hardening gaps, not CVEs to patch.",
143
+ "rwep_threshold": {
144
+ "escalate": 55,
145
+ "monitor": 35,
146
+ "close": 20
147
+ },
148
+ "framework_lag_declaration": "SPF/DKIM/DMARC + TLS audits are NON-EVIDENCE for inbound protocol hardening; they cover sender authentication and transport encryption, not end-of-data handling, STARTTLS buffer drain, relay authorization, or command-injection refusal.",
149
+ "skill_chain": [
150
+ {
151
+ "skill": "mail-server-hardening",
152
+ "purpose": "enumerate the inbound protocol-hardening checks per RFC 5321/9051/5804/5228"
153
+ },
154
+ {
155
+ "skill": "email-security-anti-phishing",
156
+ "purpose": "confirm the sender-auth layer that smuggling bypasses, for context"
157
+ },
158
+ {
159
+ "skill": "compliance-theater",
160
+ "purpose": "separate SPF/DKIM/DMARC/TLS claims from enforced protocol hardening"
161
+ },
162
+ {
163
+ "skill": "framework-gap-analysis",
164
+ "purpose": "map findings to the SI-2 / Art.21 gaps the controls do not cover"
165
+ }
166
+ ],
167
+ "token_budget": {
168
+ "estimated_total": 13000,
169
+ "breakdown": {
170
+ "govern": 1200,
171
+ "direct": 800,
172
+ "look": 4500,
173
+ "detect": 4000,
174
+ "analyze": 1800,
175
+ "validate": 500,
176
+ "close": 200
177
+ }
178
+ }
179
+ },
180
+ "look": {
181
+ "artifacts": [
182
+ {
183
+ "id": "mail-listener-inventory",
184
+ "type": "config_file",
185
+ "source": "Enumerate listening mail ports + their handlers: grep for mail-server-{mx,submission,imap,jmap,pop3,managesieve,tls}.js and the bound ports (25/465/587/143/993/110/995/4190) across source and config.",
186
+ "description": "Which mail protocols the operator terminates and on which ports (implicit-TLS vs opportunistic-STARTTLS).",
187
+ "required": true,
188
+ "air_gap_alternative": "If only source is available, enumerate the listener modules wired in; mark runtime port-binding as inventory_gap."
189
+ },
190
+ {
191
+ "id": "smtp-command-guard",
192
+ "type": "config_file",
193
+ "source": "grep for guard-smtp-command / end-of-data / <LF>.<LF> / smtpd_forbid / relay / RCPT handling across the SMTP receive path.",
194
+ "description": "How the SMTP listener handles end-of-data termination and unauthenticated relay.",
195
+ "required": true,
196
+ "air_gap_alternative": "Inspect the SMTP receive-path source for the end-of-data + relay-authorization checks."
197
+ },
198
+ {
199
+ "id": "imap-pop3-managesieve-guards",
200
+ "type": "config_file",
201
+ "source": "grep for guard-imap-command / guard-pop3-command / guard-managesieve-command / bare-CR / literal / PUTSCRIPT across the IMAP/POP3/ManageSieve parsers.",
202
+ "description": "How the mailbox-protocol parsers handle bare-CR/LF, literal injection, and PUTSCRIPT bounds.",
203
+ "required": true,
204
+ "air_gap_alternative": "Inspect the command-parser source for CRLF enforcement + literal-length validation."
205
+ },
206
+ {
207
+ "id": "starttls-and-auth-config",
208
+ "type": "config_file",
209
+ "source": "grep for STARTTLS / drain / buffer / AUTHENTICATE / require-tls / cleartext across the listeners.",
210
+ "description": "Whether STARTTLS drains the pre-handshake buffer and whether AUTH is gated on an active TLS session.",
211
+ "required": true,
212
+ "air_gap_alternative": "Inspect the STARTTLS upgrade handler for a receive-buffer clear and the AUTH gate."
213
+ },
214
+ {
215
+ "id": "sieve-and-dav-config",
216
+ "type": "config_file",
217
+ "source": "grep for safe-sieve / mail-sieve / redirect / mail-dav / PROPFIND / xml across the Sieve engine and CalDAV/CardDAV endpoint.",
218
+ "description": "Whether Sieve redirect is capped and whether the mailbox-DAV endpoint refuses traversal and disables XXE.",
219
+ "required": false,
220
+ "air_gap_alternative": "Inspect the Sieve engine for a redirect cap and the DAV XML parser for entity-expansion settings."
221
+ },
222
+ {
223
+ "id": "mail-abuse-controls",
224
+ "type": "config_file",
225
+ "source": "grep for mail-server-rate-limit / greylist / mail-rbl / lockout across the listeners.",
226
+ "description": "Whether rate limiting, greylisting, and RBL checks are active on the auth and inbound surfaces.",
227
+ "required": false,
228
+ "air_gap_alternative": "Inspect the listener config for a rate-limit / greylist / RBL policy."
229
+ }
230
+ ],
231
+ "collection_scope": {
232
+ "time_window": "current mail-server configuration + source state (point-in-time posture audit)",
233
+ "asset_scope": "every host terminating an inbound mail protocol (SMTP MX/submission, IMAP, JMAP, POP3, ManageSieve, mailbox-DAV)"
234
+ },
235
+ "environment_assumptions": [
236
+ {
237
+ "assumption": "The operator runs an inbound mail server (terminates SMTP/IMAP/POP3/ManageSieve), not only an outbound client.",
238
+ "if_false": "If the operator only SENDS mail via a third-party API, the inbound protocol indicators do not apply; pivot to sender-auth posture (email-security-anti-phishing) only."
239
+ },
240
+ {
241
+ "assumption": "Mail-server source or runtime config is readable.",
242
+ "if_false": "Mark visibility_gap=no_mail_server_inventory and report only what the receive-path source reveals."
243
+ }
244
+ ],
245
+ "fallback_if_unavailable": [
246
+ {
247
+ "artifact_id": "sieve-and-dav-config",
248
+ "fallback_action": "If no Sieve engine or mailbox-DAV endpoint is present, skip the redirect-exfil and DAV-traversal indicators.",
249
+ "confidence_impact": "none"
250
+ },
251
+ {
252
+ "artifact_id": "mail-abuse-controls",
253
+ "fallback_action": "If rate-limiting is enforced by an upstream gateway, inspect that policy instead.",
254
+ "confidence_impact": "low"
255
+ }
256
+ ]
257
+ },
258
+ "detect": {
259
+ "indicators": [
260
+ {
261
+ "id": "smtp-smuggling-end-of-data-accepted",
262
+ "type": "config_value",
263
+ "value": "The inbound SMTP listener accepts a non-standard end-of-data sequence (<LF>.<LF> or <LF>.<CR><LF>) as end-of-message instead of requiring the RFC 5321 <CR><LF>.<CR><LF>.",
264
+ "description": "A server that interprets non-standard end-of-data lets an attacker smuggle a second message that inherits the outer connection's SPF/DKIM/DMARC pass, delivering a spoofed sender (the CVE-2023-51764/51765/51766 class).",
265
+ "confidence": "high",
266
+ "deterministic": false,
267
+ "attack_ref": "T1071.003",
268
+ "false_positive_checks_required": [
269
+ "Send a DATA probe terminated with <LF>.<LF> and confirm the server treats it as end-of-message and accepts a smuggled follow-on envelope — a server that rejects the non-standard terminator is safe; a comment or doc that merely mentions the sequence is not a hit.",
270
+ "Confirm the listener is the INBOUND (receiving) path; an outbound relay's own end-of-data handling is not the smuggling-receiver finding."
271
+ ]
272
+ },
273
+ {
274
+ "id": "starttls-receive-buffer-not-drained",
275
+ "type": "config_value",
276
+ "value": "The SMTP/IMAP/POP3/ManageSieve listener does not discard bytes buffered before the STARTTLS handshake, so plaintext commands pipelined before STARTTLS are executed after the TLS upgrade.",
277
+ "description": "An on-path attacker injects commands/responses that cross the STARTTLS boundary (the CVE-2021-38371 / CVE-2021-33515 class) — transport encryption is genuine but the pre-handshake bytes are trusted.",
278
+ "confidence": "high",
279
+ "deterministic": false,
280
+ "attack_ref": "T1557",
281
+ "false_positive_checks_required": [
282
+ "Pipeline a plaintext command immediately before STARTTLS and confirm it is processed after the handshake — a listener that clears the receive buffer at the STARTTLS upgrade is safe.",
283
+ "Implicit-TLS ports (465/993/995) do not have a STARTTLS step and are not in scope for this indicator; only opportunistic-STARTTLS ports (25/587/143/110/4190)."
284
+ ]
285
+ },
286
+ {
287
+ "id": "imap-command-literal-injection",
288
+ "type": "config_value",
289
+ "value": "The IMAP/JMAP command parser accepts bare CR or bare LF, or a mid-line non-synchronizing literal {n} that injects a second command, instead of enforcing the RFC 9051 grammar.",
290
+ "description": "Bare-CR/LF and mid-line literal injection let an attacker smuggle a second IMAP command past the front-end, enabling command injection against the mailbox service.",
291
+ "confidence": "medium",
292
+ "deterministic": false,
293
+ "attack_ref": "T1190",
294
+ "false_positive_checks_required": [
295
+ "Confirm the parser refuses bare-CR / bare-LF and validates non-synchronizing literal lengths against the declared {n} — a parser that already rejects these (RFC 9051 §2.2.2) is safe.",
296
+ "A documented test fixture containing an injection string is not a hit; the finding is the live parser accepting it."
297
+ ]
298
+ },
299
+ {
300
+ "id": "managesieve-putscript-unbounded",
301
+ "type": "config_value",
302
+ "value": "The ManageSieve (RFC 5804) listener accepts PUTSCRIPT with an unbounded literal byte count, or accepts a script name containing slash/backslash/NUL, or permits AUTHENTICATE PLAIN/LOGIN over cleartext before STARTTLS.",
303
+ "description": "An unbounded PUTSCRIPT is a resource-exhaustion and storage-backend path-collision vector; cleartext AUTHENTICATE leaks credentials (the listener trusts a name/size it should bound).",
304
+ "confidence": "medium",
305
+ "deterministic": false,
306
+ "attack_ref": "T1190",
307
+ "false_positive_checks_required": [
308
+ "Confirm PUTSCRIPT caps the literal byte size, rejects script names with slash/backslash/NUL, and refuses AUTHENTICATE over cleartext (RFC 5804 §1.1 + RFC 4954 §4) — a listener enforcing all three is safe.",
309
+ "A managed/hosted ManageSieve fronted by a proxy that enforces these is not the finding; inspect the listener that terminates the protocol."
310
+ ]
311
+ },
312
+ {
313
+ "id": "sieve-redirect-uncapped",
314
+ "type": "config_value",
315
+ "value": "Sieve script execution (RFC 5228) permits the `redirect` action with no per-script cap on redirect count or destination allowlist.",
316
+ "description": "An attacker who can store a Sieve script (or exploit a stored-script flaw) uses uncapped `redirect` as a mail-routing exfiltration primitive, silently forwarding a victim's mail to an external address.",
317
+ "confidence": "medium",
318
+ "deterministic": false,
319
+ "attack_ref": "T1114",
320
+ "false_positive_checks_required": [
321
+ "Confirm Sieve execution bounds redirect count per script and/or enforces a redirect-destination policy — an engine with a gas counter + redirect cap is safe.",
322
+ "A Sieve engine that does not implement `redirect` at all, or restricts it to internal addresses only, is not the finding."
323
+ ]
324
+ },
325
+ {
326
+ "id": "inbound-open-relay",
327
+ "type": "config_value",
328
+ "value": "The SMTP listener accepts RCPT TO an external (non-local) domain from an unauthenticated peer — an open relay.",
329
+ "description": "An open relay lets any sender route mail through the operator's infrastructure, abusing its reputation for spam/phishing delivery and bypassing the recipient's sender controls.",
330
+ "confidence": "high",
331
+ "deterministic": false,
332
+ "attack_ref": "T1071.003",
333
+ "false_positive_checks_required": [
334
+ "From an unauthenticated session, issue MAIL FROM + RCPT TO an external domain and confirm the server rejects the relay — a server that requires authentication or restricts relay to local domains is safe.",
335
+ "A submission service (587) that relays for AUTHENTICATED users is not an open relay; the finding is relay for UNAUTHENTICATED peers on the inbound MX (25)."
336
+ ]
337
+ },
338
+ {
339
+ "id": "pop3-command-injection",
340
+ "type": "config_value",
341
+ "value": "The POP3 command parser accepts bare CR or bare LF in commands instead of enforcing canonical CRLF termination.",
342
+ "description": "Bare-CR/LF acceptance in POP3 enables command smuggling against the mailbox-retrieval service the same way it does in SMTP/IMAP.",
343
+ "confidence": "low",
344
+ "deterministic": false,
345
+ "attack_ref": "T1190",
346
+ "false_positive_checks_required": [
347
+ "Confirm the POP3 parser refuses bare-CR / bare-LF — a parser enforcing CRLF is safe.",
348
+ "POP3 may be disabled entirely; if no POP3 listener exists this indicator is not-in-scope, not a hit."
349
+ ]
350
+ },
351
+ {
352
+ "id": "mailbox-dav-path-traversal-xxe",
353
+ "type": "config_value",
354
+ "value": "The CalDAV/CardDAV (mailbox-DAV) endpoint does not refuse `..` / `%2e%2e` / NUL in request URLs, or parses PROPFIND/REPORT XML bodies without disabling external entities (XXE).",
355
+ "description": "Path traversal reads/writes outside the mailbox store; XXE on the DAV XML body exfiltrates local files or performs SSRF from the mail server.",
356
+ "confidence": "medium",
357
+ "deterministic": false,
358
+ "attack_ref": "T1190",
359
+ "false_positive_checks_required": [
360
+ "Confirm the DAV endpoint rejects encoded/decoded `..` and NUL in the request path AND that its XML parser disables DTDs/external entities — a hardened endpoint is safe.",
361
+ "A DAV library that resolves the path against a chroot/jail and uses a non-resolving XML parser is not the finding even if `..` appears in a raw URL."
362
+ ]
363
+ },
364
+ {
365
+ "id": "cleartext-auth-before-starttls",
366
+ "type": "config_value",
367
+ "value": "The submission/IMAP/POP3 listener offers and accepts AUTHENTICATE/AUTH PLAIN or LOGIN before STARTTLS (no require-TLS-before-auth).",
368
+ "description": "Credentials are transmitted in cleartext on the wire before encryption, sniffable by any on-path observer.",
369
+ "confidence": "medium",
370
+ "deterministic": false,
371
+ "attack_ref": "T1040",
372
+ "false_positive_checks_required": [
373
+ "Confirm the listener advertises and accepts AUTH only after STARTTLS (or only on implicit-TLS ports) — a listener that gates AUTH on an active TLS session is safe.",
374
+ "On an implicit-TLS port (465/993/995) the session is already encrypted, so pre-STARTTLS AUTH is not applicable."
375
+ ]
376
+ },
377
+ {
378
+ "id": "mail-auth-no-rate-limit",
379
+ "type": "config_value",
380
+ "value": "The mail listeners enforce no per-IP/per-account rate limit, greylisting, or RBL check on authentication attempts and inbound connections.",
381
+ "description": "Absence of rate limiting / greylisting leaves the auth surface open to credential brute-force and the inbound surface open to spam-flood abuse.",
382
+ "confidence": "low",
383
+ "deterministic": false,
384
+ "attack_ref": "T1110",
385
+ "false_positive_checks_required": [
386
+ "Confirm a per-IP or per-account auth rate-limit (and/or greylist / RBL) is active on the listeners — a server with lockout + connection throttling is safe.",
387
+ "A mail service fronted by a rate-limiting gateway / WAF that enforces this upstream is not the finding; inspect the effective enforced policy, not just the listener default."
388
+ ]
389
+ }
390
+ ],
391
+ "false_positive_profile": [
392
+ {
393
+ "indicator_id": "smtp-smuggling-end-of-data-accepted",
394
+ "benign_pattern": "A documented test fixture, comment, or upstream-proxy-enforced control that mentions the protocol shape without the live listener exhibiting it.",
395
+ "distinguishing_test": "Send a DATA probe terminated with <LF>.<LF> and confirm the server treats it as end-of-message and accepts a smuggled follow-on envelope — a server that rejects the non-standard terminator is safe; a comment or doc that merely mentions the sequence is not a hit."
396
+ },
397
+ {
398
+ "indicator_id": "starttls-receive-buffer-not-drained",
399
+ "benign_pattern": "A documented test fixture, comment, or upstream-proxy-enforced control that mentions the protocol shape without the live listener exhibiting it.",
400
+ "distinguishing_test": "Pipeline a plaintext command immediately before STARTTLS and confirm it is processed after the handshake — a listener that clears the receive buffer at the STARTTLS upgrade is safe."
401
+ },
402
+ {
403
+ "indicator_id": "imap-command-literal-injection",
404
+ "benign_pattern": "A documented test fixture, comment, or upstream-proxy-enforced control that mentions the protocol shape without the live listener exhibiting it.",
405
+ "distinguishing_test": "Confirm the parser refuses bare-CR / bare-LF and validates non-synchronizing literal lengths against the declared {n} — a parser that already rejects these (RFC 9051 §2.2.2) is safe."
406
+ },
407
+ {
408
+ "indicator_id": "managesieve-putscript-unbounded",
409
+ "benign_pattern": "A documented test fixture, comment, or upstream-proxy-enforced control that mentions the protocol shape without the live listener exhibiting it.",
410
+ "distinguishing_test": "Confirm PUTSCRIPT caps the literal byte size, rejects script names with slash/backslash/NUL, and refuses AUTHENTICATE over cleartext (RFC 5804 §1.1 + RFC 4954 §4) — a listener enforcing all three is safe."
411
+ },
412
+ {
413
+ "indicator_id": "sieve-redirect-uncapped",
414
+ "benign_pattern": "A documented test fixture, comment, or upstream-proxy-enforced control that mentions the protocol shape without the live listener exhibiting it.",
415
+ "distinguishing_test": "Confirm Sieve execution bounds redirect count per script and/or enforces a redirect-destination policy — an engine with a gas counter + redirect cap is safe."
416
+ },
417
+ {
418
+ "indicator_id": "inbound-open-relay",
419
+ "benign_pattern": "A documented test fixture, comment, or upstream-proxy-enforced control that mentions the protocol shape without the live listener exhibiting it.",
420
+ "distinguishing_test": "From an unauthenticated session, issue MAIL FROM + RCPT TO an external domain and confirm the server rejects the relay — a server that requires authentication or restricts relay to local domains is safe."
421
+ },
422
+ {
423
+ "indicator_id": "pop3-command-injection",
424
+ "benign_pattern": "A documented test fixture, comment, or upstream-proxy-enforced control that mentions the protocol shape without the live listener exhibiting it.",
425
+ "distinguishing_test": "Confirm the POP3 parser refuses bare-CR / bare-LF — a parser enforcing CRLF is safe."
426
+ },
427
+ {
428
+ "indicator_id": "mailbox-dav-path-traversal-xxe",
429
+ "benign_pattern": "A documented test fixture, comment, or upstream-proxy-enforced control that mentions the protocol shape without the live listener exhibiting it.",
430
+ "distinguishing_test": "Confirm the DAV endpoint rejects encoded/decoded `..` and NUL in the request path AND that its XML parser disables DTDs/external entities — a hardened endpoint is safe."
431
+ },
432
+ {
433
+ "indicator_id": "cleartext-auth-before-starttls",
434
+ "benign_pattern": "A documented test fixture, comment, or upstream-proxy-enforced control that mentions the protocol shape without the live listener exhibiting it.",
435
+ "distinguishing_test": "Confirm the listener advertises and accepts AUTH only after STARTTLS (or only on implicit-TLS ports) — a listener that gates AUTH on an active TLS session is safe."
436
+ },
437
+ {
438
+ "indicator_id": "mail-auth-no-rate-limit",
439
+ "benign_pattern": "A documented test fixture, comment, or upstream-proxy-enforced control that mentions the protocol shape without the live listener exhibiting it.",
440
+ "distinguishing_test": "Confirm a per-IP or per-account auth rate-limit (and/or greylist / RBL) is active on the listeners — a server with lockout + connection throttling is safe."
441
+ }
442
+ ],
443
+ "minimum_signal": {
444
+ "detected": "At least one inbound mail listener accepts a protocol shape it should refuse (non-standard end-of-data, undrained STARTTLS buffer, command-literal injection, unauthenticated relay, uncapped Sieve redirect, DAV traversal/XXE, or cleartext AUTH) on a production-reachable port.",
445
+ "inconclusive": "A protocol check is enforced by an upstream proxy the audit could not read — record as visibility_gap, not a clean result.",
446
+ "not_detected": "Every inbound listener enforces canonical CRLF + standard end-of-data, drains the STARTTLS buffer, gates AUTH on active TLS, refuses unauthenticated relay, caps Sieve redirect, and hardens the mailbox-DAV parser."
447
+ }
448
+ },
449
+ "analyze": {
450
+ "rwep_inputs": [
451
+ {
452
+ "signal_id": "smtp-smuggling-end-of-data-accepted",
453
+ "rwep_factor": "public_poc",
454
+ "weight": 20
455
+ },
456
+ {
457
+ "signal_id": "inbound-open-relay",
458
+ "rwep_factor": "blast_radius",
459
+ "weight": 25
460
+ },
461
+ {
462
+ "signal_id": "starttls-receive-buffer-not-drained",
463
+ "rwep_factor": "active_exploitation",
464
+ "weight": 10
465
+ }
466
+ ],
467
+ "blast_radius_model": {
468
+ "scope_question": "Is the affected listener internet-facing, and does the gap enable spoofing/relay (reputation + phishing delivery) or mailbox data exposure?",
469
+ "scoring_rubric": [
470
+ {
471
+ "condition": "Internet-facing inbound MX with SMTP smuggling or open relay (spoofing / reputation abuse at internet scale)",
472
+ "blast_radius_score": 5,
473
+ "description": "Spoofed authentication-passing mail or relayed spam delivered at scale"
474
+ },
475
+ {
476
+ "condition": "Internet-facing mailbox protocol (IMAP/DAV) with command-injection / traversal exposing mailbox data",
477
+ "blast_radius_score": 4,
478
+ "description": "Mailbox contents readable or routable to an attacker"
479
+ },
480
+ {
481
+ "condition": "Internal-only mail listener behind network controls",
482
+ "blast_radius_score": 2,
483
+ "description": "Exploitation requires prior network access"
484
+ }
485
+ ]
486
+ },
487
+ "compliance_theater_check": {
488
+ "claim": "We have SPF/DKIM/DMARC and TLS, so our mail server is secure.",
489
+ "audit_evidence": "DMARC policy records, a TLS certificate, a config flag asserting relay restrictions.",
490
+ "reality_test": "Probe the inbound listener: non-standard end-of-data acceptance, STARTTLS buffer drain, unauthenticated relay, cleartext AUTH. If any succeeds, sender-auth and TLS did not protect the protocol layer.",
491
+ "theater_verdict_if_gap": "theater"
492
+ },
493
+ "framework_gap_mapping": [
494
+ {
495
+ "finding_id": "smtp-smuggling-end-of-data-accepted",
496
+ "framework": "nist-800-53",
497
+ "claimed_control": "SI-2 (flaw remediation)",
498
+ "actual_gap": "SI-2 expects a patch; the smuggling fix is end-of-data configuration the patch process does not surface."
499
+ },
500
+ {
501
+ "finding_id": "inbound-open-relay",
502
+ "framework": "nis2",
503
+ "claimed_control": "Art.21(2) (network security)",
504
+ "actual_gap": "Art.21 names essential-service network security but not relay-authorization posture on the inbound MX."
505
+ }
506
+ ],
507
+ "escalation_criteria": [
508
+ {
509
+ "condition": "An internet-facing inbound MX accepts non-standard end-of-data (smuggling) or relays for unauthenticated peers",
510
+ "action": "raise_severity"
511
+ },
512
+ {
513
+ "condition": "Sieve redirect is uncapped on a multi-tenant mailbox service (mail-exfil primitive)",
514
+ "action": "trigger_playbook"
515
+ }
516
+ ]
517
+ },
518
+ "validate": {
519
+ "remediation_paths": [
520
+ {
521
+ "id": "enforce-standard-end-of-data",
522
+ "description": "Reject non-standard end-of-data sequences on the inbound SMTP listener (and upgrade the MTA to the smuggling-fixed release); require canonical <CR><LF>.<CR><LF>.",
523
+ "preconditions": [
524
+ "operator controls the inbound MTA configuration"
525
+ ],
526
+ "priority": 1,
527
+ "for_signals": [
528
+ "smtp-smuggling-end-of-data-accepted"
529
+ ]
530
+ },
531
+ {
532
+ "id": "drain-starttls-buffer-and-gate-auth",
533
+ "description": "Discard bytes buffered before the STARTTLS handshake on every opportunistic-STARTTLS listener, and refuse AUTHENTICATE/AUTH until TLS is active.",
534
+ "preconditions": [],
535
+ "priority": 1,
536
+ "for_signals": [
537
+ "starttls-receive-buffer-not-drained",
538
+ "cleartext-auth-before-starttls"
539
+ ]
540
+ },
541
+ {
542
+ "id": "harden-command-parsers",
543
+ "description": "Refuse bare-CR/LF and validate literal lengths in the IMAP/POP3 parsers; cap PUTSCRIPT bytes and reject slash/backslash/NUL script names in ManageSieve.",
544
+ "preconditions": [],
545
+ "priority": 1,
546
+ "for_signals": [
547
+ "imap-command-literal-injection",
548
+ "pop3-command-injection",
549
+ "managesieve-putscript-unbounded"
550
+ ]
551
+ },
552
+ {
553
+ "id": "restrict-relay-and-cap-sieve",
554
+ "description": "Restrict SMTP relay to authenticated users / local domains, and cap Sieve redirect count + enforce a redirect-destination policy.",
555
+ "preconditions": [],
556
+ "priority": 2,
557
+ "for_signals": [
558
+ "inbound-open-relay",
559
+ "sieve-redirect-uncapped"
560
+ ]
561
+ },
562
+ {
563
+ "id": "harden-dav-and-add-rate-limits",
564
+ "description": "Refuse encoded/decoded traversal + NUL on the mailbox-DAV endpoint and disable XML external entities; add per-IP/per-account auth rate limiting + greylisting.",
565
+ "preconditions": [],
566
+ "priority": 2,
567
+ "for_signals": [
568
+ "mailbox-dav-path-traversal-xxe",
569
+ "mail-auth-no-rate-limit"
570
+ ]
571
+ }
572
+ ],
573
+ "validation_tests": [
574
+ {
575
+ "id": "smuggling-rejected",
576
+ "test": "Send a DATA probe terminated with <LF>.<LF> from an external client.",
577
+ "expected_result": "Server rejects the non-standard terminator; no smuggled second message is delivered.",
578
+ "test_type": "negative"
579
+ },
580
+ {
581
+ "id": "relay-rejected",
582
+ "test": "From an unauthenticated session, MAIL FROM + RCPT TO an external domain.",
583
+ "expected_result": "Server refuses the relay (requires auth / local-domain).",
584
+ "test_type": "negative"
585
+ },
586
+ {
587
+ "id": "starttls-injection-rejected",
588
+ "test": "Pipeline a plaintext command before STARTTLS and complete the handshake.",
589
+ "expected_result": "Buffered pre-TLS command is discarded, not executed post-handshake.",
590
+ "test_type": "negative"
591
+ },
592
+ {
593
+ "id": "legitimate-mail-flows",
594
+ "test": "Send and retrieve a normal, well-formed message over the hardened listeners.",
595
+ "expected_result": "Mail flows normally — no regression on the legitimate path.",
596
+ "test_type": "functional"
597
+ }
598
+ ],
599
+ "residual_risk_statement": {
600
+ "risk": "A compromised authenticated account can still relay or store a malicious Sieve script within its own authorization.",
601
+ "why_remains": "Protocol hardening authenticates and bounds the protocol, not the trustworthiness of an authenticated user; account compromise is handled by identity controls.",
602
+ "acceptance_level": "ciso"
603
+ },
604
+ "evidence_requirements": [
605
+ {
606
+ "evidence_type": "config_diff",
607
+ "description": "The inbound-listener end-of-data, STARTTLS-drain, relay-authorization, parser, Sieve-cap, DAV, and rate-limit configuration as audited.",
608
+ "retention_period": "1 year"
609
+ },
610
+ {
611
+ "evidence_type": "exploit_replay_negative",
612
+ "description": "Outcomes of the smuggling / relay / STARTTLS-injection negative tests plus the legitimate-flow functional test.",
613
+ "retention_period": "1 year"
614
+ }
615
+ ],
616
+ "regression_trigger": [
617
+ {
618
+ "condition": "A new mail listener / protocol is enabled or the MTA is replaced",
619
+ "interval": "on change"
620
+ },
621
+ {
622
+ "condition": "Periodic re-attestation of inbound mail protocol posture",
623
+ "interval": "quarterly"
624
+ }
625
+ ]
626
+ },
627
+ "close": {
628
+ "evidence_package": {
629
+ "bundle_format": "csaf-2.0",
630
+ "contents": [
631
+ "mail-listener inventory",
632
+ "per-indicator findings + false-positive disposition",
633
+ "negative + functional test results",
634
+ "framework gap mapping"
635
+ ],
636
+ "destination": ".exceptd/attestations/<session_id>/attestation.json"
637
+ },
638
+ "learning_loop": {
639
+ "enabled": true,
640
+ "lesson_template": {
641
+ "attack_vector": "Inbound mail-server protocol abuse — SMTP smuggling, STARTTLS injection, open relay, command-literal injection, uncapped Sieve redirect, or mailbox-DAV traversal/XXE — that sender-authentication and transport TLS do not prevent.",
642
+ "control_gap": "Inbound listener lacks strict end-of-data handling / STARTTLS buffer drain / relay authorization / parser hardening.",
643
+ "framework_gap": "NIST SI-2 + NIS2 Art.21 cover patching and network security but not mail-protocol hardening posture.",
644
+ "new_control_requirement": "Inbound mail listeners MUST enforce canonical end-of-data, drain the STARTTLS buffer, gate AUTH on active TLS, and refuse unauthenticated relay."
645
+ }
646
+ },
647
+ "notification_actions": [
648
+ {
649
+ "obligation_ref": "EU/NIS2 Art.23 24h",
650
+ "deadline": "24h from detect_confirmed",
651
+ "recipient": "national CSIRT / competent authority",
652
+ "evidence_attached": [
653
+ "attestation"
654
+ ]
655
+ },
656
+ {
657
+ "obligation_ref": "EU/GDPR Art.33 72h",
658
+ "deadline": "72h from detect_confirmed",
659
+ "recipient": "data protection authority",
660
+ "evidence_attached": [
661
+ "attestation"
662
+ ]
663
+ }
664
+ ],
665
+ "exception_generation": {
666
+ "trigger_condition": "A legacy listener cannot be hardened immediately (e.g. a third-party MTA awaiting a vendor fix).",
667
+ "exception_template": {
668
+ "scope": "the specific listener + port",
669
+ "duration": "90 days",
670
+ "compensating_controls": [
671
+ "front the listener with a hardened SMTP/IMAP proxy",
672
+ "restrict the port to known networks",
673
+ "enhanced logging of relay + AUTH attempts"
674
+ ],
675
+ "risk_acceptance_owner": "ciso"
676
+ }
677
+ },
678
+ "regression_schedule": {
679
+ "next_run": "quarterly or on any new mail listener / MTA change",
680
+ "trigger": "change to mail listeners / protocols, or quarterly re-attestation"
681
+ }
682
+ }
683
+ },
684
+ "directives": [
685
+ {
686
+ "id": "all-inbound-mail-listeners",
687
+ "title": "Inventory + protocol-test every inbound mail listener",
688
+ "applies_to": {
689
+ "always": true
690
+ }
691
+ },
692
+ {
693
+ "id": "smtp-smuggling-sweep",
694
+ "title": "Targeted SMTP-smuggling + STARTTLS-injection sweep on internet-facing MX",
695
+ "applies_to": {
696
+ "attack_technique": "T1071.003"
697
+ }
698
+ }
699
+ ]
700
+ }