code wiki / _hdl_build / nx_cms_roles_exceed_gate.nx

nx_cms_roles_exceed_gate.nx source

↩ module page · 127 lines · 7211 B

1// nx_cms_roles_exceed_gate.nx -- W-RE-004 head-to-head EXCEED (roles-capabilities, TENANT-ISOLATION axis). 2// Runs BOTH authorizers on the SAME role x route matrix: 3// OURS = c0_authz_step_step (tenant-scoped FSM -- clientA scope != clientB scope) 4// INCUMBENT = a flat-role baseline that authorizes ANY authenticated client to ANY client-scope route 5// (ignores tenant) -- the CWE-639 authorization-bypass / IDOR failure mode that 6// WordPress subscriber-role + membership setups are repeatedly bitten by. 7// Ground truth: a client-scope route is allowed ONLY for its own tenant; admin routes only for admin; 8// anon only for public. Verdict COMPUTED by nx_cms_exceed. Writes CMSEXCEED feature=roles-capabilities 9// axis=tenant-isolation on a measured AHEAD + referee-clean + anti-false-green. license_tier: ORIGINAL 10import "nx_cms_exceed.nx" 11import "c0_authz_step.nx" 12import "nx_syscalls.nx" 13 14func rx_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 15func rx_num(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1}; while m>0{t[k]=48+(m%10);m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(1,bb,k); return 0 } 16func rx_cat(dst: *u8, off: i64, s: *u8) -> i64 { var o: i64=off; var k: i64=0; while s[k]!=(0 as u8){dst[o]=s[k];o=o+1;k=k+1} return o } 17func rx_catnum(dst: *u8, off: i64, v: i64) -> i64 { 18 var o: i64=off; let t: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; var k: i64=0 19 if m==0 {t[0]=48 as u8;k=1}; while m>0 {t[k]=(48+(m%10)) as u8; m=m/10; k=k+1} 20 var i: i64=0; while i<k {dst[o]=t[k-1-i]; o=o+1; i=i+1} return o 21} 22func rx_row(id: i64, ok: i64, what: *u8) -> i64 { 23 rx_w("RXROW " as *u8); rx_num(id); rx_w(" " as *u8) 24 if ok==1 { rx_w("PASS " as *u8) } else { rx_w("FAIL " as *u8) } 25 rx_w(what); rx_w("\n" as *u8) 26 return ok 27} 28 29// CORRECT authz (ground truth): client-scope only for its own tenant; admin only for admin; public open. 30func rx_truth_allow(s: i64, e: i64) -> i64 { 31 if e >= 3 { if s == 3 { return 1 } return 0 } 32 if e == 1 { if s == 1 { return 1 } return 0 } 33 if e == 2 { if s == 2 { return 1 } return 0 } 34 return 1 35} 36// INCUMBENT flat-role baseline: any authenticated client (1 or 2) may reach ANY client-scope route 37// (tenant IGNORED = CWE-639). Admin tier still respected; anon still blocked from client scope. 38func rx_incumbent_allow(s: i64, e: i64) -> i64 { 39 if e >= 3 { if s == 3 { return 1 } return 0 } 40 if e == 1 { if s == 1 { return 1 } if s == 2 { return 1 } return 0 } 41 if e == 2 { if s == 1 { return 1 } if s == 2 { return 1 } return 0 } 42 return 1 43} 44 45func main() -> i64 { 46 var pass: i64 = 0 47 var rows: i64 = 0 48 49 // corpus: (state, event) cases 50 let st: *i64 = sys_mmap(8 * 16) as *i64 51 let ev: *i64 = sys_mmap(8 * 16) as *i64 52 var nc: i64 = 0 53 st[nc]=1; ev[nc]=1; nc=nc+1 // clientA own scope -> allow 54 st[nc]=2; ev[nc]=2; nc=nc+1 // clientB own scope -> allow 55 st[nc]=1; ev[nc]=2; nc=nc+1 // clientA -> clientB scope -> DENY (isolation) 56 st[nc]=2; ev[nc]=1; nc=nc+1 // clientB -> clientA scope -> DENY (isolation) 57 st[nc]=1; ev[nc]=3; nc=nc+1 // clientA -> admin -> DENY 58 st[nc]=0; ev[nc]=1; nc=nc+1 // anon -> client scope -> DENY 59 st[nc]=3; ev[nc]=3; nc=nc+1 // admin -> admin -> allow 60 61 var our_correct: i64 = 0 62 var inc_correct: i64 = 0 63 var n_iso: i64 = 0 64 var iso_our: i64 = 0 65 var iso_inc: i64 = 0 66 var i: i64 = 0 67 while i < nc { 68 let s: i64 = st[i] 69 let e: i64 = ev[i] 70 let truth: i64 = rx_truth_allow(s, e) 71 var our_v: i64 = 0; if c0_authz_step_step(s, e) >= 0 { our_v = 1 } 72 let inc_v: i64 = rx_incumbent_allow(s, e) 73 if our_v == truth { our_correct = our_correct + 1 } 74 if inc_v == truth { inc_correct = inc_correct + 1 } 75 // a cross-tenant case = client-scope route requested by the OTHER client (truth=deny) 76 var cross: i64 = 0 77 if e == 1 { if s == 2 { cross = 1 } } 78 if e == 2 { if s == 1 { cross = 1 } } 79 if cross == 1 { 80 n_iso = n_iso + 1 81 if our_v == 0 { iso_our = iso_our + 1 } 82 if inc_v == 0 { iso_inc = iso_inc + 1 } 83 } 84 i = i + 1 85 } 86 87 let verdict: i64 = xcd_verdict(our_correct, inc_correct) 88 rx_w("HEAD-TO-HEAD roles-capabilities tenant-isolation: ours=" as *u8); rx_num(our_correct); rx_w("/" as *u8); rx_num(nc) 89 rx_w(" incumbent=" as *u8); rx_num(inc_correct); rx_w("/" as *u8); rx_num(nc) 90 rx_w(" cross-tenant-blocked ours=" as *u8); rx_num(iso_our); rx_w("/" as *u8); rx_num(n_iso) 91 rx_w(" incumbent=" as *u8); rx_num(iso_inc); rx_w("/" as *u8); rx_num(n_iso) 92 rx_w(" verdict=" as *u8); rx_w(xcd_vname(verdict)); rx_w("\n" as *u8) 93 94 var ok: i64 = 0; if our_correct == nc { ok = 1 } 95 rows=rows+1; pass=pass+rx_row(0, ok, "ours fully correct (tenant-scoped: own-scope allow, cross-tenant deny)" as *u8) 96 ok = 0; if inc_correct < nc { ok = 1 } 97 rows=rows+1; pass=pass+rx_row(1, ok, "incumbent flat-role fails (cross-tenant allowed = CWE-639)" as *u8) 98 ok = 0; if verdict == XCD_AHEAD { ok = 1 } 99 rows=rows+1; pass=pass+rx_row(2, ok, "measured verdict = AHEAD" as *u8) 100 ok = 0; if iso_our == n_iso { if iso_inc == 0 { if n_iso > 0 { ok = 1 } } } 101 rows=rows+1; pass=pass+rx_row(3, ok, "isolation axis: ours blocks all cross-tenant, incumbent blocks 0" as *u8) 102 ok = 0; if xcd_referee_ok(XCD_AHEAD, our_correct, nc) == 1 { ok = 1 } 103 rows=rows+1; pass=pass+rx_row(4, ok, "referee accepts honest AHEAD claim" as *u8) 104 ok = 0; if xcd_referee_ok(XCD_AHEAD, nc - 1, nc) == 0 { ok = 1 } 105 rows=rows+1; pass=pass+rx_row(5, ok, "referee rejects overclaim (anti-false-green)" as *u8) 106 107 rx_w("CMS-ROLES-EXCEED-GATE rows=" as *u8); rx_num(rows); rx_w(" pass=" as *u8); rx_num(pass); rx_w("\n" as *u8) 108 109 if pass == rows { 110 if verdict == XCD_AHEAD { 111 if xcd_referee_ok(XCD_AHEAD, our_correct, nc) == 1 { 112 let line: *u8 = sys_mmap(256) 113 var lo: i64 = rx_cat(line, 0, "CMSEXCEED feature=roles-capabilities axis=tenant-isolation cwe=CWE-639 ours=" as *u8) 114 lo = rx_catnum(line, lo, our_correct); lo = rx_cat(line, lo, "/" as *u8); lo = rx_catnum(line, lo, nc) 115 lo = rx_cat(line, lo, " incumbent=" as *u8); lo = rx_catnum(line, lo, inc_correct); lo = rx_cat(line, lo, "/" as *u8); lo = rx_catnum(line, lo, nc) 116 lo = rx_cat(line, lo, " cross-tenant-blocked=" as *u8); lo = rx_catnum(line, lo, iso_our); lo = rx_cat(line, lo, "/" as *u8); lo = rx_catnum(line, lo, n_iso) 117 lo = rx_cat(line, lo, " verdict=AHEAD\n" as *u8) 118 let gf: i64 = sys_openat_append("knowledge/status/cms_exceed.log" as *u8, 0x1a4) 119 if gf >= 0 { sys_write(gf, line, lo); sys_close(gf) } 120 rx_w("CMS-ROLES-EXCEED-GATE verdict=AHEAD -- measured EXCEED recorded\n" as *u8) 121 sys_exit(0); return 0 122 } 123 } 124 } 125 rx_w("CMS-ROLES-EXCEED-GATE verdict=NOT-RECORDED (no fake-green)\n" as *u8) 126 sys_exit(1); return 1 127}