code wiki / (root) / nx_https_get_live_github_test.nx

nx_https_get_live_github_test.nx source

↩ module page · 101 lines · 5194 B

1// nx_https_get_live_github_test.nx -- LIVE external-CA regression gate for the GitHub certificate class. 2// 3// WHY THIS EXISTS (2026-07-15): the live MCP `nx_https_get` on the NAS could NOT fetch github.com/ 4// api.github.com/raw.githubusercontent.com ("unknown certificate verification error"), while the current 5// source verifies them fine. Root cause = a STALE NAS binary predating the 2026-06-25 ECDSA-P384 + 6// chain-verify fixes; GitHub's chain (Sectigo/USERTrust ECC + Fastly) exercises exactly that path. 7// This gate makes the capability SELF-VERIFYING: current source must verify GitHub's live chain, and a 8// KNOWN-BAD cert must still be REJECTED (fail-closed) -- so the regression can never land silently again. 9// 10// Joins the live-CA family: nx_https_get_live_{real_ca,google,demo}_test.nx. Network-dependent (positive 11// legs need github reachable); the fail-closed neg-control is safe under network loss (connect-fail also 12// yields "did not fetch"). Deterministic cert-REJECTION is additionally covered offline by 13// nx_tls13_client_validate_certificate_test + nx_x509_chain_verify_test. 14// 15// expect_exit: 0 license_tier: ORIGINAL 16 17import "nx_syscalls.nx" 18import "nx_x509_trust_store.nx" 19import "nx_trust_store_load_from_certdata.nx" 20import "nx_https_get.nx" 21 22const GHT_CERTDATA: *u8 = "data/mozilla_certdata.txt" as *u8 23const GHT_CAP: i64 = 1048576 24 25func ght_put(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 26func ght_pn(v: i64) -> i64 { 27 let b: *u8 = sys_mmap(24) 28 var m: i64 = v 29 if m == 0 { b[0] = 48 as u8; sys_write(1, b, 1); return 0 } 30 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 31 var nd: i64 = 0 32 var t: i64 = m 33 while t > 0 { nd = nd + 1; t = t / 10 } 34 var i: i64 = nd - 1 35 while i >= 0 { b[i] = (48 + (m % 10)) as u8; m = m / 10; i = i - 1 } 36 sys_write(1, b, nd) 37 return 0 38} 39// clean "HTTP/1.1 200" status-line check: bytes 9..11 == "200" 40func ght_is200(out: *u8, n: i64) -> i64 { 41 if n < 12 { return 0 } 42 if out[9] != (50 as u8) { return 0 } 43 if out[10] != (48 as u8) { return 0 } 44 if out[11] != (48 as u8) { return 0 } 45 return 1 46} 47 48// POSITIVE leg: fetch must succeed AND return a 200 status line (i.e., cert verified end-to-end). 49func ght_positive(url: *u8, cr: *u8, priv: *u8, store: *TrustStore, now: i64, out: *u8) -> i64 { 50 ght_put(" GET " as *u8); ght_put(url); ght_put(" -> " as *u8) 51 let n: i64 = nx_https_get(url, cr, priv, store, now, out, GHT_CAP) 52 if n <= 0 { ght_put("FETCH-FAIL code=" as *u8); ght_pn(0 - n); ght_put(" (cert verify FAILED = the regression)\n" as *u8); return 0 } 53 if ght_is200(out, n) == 0 { ght_put("no-200 (bytes=" as *u8); ght_pn(n); ght_put(")\n" as *u8); return 0 } 54 ght_put("200 OK, bytes=" as *u8); ght_pn(n); ght_put(" (cert chain VERIFIED)\n" as *u8) 55 return 1 56} 57 58func main() -> i64 { 59 ght_put("=== nx_https_get_live_github_test -- live external-CA regression (GitHub chain) ===\n" as *u8) 60 let r: i64 = nx_trust_store_load_from_certdata(GHT_CERTDATA, 512, 4194304) 61 if r <= 0 { ght_put("FATAL: trust-store load failed (data/mozilla_certdata.txt)\n" as *u8); sys_exit(1); return 1 } 62 let store: *TrustStore = r as *TrustStore 63 let cas: i64 = trust_store_count(store) 64 ght_put(" trust store CAs=" as *u8); ght_pn(cas); ght_put("\n" as *u8) 65 if cas < 50 { ght_put("FATAL: too few CAs loaded\n" as *u8); sys_exit(1); return 1 } 66 67 let cr: *u8 = sys_mmap(32) 68 var i: i64 = 0 69 while i < 32 { cr[i] = (0xC0 + i) as u8; i = i + 1 } 70 let priv: *u8 = sys_mmap(32) 71 i = 0 72 while i < 32 { priv[i] = (0xA0 + i) as u8; i = i + 1 } 73 let now: i64 = sys_now_realtime_sec() 74 let out: *u8 = sys_mmap(GHT_CAP) 75 var fails: i64 = 0 76 77 // POSITIVE 1: api.github.com (GitHub's own ECC chain) 78 if ght_positive("https://api.github.com/repos/kekzl/imp\x00" as *u8, cr, priv, store, now, out) == 0 { fails = fails + 1 } 79 // POSITIVE 2: raw.githubusercontent.com (Fastly chain -- the other distinct authority) 80 if ght_positive("https://raw.githubusercontent.com/kekzl/imp/HEAD/README.md\x00" as *u8, cr, priv, store, now, out) == 0 { fails = fails + 1 } 81 82 // NEG-CONTROL: a known-EXPIRED cert must be REJECTED (fail-closed). A fetch that SUCCEEDS here = a 83 // security regression (we accepted an invalid cert) -> RED. Network loss -> connect-fail -> also <0 -> safe. 84 ght_put(" NEG expired.badssl.com -> " as *u8) 85 let nb: i64 = nx_https_get("https://expired.badssl.com/\x00" as *u8, cr, priv, store, now, out, GHT_CAP) 86 if nb > 0 { 87 ght_put("ACCEPTED (bytes=" as *u8); ght_pn(nb); ght_put(") -- SECURITY REGRESSION, expired cert must be rejected\n" as *u8) 88 fails = fails + 1 89 } else { 90 ght_put("rejected/unreachable (code=" as *u8); ght_pn(0 - nb); ght_put(") = fail-closed OK\n" as *u8) 91 } 92 93 if fails == 0 { 94 ght_put("NX-HTTPS-GITHUB GREEN -- live GitHub cert chains verify + expired cert rejected (capability self-verified)\n" as *u8) 95 sys_exit(0) 96 return 0 97 } 98 ght_put("NX-HTTPS-GITHUB RED fails=" as *u8); ght_pn(fails); ght_put("\n" as *u8) 99 sys_exit(1) 100 return 1 101}