nx_http_security_headers_test.nx source
↩ module page · 167 lines · 7088 B
1// nx_http_security_headers_test.nx -- smoke for production header set.
2//
3// expect_exit: 0
4//
5// license_tier: ORIGINAL
6
7import "nx_syscalls_x86_64.nx"
8import "nx_http_security_headers.nx"
9
10func bytes_eq(a: *u8, b: *u8, n: i64) -> i64 {
11 var i: i64 = 0
12 while i < n {
13 if a[i] != b[i] { return 0 }
14 i = i + 1
15 }
16 return 1
17}
18
19func bytes_contains(haystack: *u8, h_n: i64, needle: *u8, n_n: i64) -> i64 {
20 if n_n > h_n { return 0 }
21 var i: i64 = 0
22 while i <= h_n - n_n {
23 if bytes_eq(((haystack as i64) + i) as *u8, needle, n_n) == 1 { return 1 }
24 i = i + 1
25 }
26 return 0
27}
28
29func main() -> i64 {
30 // ---- Verdict + level enum gates ----
31 if nxsh_verdict_is_valid(NXSH_OK) != 1 { return 1 }
32 if nxsh_verdict_is_valid(NXSH_VERDICT_N) != 0 { return 2 }
33 if nxsh_level_is_valid(NXSH_STRICT) != 1 { return 3 }
34 if nxsh_level_is_valid(NXSH_LEVEL_N) != 0 { return 4 }
35
36 if bytes_eq(nxsh_level_name(NXSH_STRICT), "STRICT" as *u8, 6) != 1 { return 5 }
37 if bytes_eq(nxsh_level_name(NXSH_MODERATE), "MODERATE" as *u8, 8) != 1 { return 6 }
38 if bytes_eq(nxsh_level_name(NXSH_PERMISSIVE), "PERMISSIVE" as *u8, 10) != 1 { return 7 }
39
40 let buf: *u8 = sys_mmap(2048)
41 let off: *i64 = sys_mmap(8) as *i64
42
43 // ---- CSP STRICT ----
44 off[0] = 0
45 if nx_http_emit_csp(buf, off, 2048, NXSH_STRICT) != NXSH_OK { return 10 }
46 if bytes_contains(buf, off[0],
47 "Content-Security-Policy: default-src 'none'" as *u8, 43) != 1 { return 11 }
48 if bytes_contains(buf, off[0],
49 "frame-ancestors 'none'" as *u8, 22) != 1 { return 12 }
50
51 // ---- CSP MODERATE ----
52 off[0] = 0
53 if nx_http_emit_csp(buf, off, 2048, NXSH_MODERATE) != NXSH_OK { return 13 }
54 if bytes_contains(buf, off[0],
55 "default-src 'self'" as *u8, 18) != 1 { return 14 }
56 if bytes_contains(buf, off[0],
57 "'unsafe-inline'" as *u8, 15) != 1 { return 15 }
58
59 // ---- CSP PERMISSIVE ----
60 off[0] = 0
61 if nx_http_emit_csp(buf, off, 2048, NXSH_PERMISSIVE) != NXSH_OK { return 16 }
62 if bytes_contains(buf, off[0],
63 "Content-Security-Policy: default-src 'self'" as *u8, 43) != 1 { return 17 }
64
65 // ---- BAD_LEVEL ----
66 off[0] = 0
67 if nx_http_emit_csp(buf, off, 2048, 99) != NXSH_BAD_LEVEL { return 18 }
68
69 // ---- X-Frame-Options STRICT -> DENY ----
70 off[0] = 0
71 if nx_http_emit_x_frame_options(buf, off, 2048, NXSH_STRICT) != NXSH_OK { return 20 }
72 if bytes_contains(buf, off[0],
73 "X-Frame-Options: DENY\r\n" as *u8, 23) != 1 { return 21 }
74
75 // ---- X-Frame-Options MODERATE -> SAMEORIGIN ----
76 off[0] = 0
77 if nx_http_emit_x_frame_options(buf, off, 2048, NXSH_MODERATE) != NXSH_OK { return 22 }
78 if bytes_contains(buf, off[0],
79 "X-Frame-Options: SAMEORIGIN\r\n" as *u8, 29) != 1 { return 23 }
80
81 // ---- X-Frame-Options PERMISSIVE -> header omitted ----
82 off[0] = 0
83 if nx_http_emit_x_frame_options(buf, off, 2048, NXSH_PERMISSIVE) != NXSH_OK { return 24 }
84 if off[0] != 0 { return 25 }
85
86 // ---- X-Content-Type-Options ----
87 off[0] = 0
88 if nx_http_emit_x_content_type_options(buf, off, 2048) != NXSH_OK { return 30 }
89 if bytes_contains(buf, off[0],
90 "X-Content-Type-Options: nosniff\r\n" as *u8, 33) != 1 { return 31 }
91
92 // ---- Referrer-Policy STRICT -> no-referrer ----
93 off[0] = 0
94 if nx_http_emit_referrer_policy(buf, off, 2048, NXSH_STRICT) != NXSH_OK { return 40 }
95 if bytes_contains(buf, off[0],
96 "Referrer-Policy: no-referrer\r\n" as *u8, 30) != 1 { return 41 }
97
98 // ---- Referrer-Policy MODERATE -> strict-origin-when-cross-origin ----
99 off[0] = 0
100 if nx_http_emit_referrer_policy(buf, off, 2048, NXSH_MODERATE) != NXSH_OK { return 42 }
101 if bytes_contains(buf, off[0],
102 "strict-origin-when-cross-origin" as *u8, 31) != 1 { return 43 }
103
104 // ---- Permissions-Policy STRICT -> deny all ----
105 off[0] = 0
106 if nx_http_emit_permissions_policy(buf, off, 2048, NXSH_STRICT) != NXSH_OK { return 50 }
107 if bytes_contains(buf, off[0],
108 "Permissions-Policy: camera=()" as *u8, 29) != 1 { return 51 }
109 if bytes_contains(buf, off[0],
110 "microphone=()" as *u8, 13) != 1 { return 52 }
111 if bytes_contains(buf, off[0],
112 "geolocation=()" as *u8, 14) != 1 { return 53 }
113
114 // ---- Permissions-Policy PERMISSIVE -> header omitted ----
115 off[0] = 0
116 if nx_http_emit_permissions_policy(buf, off, 2048, NXSH_PERMISSIVE) != NXSH_OK { return 54 }
117 if off[0] != 0 { return 55 }
118
119 // ---- HSTS ----
120 off[0] = 0
121 if nx_http_emit_hsts(buf, off, 2048, 31536000, 1) != NXSH_OK { return 60 }
122 if bytes_contains(buf, off[0],
123 "Strict-Transport-Security: max-age=31536000; includeSubDomains\r\n" as *u8, 64) != 1 { return 61 }
124
125 // HSTS without subdomains
126 off[0] = 0
127 if nx_http_emit_hsts(buf, off, 2048, 60, 0) != NXSH_OK { return 62 }
128 if bytes_contains(buf, off[0],
129 "max-age=60\r\n" as *u8, 12) != 1 { return 63 }
130 // Verify NO "includeSubDomains" present
131 if bytes_contains(buf, off[0],
132 "includeSubDomains" as *u8, 17) != 0 { return 64 }
133
134 // ---- DNS-prefetch off ----
135 off[0] = 0
136 if nx_http_emit_dns_prefetch_off(buf, off, 2048) != NXSH_OK { return 70 }
137 if bytes_contains(buf, off[0],
138 "X-DNS-Prefetch-Control: off\r\n" as *u8, 29) != 1 { return 71 }
139
140 // ---- Bundle (all-secure-defaults) ----
141 off[0] = 0
142 if nx_http_emit_security_headers_bundle(buf, off, 2048, NXSH_STRICT) != NXSH_OK { return 80 }
143 // All 7 headers should be present:
144 if bytes_contains(buf, off[0],
145 "Content-Security-Policy:" as *u8, 24) != 1 { return 81 }
146 if bytes_contains(buf, off[0],
147 "X-Frame-Options: DENY" as *u8, 21) != 1 { return 82 }
148 if bytes_contains(buf, off[0],
149 "X-Content-Type-Options: nosniff" as *u8, 31) != 1 { return 83 }
150 if bytes_contains(buf, off[0],
151 "Referrer-Policy: no-referrer" as *u8, 28) != 1 { return 84 }
152 if bytes_contains(buf, off[0],
153 "Permissions-Policy:" as *u8, 19) != 1 { return 85 }
154 if bytes_contains(buf, off[0],
155 "X-DNS-Prefetch-Control: off" as *u8, 27) != 1 { return 86 }
156 if bytes_contains(buf, off[0],
157 "Strict-Transport-Security: max-age=31536000" as *u8, 43) != 1 { return 87 }
158
159 // ---- BAD_ARG ----
160 off[0] = 0
161 if nx_http_emit_security_headers_bundle(0 as *u8, off, 2048, NXSH_STRICT) != NXSH_BAD_ARG { return 90 }
162 if nx_http_emit_security_headers_bundle(buf, 0 as *i64, 2048, NXSH_STRICT) != NXSH_BAD_ARG { return 91 }
163 if nx_http_emit_security_headers_bundle(buf, off, 0, NXSH_STRICT) != NXSH_BAD_ARG { return 92 }
164 if nx_http_emit_security_headers_bundle(buf, off, 2048, 99) != NXSH_BAD_LEVEL { return 93 }
165
166 return 0
167}