code wiki / _hdl_build / nx_doc_serve_gate.nx

nx_doc_serve_gate.nx source

↩ module page · 137 lines · 6540 B

1// nx_doc_serve_gate.nx -- GATE for LEGAL D3 (nx_doc_serve). 2// 3// Asserts the open-in-app-of-choice serve invariants, each w/ a negative control: 4// T1 CONTENT-TYPE : every format maps to its exact MIME (browser opens the 5// right app). 6// T2 BYTE-EXACT : a body that itself contains CRLFCRLF + NUL round-trips 7// bit-for-bit (Content-Length framed); flipping one body 8// byte is detected. 9// T3 DISPOSITION : DOCX defaults to download (open in Word), PDF inline; 10// the attachment response carries the filename. 11// T4 LENGTH+HARDENING : Content-Length is exact + X-Content-Type-Options:nosniff 12// present (no MIME-sniff of a legal doc). 13// T5 INJECTION-SAFE : a "name\r\nSet-Cookie: ..." filename cannot inject a 14// header -- framing intact AND the CRLF is stripped. 15// T6 SAFE-BY-DEFAULT : an unknown format is octet-stream + attachment (never 16// inlined). 17// T7 TENANT ISOLATION : the vault prefix discipline rejects '.'/'/' tenant ids. 18// 19// Evidence -> knowledge/status/doc_serve.log 20// license_tier: ORIGINAL 21import "nx_doc_serve.nx" 22import "nx_doc_vault.nx" 23import "nx_syscalls.nx" 24 25const DS_LOG: *u8 = "knowledge/status/doc_serve.log" 26 27func ew(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 } 28func ewn(fd: i64, v: i64) -> i64 { 29 let bb: *u8 = sys_mmap(28); var m: i64 = v 30 if m < 0 { m = 0 - m; sys_write(fd, "-" as *u8, 1) } 31 let t: *u8 = sys_mmap(28); var k: i64 = 0 32 if m == 0 { t[0] = 48; k = 1 } 33 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 34 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 35 sys_write(fd, bb, k); return 0 36} 37func streq(a: *u8, b: *u8) -> i64 { 38 var i: i64 = 0 39 while a[i] != (0 as u8) { 40 if a[i] != b[i] { return 0 } 41 i = i + 1 42 } 43 if b[i] != (0 as u8) { return 0 } 44 return 1 45} 46 47func main() -> i64 { 48 var ok: i64 = 1 49 50 // ---- T1: content-type mapping ---- 51 var t1: i64 = 1 52 if streq(nx_doc_content_type(DF_PDF), "application/pdf" as *u8) != 1 { t1 = 0 } 53 if streq(nx_doc_content_type(DF_HTML), "text/html; charset=utf-8" as *u8) != 1 { t1 = 0 } 54 if streq(nx_doc_content_type(DF_TXT), "text/plain; charset=utf-8" as *u8) != 1 { t1 = 0 } 55 if streq(nx_doc_content_type(DF_NXDOC), "application/x-nishi-doc" as *u8) != 1 { t1 = 0 } 56 if streq(nx_doc_content_type(DF_DOCX), "application/vnd.openxmlformats-officedocument.wordprocessingml.document" as *u8) != 1 { t1 = 0 } 57 if streq(nx_doc_content_type(DF_OCTET), "application/octet-stream" as *u8) != 1 { t1 = 0 } 58 if t1 != 1 { ok = 0 } 59 60 // ---- a document body with adversarial bytes (CRLFCRLF + NUL inside) ---- 61 let body: *u8 = sys_mmap(64) 62 body[0]=72; body[1]=105; body[2]=13; body[3]=10; body[4]=13; body[5]=10; body[6]=0; body[7]=66; body[8]=121; body[9]=101 63 let blen: i64 = 10 64 65 // ---- T2: byte-exact round-trip + corruption detection ---- 66 var t2: i64 = 1 67 let resp: *u8 = sys_mmap(4096) 68 let n2: i64 = nx_doc_serve_response(resp, body, blen, DF_PDF, DISP_INLINE, "x" as *u8) 69 if nx_doc_serve_roundtrip_ok(resp, n2, body, blen) != 1 { t2 = 0 } 70 resp[n2 - 1] = (resp[n2 - 1] ^ 0x20) as u8 71 if nx_doc_serve_roundtrip_ok(resp, n2, body, blen) != 0 { t2 = 0 } 72 resp[n2 - 1] = (resp[n2 - 1] ^ 0x20) as u8 73 if nx_doc_serve_roundtrip_ok(resp, n2, body, blen) != 1 { t2 = 0 } 74 if t2 != 1 { ok = 0 } 75 76 // ---- T3: disposition (open-in-app vs download) ---- 77 var t3: i64 = 1 78 if nx_doc_default_disposition(DF_DOCX) != DISP_ATTACHMENT { t3 = 0 } 79 if nx_doc_default_disposition(DF_PDF) != DISP_INLINE { t3 = 0 } 80 let r3: *u8 = sys_mmap(4096) 81 let n3: i64 = nx_doc_serve_response(r3, body, blen, DF_DOCX, DISP_ATTACHMENT, "estate_plan.docx" as *u8) 82 if nx_doc_serve_contains(r3, n3, "attachment; filename=" as *u8) != 1 { t3 = 0 } 83 if nx_doc_serve_contains(r3, n3, "estate_plan.docx" as *u8) != 1 { t3 = 0 } 84 let r3b: *u8 = sys_mmap(4096) 85 let n3b: i64 = nx_doc_serve_response(r3b, body, blen, DF_PDF, DISP_INLINE, "x" as *u8) 86 if nx_doc_serve_contains(r3b, n3b, "Content-Disposition: inline" as *u8) != 1 { t3 = 0 } 87 if t3 != 1 { ok = 0 } 88 89 // ---- T4: exact Content-Length + nosniff hardening ---- 90 var t4: i64 = 1 91 if nx_doc_serve_contains(r3b, n3b, "Content-Length: 10" as *u8) != 1 { t4 = 0 } 92 if nx_doc_serve_contains(r3b, n3b, "X-Content-Type-Options: nosniff" as *u8) != 1 { t4 = 0 } 93 if t4 != 1 { ok = 0 } 94 95 // ---- T5: a malicious filename cannot inject a header ---- 96 var t5: i64 = 1 97 let r5: *u8 = sys_mmap(4096) 98 let n5: i64 = nx_doc_serve_response(r5, body, blen, DF_DOCX, DISP_ATTACHMENT, "deed\r\nSet-Cookie: evil.docx" as *u8) 99 if nx_doc_serve_roundtrip_ok(r5, n5, body, blen) != 1 { t5 = 0 } 100 if nx_doc_serve_contains(r5, n5, "\r\nSet-Cookie" as *u8) != 0 { t5 = 0 } 101 if t5 != 1 { ok = 0 } 102 103 // ---- T6: unknown format is octet-stream + attachment (never inlined) ---- 104 var t6: i64 = 1 105 if streq(nx_doc_content_type(DF_OCTET), "application/octet-stream" as *u8) != 1 { t6 = 0 } 106 if nx_doc_default_disposition(DF_OCTET) != DISP_ATTACHMENT { t6 = 0 } 107 if t6 != 1 { ok = 0 } 108 109 // ---- T7: per-tenant prefix discipline ---- 110 var t7: i64 = 1 111 if nx_vault_valid_tid("client_andelinwest" as *u8) != 1 { t7 = 0 } 112 if nx_vault_valid_tid("../secret" as *u8) != 0 { t7 = 0 } 113 if nx_vault_valid_tid("a/b" as *u8) != 0 { t7 = 0 } 114 if t7 != 1 { ok = 0 } 115 116 // ---- evidence ---- 117 var fd: i64 = 1 118 while fd >= 1 { 119 ew(fd, "DOCSERVEGATE authored=organ composes=D1 content_type=" as *u8); ewn(fd, t1) 120 ew(fd, " byte_exact_roundtrip=" as *u8); ewn(fd, t2) 121 ew(fd, " disposition_open_in_app=" as *u8); ewn(fd, t3) 122 ew(fd, " length_exact_nosniff=" as *u8); ewn(fd, t4) 123 ew(fd, " filename_injection_safe=" as *u8); ewn(fd, t5) 124 ew(fd, " unknown_safe_default=" as *u8); ewn(fd, t6) 125 ew(fd, " tenant_isolation=" as *u8); ewn(fd, t7) 126 if ok == 1 { ew(fd, " verdict=GREEN\n" as *u8) } else { ew(fd, " verdict=RED\n" as *u8) } 127 if fd == 1 { 128 let lf: i64 = sys_openat_append(DS_LOG, 420) 129 if lf >= 1 { fd = lf } else { fd = 0 } 130 } else { 131 sys_close(fd); fd = 0 132 } 133 } 134 135 if ok == 1 { return 0 } 136 return 1 137}