Files
LumaWeb/state/evidence/S00-018-auto-protocol-89fe6563092c.md
T
wt e2b4dbdb76 S00-018: Bound standalone XML ingress before Stanza parsing and import
Changes: Add an isolated public transport integration with finite byte, depth, element and attribute budgets; validate complete text XML with pinned saxes before real JXT parsing/import. Add adversarial and boundary fixtures, terminal cleanup tests, dependency notices and a proposed parser ADR.
Validation: Fresh-cache npm ci and npm test passed all 55 tests with Node 24.21.0/npm 11.19.0. Reproduced three stock parser failures, checked ten exact dependency licenses/integrities and 340 unchanged Stanza files; make check passed 72 tooling tests. Scope and whitespace inspected. Browser runtime, live WSS and interoperability were not tested.

Task: S00-018
Agent: auto-protocol-89fe6563092c
Role: protocol
Action: claim
Status: review

Task title: Validate bounded standalone XML ingress for the XMPP candidate
2026-10-15 02:31:33 +07:00

8.6 KiB

S00-018 executor evidence

Agent: auto-protocol-89fe6563092c (protocol). Date: 2026-10-15. Result: bounded standalone XML ingress experiment and proposed ADR; independent security review pending.

Input: assigned master/startup/role/workflow instructions; resume/show/packet; required TESTING, decisions/README, blocker S00-018; exact ACC-004/NET-003/NET-004; accepted scope/stack/SASL ADRs and all direct dependency evidence/reviews/handoffs; original parser blocker evidence/handoff/probe; shipped Client/Transport/JXT and saxes API/source. No missing required input. No new shared contract is needed. Output: only experiments/0002-xmpp-library/parser-validation and docs/decisions/0002-xmpp-parser-validation.md, plus workflow metadata.

Actual changes and demonstrated acceptance

Public Client.transports constructor registration and explicit single transport selection run real Client.connect. Per-message type/unit/UTF-8 byte checks precede new saxes XML 1.0 namespace-aware document parsing. Callback depth/element/ attribute/name/value budgets precede candidate JXT.parse/registry.import. SAX close detects incompleteness; malformed/multiple-root documents never import an earlier complete root. All XML syntax uses existing libraries. Global input bytes bound unfinished/oversized tokens before event callbacks. No vendor patch, late interception, fixture parser or handwritten XML security parser.

Local inclusive budgets: 4096 UTF-8 bytes, depth 8, elements 32, attributes 16 including namespace declarations, aggregate attribute name+decoded value units 1024, names 128, decoded attribute values 256. Combined boundary fixture meets all aggregate ceilings simultaneously and yields its exact real imported body; separate Unicode/name/value equality cases pass. Limits remain experiment policy, not product/shared contract decisions. DTD/comment/PI/declaration reject; namespace, entities, malformed chars and duplicate attributes checked by saxes.

55 tests use actual Client/JXT/registry/queue. FixtureSocket captures only socket effects; registry tracing calls the real import. Original 1 MiB body, depth 256, and 18-message partial-document categories reject terminally. Bad input never delivers stanza or stream:start, invalid syntax/budgets never reach registry import, and old captured callbacks cannot revive the attempt. Callback detachment, stream/config cleanup, fresh Client.connect, successive independent documents, stream open/close/restart, export/send and subprotocol/socket failure are tested. No peer payload/error text is logged or raw-evented.

Actual commands and results

All Node/npm commands used PATH=/private/tmp/luma-stack-runtime/node-v24.21.0-darwin-arm64/bin:$PATH, the previously reviewed isolated Node 24.21.0/npm 11.19.0, from project root. No system install or certificate override. Exact engine pins and strict SSL remain in manifest/.npmrc. No new runtime archive verification claimed.

Command Exit Observed result
python3 scripts/tasks.py resume --agent auto-protocol-89fe6563092c 0 Assigned S00-018 in_progress, no repeat claim
python3 scripts/tasks.py show S00-018; packet S00-018 --agent auto-protocol-89fe6563092c (separate invocations) 0 each Scope/prerequisites/requirements confirmed
node experiments/0002-xmpp-library/parser-probe/reproduce.mjs 0 Stock accepted 18 writes/65536 body bytes, 1048576-byte body, 256 nested children; defect reproduction, not safe result
npm view saxes@6.0.0 version license engines dependencies --json --cache /private/tmp/luma-parser-cache --fetch-retries=0 --fetch-timeout=15000 --strict-ssl=true 0 6.0.0, ISC, Node >=v12.22.7, xmlchars ^2.2.0
npm install --prefix experiments/0002-xmpp-library/parser-validation --ignore-scripts --no-audit --no-fund --cache /private/tmp/luma-parser-cache --fetch-retries=0 --fetch-timeout=15000 0 Ten packages, independent lock generated
npm test --prefix experiments/0002-xmpp-library/parser-validation 0 55 passed, zero failed/skipped/cancelled, 378.193208 ms
npm ci --prefix experiments/0002-xmpp-library/parser-validation --ignore-scripts --no-audit --no-fund --cache /private/tmp/luma-parser-clean-89fe6563092c --fetch-retries=0 --fetch-timeout=15000 0 Actual clean install with fresh cache, ten packages, scripts disabled
npm test --prefix experiments/0002-xmpp-library/parser-validation after ci 0 55 passed, zero failed/skipped/cancelled, 341.101792 ms; runtime/test source unchanged afterward
curl --fail --silent --show-error https://raw.githubusercontent.com/lddubeau/saxes/v6.0.0/LICENSE -o /private/tmp/luma-parser-saxes-LICENSE 0 Upstream full ISC lineage/historical MIT notice retrieved through verified HTTPS; preserved in experiment
Corrected inline Python license collector 0 Ten exact installed versions/licenses/HTTPS/SHA512 entries; preserved shipped notices plus upstream saxes LICENSE
python3 experiments/0002-xmpp-library/parser-validation/check-dependencies.py 0 Ten exact graph/license checks; all 340 Stanza files byte-match original candidate
make check 0 283 tasks, 22 stages, 221 requirements, 211 Web requirements, revision 44; 72 tooling tests in 18.439s
git diff --check; git status --short --untracked-files=all (separate checks) 0 each Scoped source only plus coordinator state claim before evidence
Inline Python authored-file whitespace/final-newline checks 0 All 12 authored experiment/ADR files checked, including untracked files

Exploratory failures are not passed checks: guessed transports/index.d.ts absent (actual Transport API is index.d.ts); first license collector failed because saxes tarball omits LICENSE (Python AssertionError, surrounding shell ended 0 because following npm ci succeeded). Guessed upstream root saxes.ts URL returned 404; subsequent head/rg saw no file (combined command exit 2). Actual upstream LICENSE fetch succeeded; no required artifact is missing and no source patch was attempted. These failures do not affect the reproduced acceptance checks.

Primary sources and dependencies

Opened RFC 7395 §3.2/3.3.3 through web tools; versioned saxes README/package source, upstream Stanza Client source; inspected installed version-pinned declarations and implementation. Direct links and constraints are in ADR. Sources inspected 2026-10-15. The supported extension claim rests on public shipped constructor registry/Transport interface and actual Client selection, not private fields.

New direct pins saxes 6.0.0 ISC / xmlchars 2.2.0 MIT, existing Stanza 12.22.1 MIT. Other exact installed packages: @types/node 22.20.5, @types/punycode 2.1.4, @types/ws 8.18.2, punycode 2.3.1, sdp 3.2.2, undici-types 6.21.0, ws 8.22.0, all MIT. Inventory/notices and lock are preserved. Saxes release is older; continued support/advisory/provenance clearance is not assumed. Node-focused CommonJS packages require browser bundling. Default adapter uses native browser WebSocket, URL, TextEncoder and private fields; fixture injection is explicit.

SHA256:

  • package-lock.json: 35b177d57aaf81778eaf3d3321b3f77eb1e755a46abee784ef62b8959aedd63c
  • bounded-ingress.mjs: e6399ff581f59d1f09b471234d6e4b8f2ed6b61804aa4eb0eef7dd3f8e3f2dbc
  • licenses/saxes-6.0.0-LICENSE: 0fac2374380621b22e6b50451057721a9c52935b02d16d106a9f04897f061d0e

Limits and independent review input

No browser build/runtime, actual WSS/TLS/server handshake, auth changes, independent client interoperability, load/exhaustion benchmark or security audit was performed. No TLS/CORS bypass, real credentials/conversations, custom crypto or invented binding. Original candidate, reviewed SASL plugin, app modules, shared contracts, immutable specs and plan definitions unchanged. Git mutations and additional task/agent launch were not performed.

Browser WebSocket allocates a complete inbound message before JavaScript checks; this experiment bounds parser work afterward, not network-stack memory. SAX can store one token/attribute before a callback, bounded by the byte precheck. Total traffic, Client queues, downstream extension work and CPU rate are not bounded. Minimal transport lacks full stream-error/close negotiation/redirect/keepalive/ language inheritance/stream sequencing. Complete SAX/JXT semantic equivalence is not certified. See README/ADR; these limits prohibit production-readiness claims but do not invalidate the assigned local parser/framing experiment.

Separate security reviewer must reproduce README clean install/tests/license checks, inspect actual scope/order/API/cleanup and compare this evidence and executor commit message with actual patch. ADR remains proposed and task is submitted for review, not done. Coordinator commits and launches fresh review; this executor stops after submit and does not resume S00-003.