code wiki / (root) / nx_chat_demo_api_gate.nx

nx_chat_demo_api_gate.nx source

↩ module page · 148 lines · 7565 B

1// nx_chat_demo_api_gate.nx -- REFEREE for the SAFE public chat front (nx_chat_demo_api). Forks the 2// PROMOTED elf and proves the security boundary: only post/list, rooms forced into demo_, inputs 3// sanitized and capped, injection-safe JSON, budgets/errors surfaced. Fixture rooms are epoch-suffixed 4// so each run is fresh (they live in the real demo_ store, tiny + budget-bounded, the whole point). 5// license_tier: ORIGINAL expect_exit: 0 6import "nx_syscalls.nx" 7import "nx_tool_run.nx" 8import "nx_gate_verdict.nx" 9const CG_CAP: i64 = 65536 10func cg_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 11func cg_count(buf: *u8, n: i64, needle: *u8) -> i64 { 12 let m: i64 = cg_len(needle) 13 if m <= 0 { return 0 } 14 var c: i64 = 0 15 var i: i64 = 0 16 while i + m <= n { 17 var k: i64 = 0 18 var hit: i64 = 1 19 while k < m { if buf[i+k] != needle[k] { hit = 0; k = m } else { k = k + 1 } } 20 if hit == 1 { c = c + 1; i = i + m } else { i = i + 1 } 21 } 22 return c 23} 24func cg_run(elf: *u8, av: *i64, out: *u8, ol: *i64) -> i64 { return tr_run_capture(elf, av, out, CG_CAP, ol) } 25func main(argc: i64, argv: *i64) -> i64 { 26 let ctr: *i64 = gv_ctr() 27 gv_head("nx_chat_demo_api -- the safe browser<->store boundary: post/list only, demo_ forced, inputs sanitized, injection-safe" as *u8) 28 let ELF: *u8 = "/volume1/homes/elderwesto/nishihost/nx_chat_demo_api.elf" as *u8 29 let out: *u8 = sys_mmap(CG_CAP) 30 let ol: *i64 = sys_mmap(16) as *i64 31 let av: *i64 = sys_mmap(64) as *i64 32 let ms: i64 = sys_now_realtime_ms() 33 // room base 'g<ms>' -- deterministic sanitize target 34 let rm: *u8 = sys_mmap(64) 35 var o: i64 = gv_cat(rm, 0, "g" as *u8) 36 o = gv_catn(rm, o, ms) 37 rm[o] = 0 as u8 38 // ---- T1 post ------------------------------------------------------------------------------ 39 av[0] = ELF as i64 40 av[1] = "post" as i64 41 av[2] = rm as i64 42 av[3] = "alice" as i64 43 av[4] = "hello from the gate" as i64 44 av[5] = 0 45 let p1: i64 = cg_run(ELF, av, out, ol) 46 var t1: i64 = 0 47 if p1 == 0 { if cg_count(out, ol[0], "{\"ok\":1" as *u8) == 1 { if cg_count(out, ol[0], "\"seq\":" as *u8) == 1 { t1 = 1 } } } 48 gv_check("T1 BITE: post returns ok:1 with a seq (message stored through the real C1 store)" as *u8, t1, ctr) 49 // ---- T2 list returns it, demo_ forced ------------------------------------------------------ 50 av[1] = "list" as i64 51 av[2] = rm as i64 52 av[3] = 0 53 let l1: i64 = cg_run(ELF, av, out, ol) 54 var t2: i64 = 0 55 if l1 == 0 { if cg_count(out, ol[0], "\"from\":\"alice\"" as *u8) == 1 { if cg_count(out, ol[0], "\"text\":\"hello from the gate\"" as *u8) == 1 { t2 = 1 } } } 56 gv_check("T2 list returns the posted message with correct sender and text" as *u8, t2, ctr) 57 var t3: i64 = 0 58 if l1 == 0 { if cg_count(out, ol[0], "\"room\":\"demo_g" as *u8) == 1 { t3 = 1 } } 59 gv_check("T3 DEMO NAMESPACE FORCED: the stored room is always demo_<name> -- no way to address a non-demo room" as *u8, t3, ctr) 60 // ---- T4 sanitize: uppercase + special chars are stripped, deterministically ---------------- 61 let rmx: *u8 = sys_mmap(64) 62 o = gv_cat(rmx, 0, "Hall Way!" as *u8) // -> hallway 63 rmx[o] = 0 as u8 64 av[1] = "post" as i64 65 av[2] = rmx as i64 66 av[3] = "Bob..007" as i64 // -> bob007 67 av[4] = "sanitized ok" as i64 68 av[5] = 0 69 let p2: i64 = cg_run(ELF, av, out, ol) 70 var t4: i64 = 0 71 if p2 == 0 { if cg_count(out, ol[0], "\"room\":\"demo_hallway\"" as *u8) == 1 { t4 = 1 } } 72 gv_check("T4 SANITIZE: 'Hall Way!' becomes demo_hallway -- spaces/case/punctuation stripped, no injection into the room path" as *u8, t4, ctr) 73 av[1] = "list" as i64 74 av[2] = "hallway" as i64 75 av[3] = 0 76 let l2: i64 = cg_run(ELF, av, out, ol) 77 var t5: i64 = 0 78 if l2 == 0 { if cg_count(out, ol[0], "\"from\":\"bob007\"" as *u8) == 1 { t5 = 1 } } 79 gv_check("T5 the sanitized name is deterministic: listing 'hallway' finds what 'Hall Way!' posted, sender folded to bob007" as *u8, t5, ctr) 80 // ---- T6 INJECTION-SAFE JSON ---------------------------------------------------------------- 81 let ri: *u8 = sys_mmap(64) 82 o = gv_cat(ri, 0, "inj" as *u8) 83 o = gv_catn(ri, o, ms) 84 ri[o] = 0 as u8 85 av[1] = "post" as i64 86 av[2] = ri as i64 87 av[3] = "eve" as i64 88 av[4] = "say hi and pipe | quote and end" as i64 89 av[5] = 0 90 cg_run(ELF, av, out, ol) 91 av[1] = "list" as i64 92 av[2] = ri as i64 93 av[3] = 0 94 let l3: i64 = cg_run(ELF, av, out, ol) 95 var t6: i64 = 0 96 if l3 == 0 { if cg_count(out, ol[0], "{\"ok\":1" as *u8) == 1 { if cg_count(out, ol[0], "pipe | quote" as *u8) == 1 { t6 = 1 } } } 97 gv_check("T6 INJECTION-SAFE: a body with a pipe (the store row delimiter) round-trips intact and the JSON stays valid -- C1 hex-armors the body, the delimiter cannot break parsing" as *u8, t6, ctr) 98 // ---- T7 neg-control-empty-text ------------------------------------------------------------- 99 av[1] = "post" as i64 100 av[2] = rm as i64 101 av[3] = "alice" as i64 102 av[4] = "" as i64 103 av[5] = 0 104 let p3: i64 = cg_run(ELF, av, out, ol) 105 var t7: i64 = 0 106 if p3 != 0 { if cg_count(out, ol[0], "empty-text" as *u8) == 1 { t7 = 1 } } 107 gv_check("T7 neg-control-empty: an empty message is refused, not stored" as *u8, t7, ctr) 108 // ---- T8 neg-control-bad-room (all-special sanitizes to empty) ------------------------------- 109 av[1] = "post" as i64 110 av[2] = "!!!___" as i64 // wait: underscores survive; use pure punctuation below 111 av[3] = "alice" as i64 112 av[4] = "x" as i64 113 av[5] = 0 114 av[2] = "!@#$%" as i64 115 let p4: i64 = cg_run(ELF, av, out, ol) 116 var t8: i64 = 0 117 if p4 != 0 { if cg_count(out, ol[0], "bad-room" as *u8) == 1 { t8 = 1 } } 118 gv_check("T8 neg-control-bad-room: a room name that sanitizes to nothing is refused -- cannot post to an empty/ambiguous room" as *u8, t8, ctr) 119 // ---- T9 neg-control-verb-whitelist --------------------------------------------------------- 120 av[1] = "purge" as i64 121 av[2] = rm as i64 122 av[3] = "alice" as i64 123 av[4] = "x" as i64 124 av[5] = 0 125 let p5: i64 = cg_run(ELF, av, out, ol) 126 var t9: i64 = 0 127 if p5 != 0 { if cg_count(out, ol[0], "usage" as *u8) == 1 { if cg_count(out, ol[0], "CHAT-PURGE" as *u8) == 0 { t9 = 1 } } } 128 gv_check("T9 VERB WHITELIST: only post/list exist -- 'purge' (and open/del/retention) are unreachable through this front; the destructive verbs cannot be invoked by a browser" as *u8, t9, ctr) 129 // ---- T10 text cap: a 400-char body is capped, still valid ---------------------------------- 130 let big: *u8 = sys_mmap(512) 131 var bi: i64 = 0 132 while bi < 400 { big[bi] = 97 as u8; bi = bi + 1 } 133 big[400] = 0 as u8 134 let rc2: *u8 = sys_mmap(64) 135 o = gv_cat(rc2, 0, "cap" as *u8) 136 o = gv_catn(rc2, o, ms) 137 rc2[o] = 0 as u8 138 av[1] = "post" as i64 139 av[2] = rc2 as i64 140 av[3] = "alice" as i64 141 av[4] = big as i64 142 av[5] = 0 143 let p6: i64 = cg_run(ELF, av, out, ol) 144 var t10: i64 = 0 145 if p6 == 0 { if cg_count(out, ol[0], "{\"ok\":1" as *u8) == 1 { t10 = 1 } } 146 gv_check("T10 a 400-char body is accepted but capped at 280 by the boundary (no unbounded write reaches the store)" as *u8, t10, ctr) 147 return gv_verdict("CHAT-DEMO-API-GATE" as *u8, ctr, "post/list only, demo_ namespace forced, inputs sanitized and capped, injection-safe JSON, destructive verbs unreachable -- a safe browser front to the real C1 store" as *u8) 148}