nx_url_safety_lib.nx
buildroot/runtime/nx_url_safety_lib.nx
about
nx_url_safety_lib.nx -- THE ONE SSRF URL-SAFETY RULER (/compare/mediaingest R11 ge_edge_push).
WHY THIS EXISTS. Measured 2026-09-01, corpus_complete=1 over 23,424 sources: the estate has TWO copies of
this decision -- csd_url_safe (nx_clean_serve_daemon.nx:101) and ncv_url_safe (nx_cleanview.nx:44). They
are byte-for-byte identical logic today, differing only in their function-name prefix, which is exactly
the duplicate-ruler defect: they agree by the luck of having been copied, and the next edit to one will
not reach the other. For a SECURITY decision that is not a style problem -- it is how one surface quietly
keeps admitting a host the other learned to refuse.
⇒ ONE ruler, composed by every caller. WHEN TWO ORGANS MUST AGREE, MAKE DISAGREEMENT IMPOSSIBLE BY
CONSTRUCTION RATHER THAN BY REVIEW DISCIPLINE.
WHY IT RETURNS A REASON AND NOT A BOOLEAN. This estate has already paid for a boolean here. Its own law:
"Four SSRF deny-tests went green while the guard was wholly broken (a url-decoder missing its SPACE
terminator swallowed the request line so EVERY url refused as control bytes)." A guard that refuses
everything passes every negative test. So:
- us_reason() names WHICH RULE FIRED, so a refusal test can assert the rule and not merely the refusal;
- us_url_safe() is the 0/1 shim, defined AS us_reason()==US_OK, so the boolean can never disagree with
the reason it is derived from;
- and any gate over this MUST carry POSITIVE CONTROLS -- inputs that must be ALLOWED -- or a
refuse-everything regression scores full marks.
SCOPE, STATED SO NOBODY OVER-TRUSTS IT. This is a SYNTACTIC guard on the URL as written. It does NOT
resolve DNS, so a public hostname whose A record points at 10.x (DNS rebinding, and the classic
time-of-check/time-of-use hole) is ALLOWED here and must be caught at connect time by the fetcher. It
blocks all of 172.x rather than only 172.16-31 -- deliberately conservative, and wrong in the direction
of refusing a legitimate public host rather than admitting a private one.
module: nishi-core.net.url_safety
license_tier: ORIGINAL
dependencies 1 imports · 4 importers
imports: nx_syscalls.nx
imported by: nx_clean_serve_daemon.nxnx_cleanview.nxnx_url_safety_gate.nxnx_vault_capture.nx
structs
| none |
consts
| 33 | const US_OK: i64 = 0 |
| 34 | const US_BAD_SCHEME: i64 = 1 // neither http:// nor https:// |
| 35 | const US_NO_HOST: i64 = 2 // empty host after the scheme |
| 36 | const US_LOOPBACK: i64 = 3 // localhost or 127.x |
| 37 | const US_PRIVATE_10: i64 = 4 |
| 38 | const US_PRIVATE_192: i64 = 5 |
| 39 | const US_LINK_LOCAL: i64 = 6 // 169.254.x -- cloud metadata lives here |
| 40 | const US_PRIVATE_172: i64 = 7 |
| 41 | const US_ZERO_NET: i64 = 8 // 0.x -- 0.0.0.0 routes to local on many stacks |
| 42 | const US_IPV6_LITERAL: i64 = 9 // any [..] literal: loopback/ULA/link-local all hide in here |
| 43 | const US_INTERNAL_TLD: i64 = 10 // .local / .internal / .lan |
| 44 | const US_REASON_N: i64 = 11 |
| 46 | const US_HOST_CAP: i64 = 512 |
| 47 | const US_CH_SLASH: i64 = 47 |
| 48 | const US_CH_COLON: i64 = 58 |
| 49 | const US_CH_QUERY: i64 = 63 |
| 50 | const US_CH_AT: i64 = 64 |
| 51 | const US_CH_UPPER_A: i64 = 65 |
| 52 | const US_CH_UPPER_Z: i64 = 90 |
| 53 | const US_CH_CASE_DELTA: i64 = 32 |
functions
| 55 | func us_reason_name(r: i64) -> *u8 called by 1: main |
| 70 | func us_reason_is_valid(r: i64) -> i64 |
| 76 | func us_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } called by 1: us_pfx_ci |
| 77 | func us_lc(c: i64) -> i64 called by 1: us_pfx_ci |
| 83 | func us_pfx_ci(s: *u8, n: i64, pfx: *u8) -> i64 |
| 96 | func us_host_of(url: *u8, ulen: i64, host: *u8, cap: i64) -> i64 |
| 128 | func us_reason(url: *u8, ulen: i64) -> i64 |
| 149 | func us_url_safe(url: *u8, ulen: i64) -> i64 |