code wiki / _hdl_build / nx_apistack_cors_gate.nx
nx_apistack_cors_gate.nx source
↩ module page · 43 lines · 3073 B
1// nx_apistack_cors_gate.nx -- hermetic gate for CAP-API-CORS. Proves deny-by-default: allowlisted origin allowed,
2// everything else denied, empty denied, and the header emits for an allowed origin. expect_exit: 0
3import "nx_syscalls.nx"
4import "nx_apistack_cors.nx"
5import "nx_gate_verdict.nx"
6
7func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
8func gn(v: i64) -> i64 { var t: i64=v; if t<0{sys_write(1,"-" as *u8,1);t=0-t} let tm:*u8=sys_mmap(24); var k:i64=0; if t==0{tm[0]=48 as u8;k=1} while t>0{tm[k]=(48+(t%10)) as u8;t=t/10;k=k+1} let b:*u8=sys_mmap(24); var j:i64=0; while j<k{b[j]=tm[k-1-j];j=j+1} sys_write(1,b,k); return 0 }
9func g_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
10func g_app(buf: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){buf[off+i]=s[i];i=i+1} return off+i }
11func g_eq(a: *u8, b: *u8, n: i64) -> i64 { var i: i64=0; while i<n { if a[i]!=b[i] { return 0 } i=i+1 } return 1 }
12
13func main(argc: i64, argv: *i64) -> i64 {
14 gp("=== nx_apistack_cors_gate (deny-by-default CORS allowlist) ===\n" as *u8)
15 let C: *u8 = "/tmp/cors_allow.conf" as *u8
16 let cf: *u8 = sys_mmap(256); var cn: i64 = 0
17 cn = g_app(cf, cn, "https://nishifamily.com" as *u8); cf[cn]=10 as u8; cn=cn+1
18 cn = g_app(cf, cn, "https://admin.andelinwest.com" as *u8); cf[cn]=10 as u8; cn=cn+1
19 let fd: i64 = sys_openat_wr(C, 0x1a4); if fd >= 0 { sys_write(fd, cf, cn); sys_close(fd) }
20 var pass: i64 = 0; var fail: i64 = 0
21
22 let ok: *u8 = "https://nishifamily.com" as *u8
23 if cors_allowed(C, ok, g_slen(ok)) == 1 { pass=pass+1; gp(" T1 allowlisted origin -> allowed PASS\n" as *u8) } else { fail=fail+1; gp(" T1 FAIL\n" as *u8) }
24
25 let bad: *u8 = "https://evil.com" as *u8
26 if cors_allowed(C, bad, g_slen(bad)) == 0 { pass=pass+1; gp(" T2 unlisted origin -> DENIED (deny-by-default) PASS\n" as *u8) } else { fail=fail+1; gp(" T2 FAIL allowed\n" as *u8) }
27
28 if cors_allowed(C, "" as *u8, 0) == 0 { pass=pass+1; gp(" T3 empty origin -> denied PASS\n" as *u8) } else { fail=fail+1; gp(" T3 FAIL\n" as *u8) }
29
30 let hb: *u8 = sys_mmap(256); let hn: i64 = cors_emit_header(hb, ok, g_slen(ok))
31 if g_eq(hb, "Access-Control-Allow-Origin: https://nishifamily.com\r\n" as *u8, hn) == 1 { pass=pass+1; gp(" T4 header emits for allowed origin PASS\n" as *u8) } else { fail=fail+1; gp(" T4 FAIL\n" as *u8) }
32
33 gp("RESULT pass=" as *u8); gn(pass); gp(" fail=" as *u8); gn(fail)
34 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
35 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
36 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
37 let ctr__dry: *i64 = gv_ctr()
38 ctr__dry[0] = pass
39 ctr__dry[1] = pass + fail
40 let rc__dry: i64 = gv_verdict("APISTACK-CORS-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
41 sys_exit(rc__dry)
42 return rc__dry
43}