code wiki / _hdl_build / nx_html_sanitize.nx

nx_html_sanitize.nx

buildroot/runtime/_hdl_build/nx_html_sanitize.nx

12430 B294 linesdepth 2pulls 2 transitivereach 47 importersview sourcekind librarytopic html
docsdependenciesstructsconstsfunctions

about

nx_html_sanitize.nx -- CMS ladder step 9 (KEYSTONE): KSES-style HTML ALLOWLIST sanitizer, run on WRITE at the /admin/save boundary (global rule 12: defensive at boundaries). Everything not on the allowlist is REMOVED, never blocklisted: unknown tags stripped (inner text kept), ALL attributes dropped except a@href, href accepted ONLY for http:// https:// / # schemes (post-filter, so "java\tscript:" tricks die with the filtered whitespace), <script>/<style> CONTENT stripped too, stray '<' escaped to &lt;. Quote-aware '>' scan (a '>' inside a quoted attribute does not end the tag). hs_escape = full entity escape for plain-text fields (escape-on-render, defense in depth). Allowlist = packed table HS_TAGS (data-driven, rule 11) -- add a tag = add a table entry. NEEDS_TUTOR build (PARSER shape, not yet emitter-covered): Claude authored, Engineer KATs = real XSS vectors in nx_html_sanitize_test.nx. LAWS: struct-free, integer-only, flat ifs. license_tier: ORIGINAL

dependencies 1 imports · 9 importers

nx_syscalls.nx nx_html_sanitize.nx _pe_blockr.nx _pe_seohead.nx _wb_tmpl.nx nx_cms_draft_exceed_gate.nx nx_cms_render.nx nx_html_sanitize_test.nx nx_sitegen.nx nx_sitegen_freeform.nx nx_sitegen_video.nx

imports: nx_syscalls.nx

imported by: _pe_blockr.nx_pe_seohead.nx_wb_tmpl.nxnx_cms_draft_exceed_gate.nxnx_cms_render.nxnx_html_sanitize_test.nxnx_sitegen.nxnx_sitegen_freeform.nxnx_sitegen_video.nx

structs

none

consts

14const HS_TAGS: *u8 = "b\0i\0u\0em\0strong\0p\0br\0ul\0ol\0li\0a\0h2\0h3\0blockquote\0\0"

functions

16func hs_lc(c: i64) -> i64 { if c >= 65 { if c <= 90 { return c + 32 } } return c }
17func hs_alpha(c: i64) -> i64 { let l: i64 = hs_lc(c); if l >= 97 { if l <= 122 { return 1 } } return 0 }
called by 1: hs_name_at calls 1: hs_lc
18func hs_digit(c: i64) -> i64 { if c >= 48 { if c <= 57 { return 1 } } return 0 }
called by 1: hs_name_at
21func hs_tag_allowed(t: *u8, tl: i64) -> i64
called by 1: hs_sanitize
41func hs_emitb(out: *u8, o: i64, cap: i64, c: i64) -> i64
46func hs_emit(out: *u8, o: i64, cap: i64, s: *u8) -> i64
54func hs_name_at(inp: *u8, n: i64, j: i64, tbuf: *u8) -> i64
called by 1: hs_sanitize calls 3: hs_alphahs_digiths_lc
71func hs_find_gt(inp: *u8, n: i64, i: i64) -> i64
87func hs_skip_close(inp: *u8, n: i64, j: i64, tbuf: *u8, tl: i64) -> i64
called by 1: hs_sanitize calls 2: hs_lchs_find_gt
110func hs_href_value(inp: *u8, gt: i64, v: i64, hbuf: *u8, hcap: i64) -> i64
called by 1: hs_href_extract
136func hs_href_extract(inp: *u8, n: i64, i: i64, gt: i64, hbuf: *u8, hcap: i64) -> i64
called by 1: hs_sanitize calls 2: hs_lchs_href_value
164func hs_scheme_ok(h: *u8, hl: i64) -> i64
called by 1: hs_sanitize calls 1: hs_lc
184func hs_sanitize(inp: *u8, n: i64, out: *u8, cap: i64) -> i64
261func hs_cat_esc_span(d: *u8, o: i64, q: *u8, s: i64, e: i64, cap: i64) -> i64
called by 1: ht_kat_span calls 2: hs_emiths_emitb
279func hs_escape(inp: *u8, n: i64, out: *u8, cap: i64) -> i64