MHSanaei/3x-ui · critical
xray binary exceeds %d bytes
Error message
xray binary exceeds %d bytes
What it means
Returned during UpdateXray's extraction step when a file expanded from the downloaded zip streams more than maxXrayBinaryBytes (200 MiB) into the temp file. This is the zip-bomb guard: the archive passed the outer size and SHA-256 checks, but a single decompressed entry exceeding 200 MiB means the zip is malicious or malformed. The real xray binary is ~20-30 MiB, so the guard should never trip on a legitimate release.
Source
Thrown at internal/web/service/server.go:1050
}
tmpFile, err := os.CreateTemp(filepath.Dir(fileName), ".xray-*")
if err != nil {
return err
}
tmpPath := tmpFile.Name()
ok := false
defer func() {
_ = tmpFile.Close()
if !ok {
_ = os.Remove(tmpPath)
}
}()
n, err := io.Copy(tmpFile, io.LimitReader(zipFile, maxXrayBinaryBytes+1))
if err != nil {
return err
}
if n > maxXrayBinaryBytes {
return fmt.Errorf("xray binary exceeds %d bytes", maxXrayBinaryBytes)
}
if err := tmpFile.Chmod(0o755); err != nil {
return err
}
if err := tmpFile.Close(); err != nil {
return err
}
if runtime.GOOS == "windows" {
_ = os.Remove(fileName)
}
if err := os.Rename(tmpPath, fileName); err != nil {
return err
}
ok = true
return nil
}
// 4. Extract correct binaryView on GitHub (pinned to ad32144c42)
Solutions
- Retry the update; if it persists, treat the host's download path as untrusted and verify manually
- Download the zip by hand, run sha256sum against the official .dgst, and unzip -l to inspect entry sizes
- Only consider raising maxXrayBinaryBytes if official binaries ever approach 200 MiB
Defensive patterns
Strategy: validation
Validate before calling
for _, f := range zipReader.File {
if f.UncompressedSize64 > maxXrayBinaryBytes {
return fmt.Errorf("zip entry %s expands to %d bytes; refusing", f.Name, f.UncompressedSize64)
}
}
Prevention
- Check zip entry UncompressedSize64 headers before streaming, in addition to a streamed cap
- Keep the streamed LimitReader(n+1) pattern so decompression bombs cannot exhaust disk
- Never execute any binary extracted from an archive that tripped a size guard
When it happens
Trigger: A crafted zip whose entries decompress far beyond the archive size; a corrupted zip whose entry headers claim/expand bogus sizes; extraction reading the wrong entry because the zip layout changed.
Common situations: Effectively only with tampered/corrupted archives that also passed the checksum (impossible unless the .dgst itself was compromised) — or after a genuine xray binary exceeds 200 MiB, which has never happened.
Related errors
- panel updater exceeds %d bytes
- download xray: archive exceeds %d bytes
- Xray update aborted: the downloaded archive does not match t
- remote response exceeds size limit
- outbound subscription response body exceeds size limit
AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15).
Data as JSON: /api/errors/96c262afe1296410.
Report an issue: GitHub.