code wiki / (root) / nx_cap_issue_gate.nx

nx_cap_issue_gate.nx source

↩ module page · 101 lines · 5825 B

1// nx_cap_issue_gate.nx -- proves the self-service DELEGATION endpoint (POST /api/cap/issue) over R0's ta_handle: 2// delegating narrows (the delegated cap grants the subset, not the dropped tool), widening is REFUSED, and a 3// forged presenter cap is REFUSED. Drives ta_handle_pfx in-process. license_tier: ORIGINAL 4import "nx_tools_api.nx" 5import "nx_gate.nx" 6 7func ig_has(o: *u8, n: i64, ndl: *u8) -> i64 { if ta_indexof(o, n, ndl) >= 0 { return 1 } return 0 } 8func ig_mark(cond: i64, p: *i64, t: *i64, lbl: *u8) -> i64 { 9 t[0] = t[0] + 1 10 if cond == 1 { p[0] = p[0] + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 11 gw(lbl); gw("\n" as *u8) 12 return 0 13} 14func ig_issue_req(cap: *u8, caplen: i64, allow: *u8, out: *u8) -> i64 { 15 var o: i64 = ta_cat(out, 0, "POST /api/cap/issue HTTP/1.1\r\nHost: x\r\nX-Nishi-Cap: " as *u8) 16 o = ta_catb(out, o, cap, caplen) 17 o = ta_cat(out, o, "\r\nConnection: close\r\n\r\n{\"allow\":\"" as *u8) 18 o = ta_cat(out, o, allow) 19 o = ta_cat(out, o, "\",\"exp\":9999999999}" as *u8) 20 return o 21} 22func ig_call_req(cap: *u8, caplen: i64, name: *u8, out: *u8) -> i64 { 23 var o: i64 = ta_cat(out, 0, "POST /mcp HTTP/1.1\r\nHost: x\r\nConnection: close\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/call\",\"params\":{\"name\":\"" as *u8) 24 o = ta_cat(out, o, name) 25 o = ta_cat(out, o, "\",\"_cap\":\"" as *u8) 26 o = ta_catb(out, o, cap, caplen) 27 o = ta_cat(out, o, "\"}}" as *u8) 28 return o 29} 30// extract the "cap" value from a /api/cap/issue response into (off,len) relative to resp. 1/0. 31func ig_extract(resp: *u8, n: i64, ol: *i64) -> i64 { 32 let bo: i64 = ta_body_off(resp, n) 33 let body: *u8 = ((resp as i64) + bo) as *u8 34 let bn: i64 = n - bo 35 let cb: *i64 = sys_mmap(16) as *i64 36 if ta_json_str(body, bn, "\"cap\"" as *u8, cb) == 1 { ol[0] = bo + cb[0]; ol[1] = cb[1]; return 1 } 37 return 0 38} 39 40func main() -> i64 { 41 gw("=== nx_cap_issue_gate: self-service capability DELEGATION (ocap: subset-only, widening refused) ===\n" as *u8) 42 let TP: *u8 = "knowledge/toolreg-test-iss-" as *u8 43 let secret: *u8 = TA_CAP_SECRET 44 let slen: i64 = ta_slen(TA_CAP_SECRET) 45 let p: *i64 = sys_mmap(16) as *i64; p[0] = 0 46 let t: *i64 = sys_mmap(16) as *i64; t[0] = 0 47 let out: *u8 = sys_mmap(1048576) 48 let req: *u8 = sys_mmap(4096) 49 let ol: *i64 = sys_mmap(16) as *i64 50 51 let rootb: *u8 = sys_mmap(1024) 52 let root: i64 = capt_issue(secret, slen, "nx_a,nx_b" as *u8, 9, 9999999999, 1, rootb, 1024) 53 54 // Iss1: delegate {a,b} -> {a}. The delegated cap must GRANT nx_a (tools/call invoked) and DENY nx_b (narrowed). 55 let r1: i64 = ig_issue_req(rootb, root, "nx_a" as *u8, req) 56 let n1: i64 = ta_handle_pfx(TP, req, r1, out) 57 var t1: i64 = 0 58 if ig_extract(out, n1, ol) == 1 { 59 let dcap: *u8 = sys_mmap(1024); var c: i64 = 0; while c < ol[1] { dcap[c] = out[ol[0] + c]; c = c + 1 } 60 let dl: i64 = ol[1] 61 let ra: i64 = ig_call_req(dcap, dl, "nx_a" as *u8, req); let na: i64 = ta_handle_pfx(TP, req, ra, out) 62 // post-R2-exec-rung: a granted cap on a non-GREEN-allowlisted tool terminates at the 63 // "capability-authorized ..." tool result (only reachable when the delegated cap VERIFIED) 64 var ga: i64 = 0; if ig_has(out, na, "capability-authorized" as *u8) == 1 { if ig_has(out, na, "-32001" as *u8) == 0 { ga = 1 } } 65 let rb: i64 = ig_call_req(dcap, dl, "nx_b" as *u8, req); let nb: i64 = ta_handle_pfx(TP, req, rb, out) 66 var db: i64 = 0; if ig_has(out, nb, "-32001" as *u8) == 1 { db = 1 } 67 if ga == 1 { if db == 1 { t1 = 1 } } 68 } 69 ig_mark(t1, p, t, "Iss1 delegate {a,b}->{a}: delegated cap GRANTS a, DENIES b (narrowed + usable)" as *u8) 70 71 // Iss2: request {a,c} where c is NOT in the presenter's grant -> REFUSED (no widening). 72 let r2: i64 = ig_issue_req(rootb, root, "nx_a,nx_c" as *u8, req) 73 let n2: i64 = ta_handle_pfx(TP, req, r2, out) 74 var t2: i64 = 0; if ig_has(out, n2, "cannot delegate" as *u8) == 1 { t2 = 1 } 75 ig_mark(t2, p, t, "Iss2 request {a,c} (c not held) -> REFUSED (no widening; escalation blocked)" as *u8) 76 77 // Iss3: forged presenter cap -> REFUSED. 78 let fb: *u8 = sys_mmap(1024) 79 let froot: i64 = capt_issue("WRONG-forger-key-9999999999999999xy" as *u8, 35, "nx_a" as *u8, 4, 9999999999, 1, fb, 1024) 80 let r3: i64 = ig_issue_req(fb, froot, "nx_a" as *u8, req) 81 let n3: i64 = ta_handle_pfx(TP, req, r3, out) 82 var t3: i64 = 0; if ig_has(out, n3, "cannot delegate" as *u8) == 1 { t3 = 1 } 83 ig_mark(t3, p, t, "Iss3 FORGED presenter cap -> REFUSED (unforgeable input)" as *u8) 84 85 // Iss4: exp-clamp -- parent exp=1000; the endpoint request asks exp=9999999999 -> the delegated cap MUST be clamped 86 // to <= parent (so it is EXPIRED at now=2000, NOT silently extended to the far future). 87 let pb2: *u8 = sys_mmap(1024) 88 let root2: i64 = capt_issue(secret, slen, "nx_a,nx_b" as *u8, 9, 1000, 5, pb2, 1024) 89 let r4: i64 = ig_issue_req(pb2, root2, "nx_a" as *u8, req) 90 let n4: i64 = ta_handle_pfx(TP, req, r4, out) 91 var t4: i64 = 0 92 if ig_extract(out, n4, ol) == 1 { 93 let dc: *u8 = sys_mmap(1024); var cc: i64 = 0; while cc < ol[1] { dc[cc] = out[ol[0] + cc]; cc = cc + 1 } 94 if capt_verify(secret, slen, dc, ol[1], "nx_a" as *u8, 4, 2000) == CAPT_DENY_EXP { t4 = 1 } 95 } 96 ig_mark(t4, p, t, "Iss4 delegate exp > parent -> CLAMPED to parent (delegated cap EXPIRED at now=2000, not extended)" as *u8) 97 98 gw("\n=== nx_cap_issue_gate " as *u8); gn(p[0]); gw("/" as *u8); gn(t[0]); gw(" ===\n" as *u8) 99 if p[0] == t[0] { gw("CAP-ISSUE GREEN -- delegation narrows, widening + forgery refused (ocap delegation chain, no ambient identity)\n" as *u8); sys_exit(0); return 0 } 100 gw("CAP-ISSUE RED\n" as *u8); sys_exit(1); return 1 101}