code wiki / _hdl_build / nx_cwdguard.nx

nx_cwdguard.nx source

↩ module page · 240 lines · 10924 B

1// nx_cwdguard.nx -- THE STANDING GUARD for the CWD-DEPENDENT-VERDICT class (debt 1785879363). 2// 3// WHAT BIT US (measured 2026-08-04, three separate organs in one session): 4// * nx_swarm_endpoint_lib read knowledge/swarm_nodes.conf relative; the gen daemon runs with 5// CWD=/volume1/ai/gen, so the SSOT silently missed and gen dispatched at a DEAD GPU address. 6// * nx_writebench printed verdict=GREEN coverage=553 from buildroot and result=LIAR 7// claimed-artifacts-missing=8 from nishihost -- the tools-daemon CWD, i.e. EVERY MCP call. 8// * nx_law_warden returned RED "law plane unseeded" and nx_sota_status reported an EMPTY estate 9// (no proven domains at all) purely because of the directory they were launched from. 10// ★★★★★★A VERDICT THAT CHANGES WITH THE CALLER'S WORKING DIRECTORY IS NOT A MEASUREMENT. 11// 12// ★WHY THIS DETECTOR IS STATIC, NOT A DIFFER. The obvious guard -- run each tool from two 13// directories and compare -- is WRONG HERE, and I proved it on myself: comparing output md5 flagged 14// nx_barcheck (a TLS bench whose ms= timings vary per run) and nx_frontier_watch (which APPENDS a 15// row per run, so its base row advances every time) as CWD-fragile when NEITHER IS. It also would 16// EXECUTE mutating organs twice per sweep just to look at them. So this guard reads SOURCE: 17// an organ is AT RISK when it opens an estate path RELATIVE and carries no anchor. That is cheap, 18// deterministic, side-effect-free, and has no false positives from clocks or counters. 19// ⚠HONEST ENVELOPE: at-risk is a RISK, not a proven defect -- an organ whose subject genuinely IS 20// "whatever tree I was pointed at" is CORRECT to read relative. This names candidates for a human 21// or a follow-up differ to adjudicate; it must never be read as a list of confirmed bugs. 22// 23// nx_cwdguard -- scan, print the at-risk roster + verdict 24// nx_cwdguard selftest -- teeth, incl. the NEGATIVE control (an anchored organ is NOT flagged) 25// license_tier: ORIGINAL expect_exit: 0 26// module: nishi-core.estate.cwdguard 27import "nx_syscalls.nx" 28import "nx_estate_path.nx" 29 30const CG_SCRATCH: i64 = 1048576 31const CG_MAXTOOLS: i64 = 2048 32const CG_NAMECAP: i64 = 64 33 34func cg_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 35func cg_n(v: i64) -> i64 { 36 let t: *u8 = sys_mmap(32); let b: *u8 = sys_mmap(32) 37 var m: i64 = v; var k: i64 = 0 38 if m == 0 { t[0] = 48 as u8; k = 1 } 39 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 40 var i: i64 = 0 41 while i < k { b[i] = t[k - 1 - i]; i = i + 1 } 42 sys_write(1, b, k); return 0 43} 44 45// read a whole file via the CWD-proof resolver (this guard must not be fragile in the way it detects) 46func cg_slurp(path: *u8, buf: *u8, cap: i64) -> i64 { 47 let fd: i64 = ep_open_rd(path) 48 if fd < 0 { return 0 - 1 } 49 var t: i64 = 0 50 var r: i64 = 1 51 while r > 0 { 52 if t >= cap { r = 0 } else { 53 r = sys_read(fd, ((buf as i64) + t) as *u8, cap - t) 54 if r > 0 { t = t + r } 55 } 56 } 57 sys_close(fd) 58 return t 59} 60 61func cg_has(buf: *u8, n: i64, needle: *u8) -> i64 { 62 var m: i64 = 0 63 while needle[m] != (0 as u8) { m = m + 1 } 64 if m == 0 { return 0 } 65 if m > n { return 0 } 66 var i: i64 = 0 67 while i <= n - m { 68 var j: i64 = 0 69 var same: i64 = 1 70 while j < m { if buf[i + j] != needle[j] { same = 0; j = m } else { j = j + 1 } } 71 if same == 1 { return 1 } 72 i = i + 1 73 } 74 return 0 75} 76 77// Does this source read an ESTATE path relatively? Any of the known open/read primitives applied to 78// a bare "knowledge/..." literal. (A leading '/' would be absolute and is not a risk.) 79func cg_reads_relative(buf: *u8, n: i64) -> i64 { 80 if cg_has(buf, n, "sys_openat_rd(\"knowledge/" as *u8) == 1 { return 1 } 81 if cg_has(buf, n, "sys_read_file(\"knowledge/" as *u8) == 1 { return 1 } 82 if cg_has(buf, n, "slurp(\"knowledge/" as *u8) == 1 { return 1 } 83 return 0 84} 85 86// Is it anchored / already CWD-proof? Either binding to nx_estate_path, or doing its own chdir. 87func cg_anchored(buf: *u8, n: i64) -> i64 { 88 if cg_has(buf, n, "ep_anchor" as *u8) == 1 { return 1 } 89 if cg_has(buf, n, "ep_open_rd" as *u8) == 1 { return 1 } 90 if cg_has(buf, n, "sys_chdir" as *u8) == 1 { return 1 } 91 return 0 92} 93 94// copy field 1 (tab-separated) of the line starting at off into name; returns length (0 = skip row) 95func cg_toolname(buf: *u8, off: i64, end: i64, name: *u8) -> i64 { 96 if off >= end { return 0 } 97 if buf[off] == (35 as u8) { return 0 } 98 var i: i64 = off 99 var k: i64 = 0 100 while i < end { 101 let c: i64 = buf[i] & 0xff 102 if c == 9 { i = end } else { 103 if k < CG_NAMECAP - 1 { name[k] = buf[i]; k = k + 1 } 104 i = i + 1 105 } 106 } 107 name[k] = 0 as u8 108 return k 109} 110 111// try runtime/<name>.nx then runtime/_hdl_build/<name>.nx; returns bytes read (or -1) 112func cg_load_source(name: *u8, nl: i64, buf: *u8) -> i64 { 113 let p: *u8 = sys_mmap(256) 114 var o: i64 = 0 115 let pre: *u8 = "buildroot/runtime/" as *u8 116 while pre[o] != (0 as u8) { p[o] = pre[o]; o = o + 1 } 117 var i: i64 = 0 118 while i < nl { p[o + i] = name[i]; i = i + 1 } 119 p[o + nl] = 46 as u8; p[o + nl + 1] = 110 as u8; p[o + nl + 2] = 120 as u8; p[o + nl + 3] = 0 as u8 120 var r: i64 = cg_slurp(p, buf, CG_SCRATCH) 121 if r > 0 { return r } 122 let p2: *u8 = sys_mmap(256) 123 var o2: i64 = 0 124 let pre2: *u8 = "buildroot/runtime/_hdl_build/" as *u8 125 while pre2[o2] != (0 as u8) { p2[o2] = pre2[o2]; o2 = o2 + 1 } 126 i = 0 127 while i < nl { p2[o2 + i] = name[i]; i = i + 1 } 128 p2[o2 + nl] = 46 as u8; p2[o2 + nl + 1] = 110 as u8; p2[o2 + nl + 2] = 120 as u8; p2[o2 + nl + 3] = 0 as u8 129 return cg_slurp(p2, buf, CG_SCRATCH) 130} 131 132func cg_scan() -> i64 { 133 ep_anchor() 134 let reg: *u8 = sys_mmap(CG_SCRATCH) 135 let rn: i64 = cg_slurp("tool_allowlist.conf" as *u8, reg, CG_SCRATCH) 136 if rn <= 0 { 137 cg_w("NX-CWDGUARD RED -- tool_allowlist.conf unreadable (fail-closed: no roster, no verdict)\n" as *u8) 138 return 1 139 } 140 let src: *u8 = sys_mmap(CG_SCRATCH) 141 let name: *u8 = sys_mmap(CG_NAMECAP) 142 var scanned: i64 = 0 143 var nosrc: i64 = 0 144 var atrisk: i64 = 0 145 var safe: i64 = 0 146 cg_w("=== NX-CWDGUARD: organs whose VERDICT could depend on the caller's working directory ===\n" as *u8) 147 cg_w("at-risk = reads a relative knowledge/ path AND carries no anchor. A RISK, not a proven defect.\n" as *u8) 148 var p: i64 = 0 149 var rows: i64 = 0 150 while p < rn { 151 // ⚠THE POSITION MUST SURVIVE THE SEARCH. My first version terminated the scan with 152 // `q = rn + 1` on finding the newline, which DESTROYED the very index it had just found -- 153 // eol became rn, every row read as one giant line, and the guard reported 154 // registry_rows=1 ... at_risk=0 verdict=GREEN over a 773-row registry. A VACUOUS GREEN. 155 // Caught only because the row COUNT is printed: ★★★★★A PARSER THAT LOSES THE POSITION 156 // REPORTS SUCCESS AND MEANS NOTHING -- print parsed-row counts, and read them. 157 var q: i64 = p 158 var eol: i64 = rn 159 var go: i64 = 1 160 while go == 1 { 161 if q >= rn { eol = rn; go = 0 } 162 else { if reg[q] == (10 as u8) { eol = q; go = 0 } else { q = q + 1 } } 163 } 164 if eol > p { if rows < CG_MAXTOOLS { 165 let nl: i64 = cg_toolname(reg, p, eol, name) 166 if nl > 0 { 167 rows = rows + 1 168 let sn: i64 = cg_load_source(name, nl, src) 169 if sn <= 0 { nosrc = nosrc + 1 } else { 170 scanned = scanned + 1 171 if cg_reads_relative(src, sn) == 1 { 172 if cg_anchored(src, sn) == 1 { safe = safe + 1 } else { 173 atrisk = atrisk + 1 174 cg_w(" AT-RISK " as *u8); sys_write(1, name, nl); cg_w("\n" as *u8) 175 } 176 } else { safe = safe + 1 } 177 } 178 } 179 } } 180 p = eol + 1 181 } 182 cg_w("registry_rows=" as *u8); cg_n(rows) 183 cg_w(" source_found=" as *u8); cg_n(scanned) 184 cg_w(" source_missing=" as *u8); cg_n(nosrc) 185 cg_w(" at_risk=" as *u8); cg_n(atrisk) 186 cg_w(" cwd_proof_or_absolute=" as *u8); cg_n(safe) 187 cg_w("\nenvelope: source_missing rows are UNJUDGED (an elf whose .nx is not in the buildroot cannot be\n" as *u8) 188 cg_w("read) -- they are printed as a count, never folded into safe. Coverage is scanned/rows.\n" as *u8) 189 if atrisk == 0 { cg_w("NX-CWDGUARD GREEN -- no registered organ reads an estate path relative without an anchor\n" as *u8); return 0 } 190 cg_w("NX-CWDGUARD FINDINGS -- adjudicate each: anchor it, or confirm the CWD is genuinely its input\n" as *u8) 191 return 0 192} 193 194// Teeth. The negative control is the one that matters: a detector that flags everything is useless. 195func cg_selftest() -> i64 { 196 var pass: i64 = 0 197 var total: i64 = 0 198 let a: *u8 = "let f = sys_read_file(\"knowledge/status/x.log\") // no anchor here\x00" as *u8 199 var an: i64 = 0 200 while a[an] != (0 as u8) { an = an + 1 } 201 total = total + 1 202 if cg_reads_relative(a, an) == 1 { if cg_anchored(a, an) == 0 { pass = pass + 1; cg_w("T1 relative+unanchored -> AT-RISK OK\n" as *u8) } } 203 204 let b: *u8 = "ep_anchor()\nlet f = sys_read_file(\"knowledge/status/x.log\")\x00" as *u8 205 var bn: i64 = 0 206 while b[bn] != (0 as u8) { bn = bn + 1 } 207 total = total + 1 208 if cg_anchored(b, bn) == 1 { pass = pass + 1; cg_w("T2 NEG-CONTROL anchored -> NOT flagged OK\n" as *u8) } 209 210 let c: *u8 = "let f = sys_read_file(\"/volume1/homes/elderwesto/nishihost/knowledge/x\")\x00" as *u8 211 var cn: i64 = 0 212 while c[cn] != (0 as u8) { cn = cn + 1 } 213 total = total + 1 214 if cg_reads_relative(c, cn) == 0 { pass = pass + 1; cg_w("T3 NEG-CONTROL absolute path -> NOT flagged OK\n" as *u8) } 215 216 let d: *u8 = "let f = ep_open_rd(\"knowledge/status/x.log\")\x00" as *u8 217 var dn: i64 = 0 218 while d[dn] != (0 as u8) { dn = dn + 1 } 219 total = total + 1 220 if cg_anchored(d, dn) == 1 { pass = pass + 1; cg_w("T4 NEG-CONTROL ep_open_rd -> NOT flagged OK\n" as *u8) } 221 222 let e: *u8 = "no estate reads at all, pure integer organ\x00" as *u8 223 var en: i64 = 0 224 while e[en] != (0 as u8) { en = en + 1 } 225 total = total + 1 226 if cg_reads_relative(e, en) == 0 { pass = pass + 1; cg_w("T5 NEG-CONTROL no estate read -> NOT flagged OK\n" as *u8) } 227 228 cg_w("CWDGUARD-SELFTEST " as *u8); cg_n(pass); cg_w("/" as *u8); cg_n(total) 229 if pass == total { cg_w(" verdict=GREEN\n" as *u8); return 0 } 230 cg_w(" verdict=RED\n" as *u8) 231 return 1 232} 233 234func main(argc: i64, argv: *i64) -> i64 { 235 if argc >= 2 { 236 let v: *u8 = argv[1] as *u8 237 if v[0] == (115 as u8) { return cg_selftest() } 238 } 239 return cg_scan() 240}