code wiki / _hdl_build / nx_input_scan.nx

nx_input_scan.nx source

↩ module page · 146 lines · 6145 B

1// nx_input_scan.nx -- INPUT-INTEGRITY scanner (first control of the 3-stage untrusted-input fence, seq497). 2// PRE-submit + POST-audit: reads a plane's text column, scans each value (case-insensitive) for 3// prompt-injection / malicious markers, and emits findings (id TAB pattern TAB value-excerpt) to an out 4// plane. verdict=GREEN (clean) or RED (>=1 finding). Generic (any plane/col). Deny-by-default posture: 5// a RED here BLOCKS admission. SUBCLASS of nx_ingest_base. No hw writes (Rule 26). expect_exit: 0 6// argv: <plane> <col> <out-findings-plane> 7import "nx_ingest_base.nx" 8import "nx_store_seed_lib.nx" 9import "nx_syscalls.nx" 10 11const IS_CAP: i64 = 4194304 12const IS_OCAP: i64 = 262144 13const IS_TAB: i64 = 9 14const IS_NL: i64 = 10 15const IS_STDERR: i64 = 2 16const IS_MAXCOL: i64 = 16 17const IS_PAIR: i64 = 2 18const IS_SPB: i64 = 256 19const IS_VCAP: i64 = 4096 20const IS_UA: i64 = 65 21const IS_UZ: i64 = 90 22const IS_CASE: i64 = 32 23const IS_ARGC_MIN: i64 = 4 24const IS_D0: i64 = 48 25const IS_D9: i64 = 57 26 27static g_out: *u8 28static g_o: i64 29static g_hits: i64 30 31func is_atoi(s: *u8) -> i64 { 32 var v: i64 = 0 33 var i: i64 = 0 34 while s[i] != (0 as u8) { let c: i64 = s[i] as i64; if c >= IS_D0 { if c <= IS_D9 { v = v * 10 + (c - IS_D0) } } i = i + 1 } 35 return v 36} 37func is_cols(q: *u8, ls: i64, le: i64, sp: *i64) -> i64 { 38 var c: i64 = 0 39 var p: i64 = ls 40 while c < IS_MAXCOL { 41 var e: i64 = p 42 var s: i64 = 1 43 while s == 1 { if e >= le { s = 0 } else { if q[e] == (IS_TAB as u8) { s = 0 } else { e = e + 1 } } } 44 sp[c*IS_PAIR] = p 45 sp[c*IS_PAIR+1] = e 46 c = c + 1 47 if e >= le { return c } 48 p = e + 1 49 } 50 return c 51} 52func is_lower(dst: *u8, q: *u8, a: i64, b: i64) -> i64 { 53 var k: i64 = 0 54 var i: i64 = a 55 while i < b { if k < IS_VCAP - 1 { var c: i64 = q[i] as i64; if c >= IS_UA { if c <= IS_UZ { c = c + IS_CASE } } dst[k] = c as u8; k = k + 1 } i = i + 1 } 56 dst[k] = 0 as u8 57 return k 58} 59func is_emit(s: *u8) -> i64 { var j: i64 = 0; while s[j] != (0 as u8) { if g_o < IS_OCAP - 2 { g_out[g_o] = s[j]; g_o = g_o + 1 } j = j + 1 } return 0 } 60func is_emitc(c: i64) -> i64 { if g_o < IS_OCAP - 2 { g_out[g_o] = c as u8; g_o = g_o + 1 } return 0 } 61func is_emit_slice(q: *u8, a: i64, b: i64) -> i64 { var i: i64 = a; while i < b { if g_o < IS_OCAP - 2 { g_out[g_o] = q[i]; g_o = g_o + 1 } i = i + 1 } return 0 } 62// if lval contains pat, record a finding (idslice + pat + value-excerpt) and return 1 63func is_check(lval: *u8, ln: i64, pat: *u8, plane: *u8, ids: i64, ide: i64, vs: i64, ve: i64) -> i64 { 64 if ib_find(lval, ln, pat, 0) >= 0 { 65 is_emit_slice(plane, ids, ide) 66 is_emitc(IS_TAB) 67 is_emit(pat) 68 is_emitc(IS_TAB) 69 var ee: i64 = ve 70 if ee - vs > 120 { ee = vs + 120 } 71 is_emit_slice(plane, vs, ee) 72 is_emitc(IS_NL) 73 g_hits = g_hits + 1 74 return 1 75 } 76 return 0 77} 78 79func main(argc: i64, argv: *i64) -> i64 { 80 if argc < IS_ARGC_MIN { 81 ib_refuse("INPUT-SCAN" as *u8, "missing args <plane> <col> <out-findings-plane>" as *u8, "seed a plan row: 1 TAB nx_input_scan TAB <plane> TAB <col> TAB <out-plane>" as *u8) 82 sys_exit(2) 83 return 2 84 } 85 let plane: *u8 = argv[1] as *u8 86 let col: i64 = is_atoi(argv[2] as *u8) 87 let outp: *u8 = argv[3] as *u8 88 let buf: *u8 = sys_mmap(IS_CAP) 89 let n: i64 = sts_load(plane, buf, IS_CAP) 90 if n <= 0 { ib_refuse("INPUT-SCAN" as *u8, "plane EMPTY" as *u8, "verify the plane prefix is a full knowledge/store/ path" as *u8); sys_exit(1); return 1 } 91 g_out = sys_mmap(IS_OCAP) 92 g_o = 0 93 g_hits = 0 94 let sp: *i64 = sys_mmap(IS_SPB) as *i64 95 let lval: *u8 = sys_mmap(IS_VCAP) 96 var rows: i64 = 0 97 var i: i64 = 0 98 while i < n { 99 var le: i64 = i 100 var s: i64 = 1 101 while s == 1 { if le >= n { s = 0 } else { if buf[le] == (IS_NL as u8) { s = 0 } else { le = le + 1 } } } 102 if le > i { 103 let nc: i64 = is_cols(buf, i, le, sp) 104 if col < nc { 105 let vs: i64 = sp[col*IS_PAIR] 106 let ve: i64 = sp[col*IS_PAIR+1] 107 let ln: i64 = is_lower(lval, buf, vs, ve) 108 let ids: i64 = sp[0] 109 let ide: i64 = sp[1] 110 is_check(lval, ln, "ignore previous" as *u8, buf, ids, ide, vs, ve) 111 is_check(lval, ln, "ignore all" as *u8, buf, ids, ide, vs, ve) 112 is_check(lval, ln, "disregard" as *u8, buf, ids, ide, vs, ve) 113 is_check(lval, ln, "you are now" as *u8, buf, ids, ide, vs, ve) 114 is_check(lval, ln, "system prompt" as *u8, buf, ids, ide, vs, ve) 115 is_check(lval, ln, "new instructions" as *u8, buf, ids, ide, vs, ve) 116 is_check(lval, ln, "as an ai" as *u8, buf, ids, ide, vs, ve) 117 is_check(lval, ln, "jailbreak" as *u8, buf, ids, ide, vs, ve) 118 is_check(lval, ln, "<script" as *u8, buf, ids, ide, vs, ve) 119 is_check(lval, ln, "javascript:" as *u8, buf, ids, ide, vs, ve) 120 is_check(lval, ln, "rm -rf" as *u8, buf, ids, ide, vs, ve) 121 is_check(lval, ln, "/etc/passwd" as *u8, buf, ids, ide, vs, ve) 122 is_check(lval, ln, "base64 -d" as *u8, buf, ids, ide, vs, ve) 123 rows = rows + 1 124 } 125 } 126 i = le + 1 127 } 128 if g_hits > 0 { 129 let rc: i64 = sts_seed(outp, g_out, g_o) 130 if rc < 0 { ib_refuse("INPUT-SCAN" as *u8, "findings commit failed" as *u8, "check seg-store for the out plane" as *u8); sys_exit(1); return 1 } 131 ib_werr("INPUT-SCAN verdict=RED rows=" as *u8) 132 ib_wn(IS_STDERR, rows) 133 ib_werr(" findings=" as *u8) 134 ib_wn(IS_STDERR, g_hits) 135 ib_werr(" (INJECTION MARKERS PRESENT -> BLOCK admission; see " as *u8) 136 ib_werr(outp) 137 ib_werr(")\n" as *u8) 138 sys_exit(3) 139 return 3 140 } 141 ib_werr("INPUT-SCAN verdict=GREEN rows=" as *u8) 142 ib_wn(IS_STDERR, rows) 143 ib_werr(" findings=0 (no injection/malicious markers in the scanned column -- clean)\n" as *u8) 144 sys_exit(0) 145 return 0 146}