4.4 KiB
Stage 1 technical note
Covered
Config fuzzing covers the Xray-core JSON/config build surface without starting listeners:
infra/conf/serial.DecodeJSONConfigfor full JSON config loading.infra/conf.Config.Buildfor global config normalization and app/inbound/outbound config construction.core.Newfor non-running runtime object initialization after successful full-config builds.InboundDetourConfig.BuildandVLessInboundConfig.Buildfor inbound/VLESS settings, users, decryption, fallback, stream, and sniffing handling.OutboundDetourConfig.BuildandVLessOutboundConfig.Buildfor outbound/VLESS endpoint, user, stream, proxy, and mux handling.StreamConfig.Buildfor transport/security fragments: TCP/raw, WS, gRPC, XHTTP, KCP, TLS, REALITY, sockopt, and finalmask paths where reachable from JSON.SniffingConfig.Build,RouterConfig.Build, andDNSConfig.Buildas focused fragment targets.- API/stats/metrics are included through full config seeds and
conf.Config.Build.
VLESS first-packet fuzzing covers the early inbound pre-auth parser directly:
proxy/vless/encoding.DecodeRequestHeader.proxy/vless.MemoryValidatorwith one configured valid client UUID.- Version, raw UUID, addons length/value, command, and destination parser handling.
- Both direct reader mode and the first-buffer mode used by VLESS inbound after the first socket read.
Stage 2 adds handler-level pre-auth coverage:
proxy/vless/inbound.(*Handler).Processfirst-read path.connection.SetReadDeadline, firstbuf.Buffer.ReadFrom,buf.BufferedReadersetup, and parser call.- UUID lookup through
MemoryValidator. - Flow admission for empty flow, unknown flow, and
xtls-rprx-visionon a raw fake connection. - Command/destination admission for TCP, UDP, Mux, and Rvs.
- Success handoff into
routing.Dispatcher.DispatchLinkusing a recording dispatcher. - Fallback-enabled first-buffer parser/reject path without dialing a real fallback target.
- Invariants for wrong UUID, malformed address metadata, malformed addon length/value, bad command, bad version, short reads, and valid prefix plus trailing body bytes.
Bugs found
One Xray-core config-build crash was found by FuzzXrayCoreFullConfigBuild:
- Minimal reproducer:
{"inBounds":[{"listen":""}]} - Crash:
panic: runtime error: index out of range [0] with length 0 - Upstream location:
github.com/xtls/xray-core/infra/conf.(*InboundDetourConfig).Build,infra/conf/xray.go:152 - Cause: empty string
listenis parsed as a domain address withDomain() == ""; the build path indexesDomain()[0]while checking for Unix domain sockets.
The minimized reproducer is retained in testdata/fuzz/FuzzXrayCoreFullConfigBuild/85cbe7a11661b2e3. The active fuzz harness now quarantines this known empty-domain-listen class before calling Config.Build so subsequent fuzzing can continue. TestXrayCoreKnownEmptyListenPanicReproducer directly calls the upstream build path under recover and asserts the panic still reproduces; when Xray-core fixes the bug, that test should fail and the quarantine should be removed.
The deterministic regression test TestXrayCoreVLESSWrongUUIDRejected verifies that a packet with a changed non-normalized UUID byte does not authenticate.
No VLESS first-packet parser crash, hang, or false dispatch was found in the Stage 2 smoke-runs.
Problems encountered
The config loader imports Xray-core serial config support, which requires additional indirect module metadata in the parent module:
github.com/ghodss/yamlgithub.com/pelletier/go-tomlgopkg.in/yaml.v2
These are Xray-core config-loader dependencies, not fuzzing infrastructure.
core.New is used only after successful build. It initializes Xray runtime objects but does not call Start, so it does not bind sockets or run transport lifecycles.
Not covered in stage 1
- Stateful network harnesses for TCP, WS, gRPC, TLS, REALITY, QUIC, or full VLESS sessions.
- Xray listener accept loops and actual socket deadlines.
- Fallback connection I/O after malformed VLESS first packets.
- Vision/REALITY encrypted first-packet lifecycle beyond the plain request-header parser.
- Long-running resource leak measurement beyond input caps, build/init checks, and elapsed-time guardrails.
- Corpus minimization for Stage 2, because no VLESS failing input was found in smoke-runs.
These are candidates for stage 2 rather than this stage.