code wiki / _hdl_build / nx_adnet_slot_gate.nx
nx_adnet_slot_gate.nx source
↩ module page · 203 lines · 10925 B
1// nx_adnet_slot_gate.nx -- GATE for the universal ad slot lib (nx_adnet_slot). Proves: section derive,
2// FAIL-CLOSED host directive, rotation pick, honest labeled render, ESCAPE + first-party-only validation
3// (planted <script advertiser stays escaped; third-party img and javascript: click rows are DROPPED),
4// any-section fallback, first-party click 302 (unknown/invalid id -> /), and that the forbidden-byte
5// detectors FIRE on planted vectors (anti-false-green). Zero visitor identity anywhere.
6// expect_exit: 0 license_tier: ORIGINAL
7import "nx_syscalls.nx"
8import "nx_g_puts_lib.nx"
9import "_hdl_build/nx_adnet_slot.nx"
10import "nx_gate_verdict.nx"
11
12func g_putn(v: i64) -> i64 { var m: i64 = v; if m < 0 { g_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 }
13
14func g_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 }
15func g_tab(dst: *u8, off: i64) -> i64 { dst[off] = 9 as u8; return off + 1 }
16func g_nl(dst: *u8, off: i64) -> i64 { dst[off] = 10 as u8; return off + 1 }
17
18// substring scan: 1 if needle (NUL-terminated) occurs in hay[0..n)
19func g_has(hay: *u8, n: i64, needle: *u8) -> i64 {
20 var nl: i64 = 0
21 while needle[nl] != (0 as u8) { nl = nl + 1 }
22 if nl == 0 { return 0 }
23 var i: i64 = 0
24 while i + nl <= n {
25 var j: i64 = 0
26 var eq: i64 = 1
27 while j < nl { if hay[i + j] != needle[j] { eq = 0; break } j = j + 1 }
28 if eq == 1 { return 1 }
29 i = i + 1
30 }
31 return 0
32}
33
34func g_row6(dst: *u8, off: i64, f0: *u8, f1: *u8, f2: *u8, f3: *u8, f4: *u8, f5: *u8) -> i64 {
35 var o: i64 = off
36 o = g_cat(dst, o, f0)
37 o = g_tab(dst, o)
38 o = g_cat(dst, o, f1)
39 o = g_tab(dst, o)
40 o = g_cat(dst, o, f2)
41 o = g_tab(dst, o)
42 o = g_cat(dst, o, f3)
43 o = g_tab(dst, o)
44 o = g_cat(dst, o, f4)
45 o = g_tab(dst, o)
46 o = g_cat(dst, o, f5)
47 o = g_nl(dst, o)
48 return o
49}
50
51func main() -> i64 {
52 g_puts("=== nx_adnet_slot_gate ===\n" as *u8)
53 var pass: i64 = 0
54 var fail: i64 = 0
55
56 // ---- build the test inventory (programmatic tabs/newlines; no escape dependence) ----
57 let inv: *u8 = sys_mmap(8192)
58 var n: i64 = 0
59 n = g_cat(inv, n, "@host" as *u8)
60 n = g_tab(inv, n)
61 n = g_cat(inv, n, "nishifamily.com" as *u8)
62 n = g_nl(inv, n)
63 n = g_row6(inv, n, "h1" as *u8, "HomeCo" as *u8, "/adnet/h1.png" as *u8, "https://example.com/h1" as *u8, "home" as *u8, "1" as *u8)
64 n = g_row6(inv, n, "h2" as *u8, "OtherCo" as *u8, "/adnet/h2.png" as *u8, "/torrent" as *u8, "home" as *u8, "1" as *u8)
65 n = g_row6(inv, n, "v1" as *u8, "VidCo" as *u8, "/adnet/v1.png" as *u8, "https://example.com/v1" as *u8, "video" as *u8, "1" as *u8)
66 n = g_row6(inv, n, "evil" as *u8, "<script>alert(1)</script>" as *u8, "/adnet/e.png" as *u8, "https://example.com/e" as *u8, "esc" as *u8, "1" as *u8)
67 n = g_row6(inv, n, "bad1" as *u8, "EvilImg" as *u8, "https://evil.example/x.png" as *u8, "https://example.com/b" as *u8, "badimg" as *u8, "1" as *u8)
68 n = g_row6(inv, n, "bad2" as *u8, "EvilClick" as *u8, "/adnet/b2.png" as *u8, "javascript:alert(1)" as *u8, "badclick" as *u8, "1" as *u8)
69 n = g_row6(inv, n, "fb" as *u8, "FallbackCo" as *u8, "/adnet/fb.png" as *u8, "/library" as *u8, "any" as *u8, "1" as *u8)
70
71 // ---- T1 section derive ----
72 let sec: *u8 = sys_mmap(128)
73 aslot_section_of("/" as *u8, 1, sec, 128)
74 if ad_streq(sec, "home" as *u8) == 1 { pass = pass + 1 } else { fail = fail + 1; g_puts("T1a FAIL root section\n" as *u8) }
75 aslot_section_of("/video/index.html" as *u8, 17, sec, 128)
76 if ad_streq(sec, "video" as *u8) == 1 { pass = pass + 1 } else { fail = fail + 1; g_puts("T1b FAIL video section\n" as *u8) }
77 aslot_section_of("/compare/llm" as *u8, 12, sec, 128)
78 if ad_streq(sec, "compare" as *u8) == 1 { pass = pass + 1 } else { fail = fail + 1; g_puts("T1c FAIL compare section\n" as *u8) }
79
80 // ---- T2 host directive FAIL-CLOSED ----
81 let hok1: i64 = aslot_host_ok(inv, n, "nishifamily.com" as *u8)
82 if hok1 == 1 { pass = pass + 1 } else { fail = fail + 1; g_puts("T2a FAIL enabled host\n" as *u8) }
83 let hok2: i64 = aslot_host_ok(inv, n, "andelinwest.com" as *u8)
84 if hok2 == 0 { pass = pass + 1 } else { fail = fail + 1; g_puts("T2b FAIL non-enabled host\n" as *u8) }
85 let noinv: *u8 = sys_mmap(64)
86 var nn: i64 = 0
87 nn = g_row6(noinv, nn, "x" as *u8, "X" as *u8, "/x.png" as *u8, "/x" as *u8, "home" as *u8, "1" as *u8)
88 let hok3: i64 = aslot_host_ok(noinv, nn, "nishifamily.com" as *u8)
89 if hok3 == 0 { pass = pass + 1 } else { fail = fail + 1; g_puts("T2c FAIL no-directive fail-closed\n" as *u8) }
90
91 // ---- T3 rotation pick + labeled render ----
92 let out: *u8 = sys_mmap(8192)
93 let idb: *u8 = sys_mmap(128)
94 let w0: i64 = aslot_html(inv, n, "/" as *u8, 1, 0, out, 8192, idb)
95 var t3: i64 = 1
96 if w0 <= 0 { t3 = 0 }
97 if g_has(out, w0, "/ad/click/h1" as *u8) == 0 { t3 = 0 }
98 if g_has(out, w0, "BROUGHT TO YOU BY" as *u8) == 0 { t3 = 0 }
99 if g_has(out, w0, "nx-ad-slot" as *u8) == 0 { t3 = 0 }
100 if ad_streq(idb, "h1" as *u8) == 0 { t3 = 0 }
101 if t3 == 1 { pass = pass + 1 } else { fail = fail + 1; g_puts("T3a FAIL rot0 render\n" as *u8) }
102 let w1: i64 = aslot_html(inv, n, "/" as *u8, 1, 1, out, 8192, idb)
103 var t3b: i64 = 1
104 if w1 <= 0 { t3b = 0 }
105 if g_has(out, w1, "/ad/click/h2" as *u8) == 0 { t3b = 0 }
106 if ad_streq(idb, "h2" as *u8) == 0 { t3b = 0 }
107 if t3b == 1 { pass = pass + 1 } else { fail = fail + 1; g_puts("T3b FAIL rot1 render\n" as *u8) }
108 let w2: i64 = aslot_html(inv, n, "/video/index.html" as *u8, 17, 0, out, 8192, idb)
109 var t3c: i64 = 1
110 if w2 <= 0 { t3c = 0 }
111 if g_has(out, w2, "/ad/click/v1" as *u8) == 0 { t3c = 0 }
112 if t3c == 1 { pass = pass + 1 } else { fail = fail + 1; g_puts("T3c FAIL section-targeted render\n" as *u8) }
113
114 // ---- T4 escape + validation kills ----
115 let w3: i64 = aslot_html(inv, n, "/esc/x" as *u8, 6, 0, out, 8192, idb)
116 var t4: i64 = 1
117 if w3 <= 0 { t4 = 0 }
118 if g_has(out, w3, "<script" as *u8) == 0 { t4 = 0 }
119 if g_has(out, w3, "<script" as *u8) == 1 { t4 = 0 }
120 if t4 == 1 { pass = pass + 1 } else { fail = fail + 1; g_puts("T4a FAIL advertiser escape\n" as *u8) }
121 let w4: i64 = aslot_html(inv, n, "/badimg/x" as *u8, 9, 0, out, 8192, idb)
122 if w4 == 0 { pass = pass + 1 } else { fail = fail + 1; g_puts("T4b FAIL third-party img not dropped\n" as *u8) }
123 let w5: i64 = aslot_html(inv, n, "/badclick/x" as *u8, 11, 0, out, 8192, idb)
124 if w5 == 0 { pass = pass + 1 } else { fail = fail + 1; g_puts("T4c FAIL javascript click not dropped\n" as *u8) }
125
126 // ---- T5 any-section fallback ----
127 let w6: i64 = aslot_html(inv, n, "/nomatch/zone" as *u8, 13, 0, out, 8192, idb)
128 var t5: i64 = 1
129 if w6 <= 0 { t5 = 0 }
130 if g_has(out, w6, "/ad/click/fb" as *u8) == 0 { t5 = 0 }
131 if t5 == 1 { pass = pass + 1 } else { fail = fail + 1; g_puts("T5 FAIL any fallback\n" as *u8) }
132
133 // ---- T6 click responder ----
134 let cw0: i64 = aslot_click_resp(inv, n, "/ad/click/h1" as *u8, 12, out, 8192, idb)
135 var t6: i64 = 1
136 if cw0 <= 0 { t6 = 0 }
137 if g_has(out, cw0, "302 Found" as *u8) == 0 { t6 = 0 }
138 if g_has(out, cw0, "Location: https://example.com/h1" as *u8) == 0 { t6 = 0 }
139 if ad_streq(idb, "h1" as *u8) == 0 { t6 = 0 }
140 if t6 == 1 { pass = pass + 1 } else { fail = fail + 1; g_puts("T6a FAIL click resolve\n" as *u8) }
141 let cw1: i64 = aslot_click_resp(inv, n, "/ad/click/zzz" as *u8, 13, out, 8192, idb)
142 var t6b: i64 = 1
143 if cw1 <= 0 { t6b = 0 }
144 if g_has(out, cw1, "Location: /\r" as *u8) == 0 { t6b = 0 }
145 if idb[0] != (0 as u8) { t6b = 0 }
146 if t6b == 1 { pass = pass + 1 } else { fail = fail + 1; g_puts("T6b FAIL unknown id fallback\n" as *u8) }
147 let cw2: i64 = aslot_click_resp(inv, n, "/ad/click/h1%22x" as *u8, 16, out, 8192, idb)
148 var t6c: i64 = 1
149 if cw2 <= 0 { t6c = 0 }
150 if g_has(out, cw2, "Location: /\r" as *u8) == 0 { t6c = 0 }
151 if t6c == 1 { pass = pass + 1 } else { fail = fail + 1; g_puts("T6c FAIL invalid id charset\n" as *u8) }
152 let cw3: i64 = aslot_click_resp(inv, n, "/video/index.html" as *u8, 17, out, 8192, idb)
153 if cw3 == 0 { pass = pass + 1 } else { fail = fail + 1; g_puts("T6d FAIL non-click path\n" as *u8) }
154
155 // ---- T7 detectors FIRE on planted vectors (anti-false-green) ----
156 var t7: i64 = 1
157 let bad_url: *u8 = "/x\" onload=\"y" as *u8
158 if aslot_url_chars_ok(bad_url) == 1 { t7 = 0 }
159 if aslot_id_ok("a b" as *u8) == 1 { t7 = 0 }
160 if aslot_img_ok("//evil.example/x.png" as *u8) == 1 { t7 = 0 }
161 if aslot_click_ok("data:text/html;base64,x" as *u8) == 1 { t7 = 0 }
162 if t7 == 1 { pass = pass + 1 } else { fail = fail + 1; g_puts("T7 FAIL detector did not fire\n" as *u8) }
163
164 // ---- T8 zero visitor identity in emitted bytes ----
165 let w8: i64 = aslot_html(inv, n, "/" as *u8, 1, 0, out, 8192, idb)
166 var t8: i64 = 1
167 if g_has(out, w8, "Set-Cookie" as *u8) == 1 { t8 = 0 }
168 if g_has(out, w8, "document.cookie" as *u8) == 1 { t8 = 0 }
169 if g_has(out, w8, "<script" as *u8) == 1 { t8 = 0 }
170 if t8 == 1 { pass = pass + 1 } else { fail = fail + 1; g_puts("T8 FAIL identity/script leak\n" as *u8) }
171
172 g_puts("pass=" as *u8)
173 g_putn(pass)
174 g_puts(" fail=" as *u8)
175 g_putn(fail)
176 g_puts("\n" as *u8)
177
178 let log: *u8 = sys_mmap(512)
179 var lo: i64 = 0
180 lo = g_cat(log, lo, "ADNETSLOT authored=organ pass=" as *u8)
181 let dg: *u8 = sys_mmap(24)
182 var dv: i64 = pass
183 var dk: i64 = 0
184 if dv == 0 { dg[0] = 48 as u8; dk = 1 }
185 while dv > 0 { dg[dk] = (48 + (dv % 10)) as u8; dv = dv / 10; dk = dk + 1 }
186 var di: i64 = dk - 1
187 while di >= 0 { log[lo] = dg[di]; lo = lo + 1; di = di - 1 }
188 if fail == 0 { lo = g_cat(log, lo, " verdict=GREEN" as *u8) } else { lo = g_cat(log, lo, " verdict=RED" as *u8) }
189 log[lo] = 10 as u8
190 lo = lo + 1
191 let fd: i64 = sys_openat_wr("knowledge/status/adnet_slot.log" as *u8, 0x1A4)
192 if fd >= 0 { sys_write(fd, log, lo); sys_close(fd) }
193
194 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
195 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
196 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
197 let ctr__dry: *i64 = gv_ctr()
198 ctr__dry[0] = pass
199 ctr__dry[1] = pass + fail
200 let rc__dry: i64 = gv_verdict("ADNET-SLOT-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
201 sys_exit(rc__dry)
202 return rc__dry
203}