code wiki / _hdl_build / nx_adnet_selfserve_gate.nx
nx_adnet_selfserve_gate.nx source
↩ module page · 155 lines · 7498 B
1// nx_adnet_selfserve_gate.nx -- GATE for self-serve advertiser intake (nx_adnet_selfserve). Proves:
2// valid submission accepted + persisted (read-back) to the STAGED journal; malicious rows (third-party
3// img, javascript: click, bad id, directive smuggling) REFUSED and NOT persisted; STAGED IS NOT LIVE
4// (the live inventory stays untouched by submit -- the load-bearing negative control); operator approve
5// re-validates and appends to live; the anti-snoop detector FIRES on a planted visitor token.
6// expect_exit: 0 license_tier: ORIGINAL
7import "nx_syscalls.nx"
8import "_hdl_build/nx_adnet_selfserve.nx"
9import "nx_gate_verdict.nx"
10
11func sg_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
12func sg_putn(v: i64) -> i64 { var m: i64 = v; if m < 0 { sg_puts("-" as *u8); m = 0 - m } let t: *u8 = sys_mmap(24); var k: i64 = 0; 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 } let o: *u8 = sys_mmap(24); var i: i64 = 0; while i < k { o[i] = t[k - 1 - i]; i = i + 1 } sys_write(1, o, k); return 0 }
13func sg_cat(dst: *u8, off: i64, s: *u8) -> i64 { var o: i64 = off; var i: i64 = 0; while s[i] != (0 as u8) { dst[o] = s[i]; o = o + 1; i = i + 1 } return o }
14func sg_tab(dst: *u8, off: i64) -> i64 { dst[off] = 9 as u8; return off + 1 }
15
16func sg_has(hay: *u8, n: i64, needle: *u8) -> i64 {
17 var nl: i64 = 0
18 while needle[nl] != (0 as u8) { nl = nl + 1 }
19 if nl == 0 { return 0 }
20 var i: i64 = 0
21 while i + nl <= n {
22 var j: i64 = 0
23 var eq: i64 = 1
24 while j < nl { if hay[i + j] != needle[j] { eq = 0; break } j = j + 1 }
25 if eq == 1 { return 1 }
26 i = i + 1
27 }
28 return 0
29}
30
31func sg_row6(dst: *u8, f0: *u8, f1: *u8, f2: *u8, f3: *u8, f4: *u8, f5: *u8) -> i64 {
32 var o: i64 = 0
33 o = sg_cat(dst, o, f0)
34 o = sg_tab(dst, o)
35 o = sg_cat(dst, o, f1)
36 o = sg_tab(dst, o)
37 o = sg_cat(dst, o, f2)
38 o = sg_tab(dst, o)
39 o = sg_cat(dst, o, f3)
40 o = sg_tab(dst, o)
41 o = sg_cat(dst, o, f4)
42 o = sg_tab(dst, o)
43 o = sg_cat(dst, o, f5)
44 return o
45}
46
47func sg_readn(path: *u8, box: *i64) -> *u8 {
48 box[0] = 0
49 let p: *u8 = sys_read_file(path, box)
50 return p
51}
52
53func main() -> i64 {
54 sg_puts("=== nx_adnet_selfserve_gate ===\n" as *u8)
55 var pass: i64 = 0
56 var fail: i64 = 0
57
58 let subs: *u8 = "/tmp/adnet_subs_test.log" as *u8
59 let inv: *u8 = "/tmp/adnet_inv_test.conf" as *u8
60 let f1: i64 = sys_openat_wr(subs, 0x1A4)
61 if f1 >= 0 { sys_close(f1) }
62 let f2: i64 = sys_openat_wr(inv, 0x1A4)
63 if f2 >= 0 { sys_close(f2) }
64
65 let good: *u8 = sys_mmap(1024)
66 let gn: i64 = sg_row6(good, "n1" as *u8, "NewCo" as *u8, "/adnet/n1.png" as *u8, "https://example.com/n1" as *u8, "home" as *u8, "1" as *u8)
67 let badimg: *u8 = sys_mmap(1024)
68 let bin: i64 = sg_row6(badimg, "b1" as *u8, "EvilImgCo" as *u8, "https://evil.example/x.png" as *u8, "https://example.com/b" as *u8, "home" as *u8, "1" as *u8)
69 let badclk: *u8 = sys_mmap(1024)
70 let bcn: i64 = sg_row6(badclk, "b2" as *u8, "EvilClkCo" as *u8, "/adnet/b2.png" as *u8, "javascript:alert(1)" as *u8, "home" as *u8, "1" as *u8)
71 let badid: *u8 = sys_mmap(1024)
72 let bdn: i64 = sg_row6(badid, "a b" as *u8, "BadIdCo" as *u8, "/adnet/b3.png" as *u8, "/x" as *u8, "home" as *u8, "1" as *u8)
73 let baddir: *u8 = sys_mmap(1024)
74 let bxn: i64 = sg_row6(baddir, "@host" as *u8, "smuggled.example" as *u8, "/x.png" as *u8, "/x" as *u8, "home" as *u8, "1" as *u8)
75
76 // T1 valid submit accepted + persisted
77 let r1: i64 = ass_submit(subs, good, gn)
78 let box: *i64 = (sys_mmap(8)) as *i64
79 let back1: *u8 = sg_readn(subs, box)
80 var t1: i64 = 1
81 if r1 != 1 { t1 = 0 }
82 if (back1 as i64) == 0 { t1 = 0 } else { if sg_has(back1, box[0], "n1" as *u8) == 0 { t1 = 0 } }
83 if t1 == 1 { pass = pass + 1 } else { fail = fail + 1; sg_puts("T1 FAIL valid submit\n" as *u8) }
84
85 // T2 malicious rows REFUSED + NOT persisted
86 var t2: i64 = 1
87 if ass_submit(subs, badimg, bin) != 0 { t2 = 0 }
88 if ass_submit(subs, badclk, bcn) != 0 { t2 = 0 }
89 if ass_submit(subs, badid, bdn) != 0 { t2 = 0 }
90 if ass_submit(subs, baddir, bxn) != 0 { t2 = 0 }
91 let back2: *u8 = sg_readn(subs, box)
92 if (back2 as i64) != 0 {
93 if sg_has(back2, box[0], "EvilImgCo" as *u8) == 1 { t2 = 0 }
94 if sg_has(back2, box[0], "EvilClkCo" as *u8) == 1 { t2 = 0 }
95 if sg_has(back2, box[0], "BadIdCo" as *u8) == 1 { t2 = 0 }
96 if sg_has(back2, box[0], "smuggled.example" as *u8) == 1 { t2 = 0 }
97 }
98 if t2 == 1 { pass = pass + 1 } else { fail = fail + 1; sg_puts("T2 FAIL refusals\n" as *u8) }
99
100 // T3 STAGED IS NOT LIVE: the live inventory stays empty after submits (negative control)
101 let back3: *u8 = sg_readn(inv, box)
102 var t3: i64 = 1
103 if (back3 as i64) != 0 { if box[0] > 0 { if sg_has(back3, box[0], "n1" as *u8) == 1 { t3 = 0 } } }
104 if t3 == 1 { pass = pass + 1 } else { fail = fail + 1; sg_puts("T3 FAIL staged leaked live\n" as *u8) }
105
106 // T4 operator approve -> live; invalid approve refused
107 var t4: i64 = 1
108 if ass_approve(inv, good, gn) != 1 { t4 = 0 }
109 let back4: *u8 = sg_readn(inv, box)
110 if (back4 as i64) == 0 { t4 = 0 } else { if sg_has(back4, box[0], "n1" as *u8) == 0 { t4 = 0 } }
111 if ass_approve(inv, badclk, bcn) != 0 { t4 = 0 }
112 let back5: *u8 = sg_readn(inv, box)
113 if (back5 as i64) != 0 { if sg_has(back5, box[0], "EvilClkCo" as *u8) == 1 { t4 = 0 } }
114 if t4 == 1 { pass = pass + 1 } else { fail = fail + 1; sg_puts("T4 FAIL approve\n" as *u8) }
115
116 // T5 anti-snoop detector: clean journal scans 0, then FIRES on a planted visitor token
117 var t5: i64 = 1
118 let back6: *u8 = sg_readn(subs, box)
119 if (back6 as i64) == 0 { t5 = 0 } else { if ass_snoop_scan(back6, box[0]) != 0 { t5 = 0 } }
120 let pfd: i64 = sys_openat_append(subs, 420)
121 if pfd >= 0 {
122 let planted: *u8 = "VISITOR-TOKEN-XYZ" as *u8
123 var pl: i64 = 0
124 while planted[pl] != (0 as u8) { pl = pl + 1 }
125 sys_write(pfd, planted, pl)
126 sys_close(pfd)
127 }
128 let back7: *u8 = sg_readn(subs, box)
129 if (back7 as i64) == 0 { t5 = 0 } else { if ass_snoop_scan(back7, box[0]) != 1 { t5 = 0 } }
130 if t5 == 1 { pass = pass + 1 } else { fail = fail + 1; sg_puts("T5 FAIL anti-snoop detector\n" as *u8) }
131
132 sg_puts("pass=" as *u8)
133 sg_putn(pass)
134 sg_puts(" fail=" as *u8)
135 sg_putn(fail)
136 sg_puts("\n" as *u8)
137
138 let log2: *u8 = sys_mmap(256)
139 var lo: i64 = 0
140 if fail == 0 { lo = sg_cat(log2, lo, "ADNETSELFSERVE authored=organ verdict=GREEN" as *u8) } else { lo = sg_cat(log2, lo, "ADNETSELFSERVE authored=organ verdict=RED" as *u8) }
141 log2[lo] = 10 as u8
142 lo = lo + 1
143 let fd: i64 = sys_openat_wr("knowledge/status/adnet_selfserve.log" as *u8, 0x1A4)
144 if fd >= 0 { sys_write(fd, log2, lo); sys_close(fd) }
145
146 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
147 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
148 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
149 let ctr__dry: *i64 = gv_ctr()
150 ctr__dry[0] = pass
151 ctr__dry[1] = pass + fail
152 let rc__dry: i64 = gv_verdict("ADNET-SELFSERVE-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
153 sys_exit(rc__dry)
154 return rc__dry
155}