{"record":{"id":"96c262afe1296410","repo":"MHSanaei/3x-ui","slug":"xray-binary-exceeds-d-bytes","errorCode":null,"errorMessage":"xray binary exceeds %d bytes","messagePattern":"xray binary exceeds (.+?) bytes","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/web/service/server.go","lineNumber":1050,"sourceCode":"\t\t}\n\t\ttmpFile, err := os.CreateTemp(filepath.Dir(fileName), \".xray-*\")\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ttmpPath := tmpFile.Name()\n\t\tok := false\n\t\tdefer func() {\n\t\t\t_ = tmpFile.Close()\n\t\t\tif !ok {\n\t\t\t\t_ = os.Remove(tmpPath)\n\t\t\t}\n\t\t}()\n\t\tn, err := io.Copy(tmpFile, io.LimitReader(zipFile, maxXrayBinaryBytes+1))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif n > maxXrayBinaryBytes {\n\t\t\treturn fmt.Errorf(\"xray binary exceeds %d bytes\", maxXrayBinaryBytes)\n\t\t}\n\t\tif err := tmpFile.Chmod(0o755); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := tmpFile.Close(); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif runtime.GOOS == \"windows\" {\n\t\t\t_ = os.Remove(fileName)\n\t\t}\n\t\tif err := os.Rename(tmpPath, fileName); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tok = true\n\t\treturn nil\n\t}\n\n\t// 4. Extract correct binary","sourceCodeStart":1032,"sourceCodeEnd":1068,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/web/service/server.go#L1032-L1068","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"for _, f := range zipReader.File {\n    if f.UncompressedSize64 > maxXrayBinaryBytes {\n        return fmt.Errorf(\"zip entry %s expands to %d bytes; refusing\", f.Name, f.UncompressedSize64)\n    }\n}\n","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["xray-update","security","zip","size-limit"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}