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}