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
This commit is contained in:
wt committed 2026-10-15 02:31:33 +07:00
1 parent f556fc0deb
commit e2b4dbdb76
19 files changed
+1648 -8

No files matched your search

@@ -0,0 +1,4 @@
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.
@@ -0,0 +1,118 @@
# 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.
+39
View File
@@ -0,0 +1,39 @@
# S00-018 handoff for independent security review
Executor: auto-protocol-89fe6563092c (protocol), 2026-10-15.
Outcome: isolated bounded XML ingress experiment and proposed parser ADR.
No blocker; implementation awaits independent security review.
Actual result: new public Client.transports constructor selected by actual
Client.connect, finite byte precheck, fresh saxes strict namespace-aware XML 1.0
validation/close per message, then actual JXT.parse/registry.import. Explicit
local byte/depth/element/attribute/name/value limits apply before tree/import.
Malformed/incomplete/multiple-root/binary/budget violations close attempt,
detach callbacks, clear stream/config; stale callbacks cannot revive it. A fresh
connection works. No persistent parser, vendor patch or custom XML syntax parser.
Pinned Node 24.21.0/npm 11.19.0 fresh-cache npm ci and 55 integrated tests passed;
stock probe reproduced all three failures; license checks for all ten packages
and byte comparison of all 340 Stanza files passed. make check: 72 tests passed.
Commands/digests/failures/limits: state/evidence/S00-018-auto-protocol-89fe6563092c.md.
Next belongs only to security reviewer: inspect proposed
docs/decisions/0002-xmpp-parser-validation.md, experiment source/tests/notices,
executor diff/message and README. Run README commands with the reviewed isolated
runtime at /private/tmp/luma-stack-runtime/node-v24.21.0-darwin-arm64/bin and a
fresh reviewer cache. Verify budget/framing checks precede JXT allocations/import,
actual Client registry selection, boundary success, zero delivery for bad input,
terminal callback replay/cleanup and fresh attempts. check-dependencies.py also
needs the original parent candidate installed for vendor comparison. Saxes
published package omits LICENSE; preserved v6.0.0 upstream LICENSE and source are
recorded. Keep ADR proposed until independent acceptance.
Limits: fixture socket only, no browser build/runtime or real WSS/server/client
interop; byte checks begin after browser allocates the message. No aggregate
traffic/Client queue/rate bounds or production policy. Minimal transport lacks
full stream-error/close negotiation/redirect/keepalive/language inheritance/
sequencing, and exhaustive SAX/JXT equivalence is not certified. Auth/crypto and
accepted SASL experiment unchanged. No specs/shared interfaces/app modules or
original candidate files changed. S00-003 remains separate; only reviewed done
and coordinator commit allow a fresh original executor to continue it. This
executor exits after submit; no commit/next agent/original work is performed.
+31 -4
View File
@@ -1,6 +1,6 @@
{
"schema_version": 1,
"revision": 43,
"revision": 45,
"tasks": {
"S00-001": {
"status": "done",
@@ -1236,10 +1236,14 @@
"completed_at": "2026-10-14T19:20:57+00:00"
},
"S00-018": {
"status": "todo",
"owner": null,
"status": "review",
"owner": "auto-protocol-89fe6563092c",
"external_wait": false,
"reason": null
"reason": null,
"started_at": "2026-10-14T19:24:01+00:00",
"updated_at": "2026-10-14T19:31:32+00:00",
"evidence": "state/evidence/S00-018-auto-protocol-89fe6563092c.md",
"handoff": "state/handoffs/S00-018.md"
}
},
"events": [
@@ -1798,6 +1802,29 @@
"from": "in_progress",
"to": "blocked",
"reason": "S00-003 cannot attest parser limits: Stanza 12.22.1 exposes no resource bounds and its persistent WebSocket parser accepts large/deep XML and reassembles incomplete documents across separate input messages."
},
{
"revision": 44,
"at": "2026-10-14T19:24:01+00:00",
"action": "claim",
"task": "S00-018",
"agent": "auto-protocol-89fe6563092c",
"role": "protocol",
"from": "todo",
"to": "in_progress",
"reason": null
},
{
"revision": 45,
"at": "2026-10-14T19:31:32+00:00",
"action": "submit",
"task": "S00-018",
"agent": "auto-protocol-89fe6563092c",
"role": null,
"from": "in_progress",
"to": "review",
"reason": null,
"evidence": "state/evidence/S00-018-auto-protocol-89fe6563092c.md"
}
],
"retired_agents": [