{"record":{"id":"9c8b129a9fa2a644","repo":"theonedev/onedev","slug":"metadata-exceeds-maximum-size-max-metadata-size","errorCode":null,"errorMessage":"Metadata exceeds maximum size: ${MAX_METADATA_SIZE}","messagePattern":"Metadata exceeds maximum size: (.+?)","errorType":"http","errorClass":"ClientException","httpStatus":406,"severity":"error","filePath":"server-plugin/server-plugin-pack-gem/src/main/java/io/onedev/server/plugin/pack/gem/GemPackHandler.java","lineNumber":152,"sourceCode":"\t\t\t\tcheckProject(projectId, true);\n\t\t\t});\n\t\t\tvar tempFile = FileUtils.createTempFile(\"upload\", \"gem\");\n\t\t\ttry {\n\t\t\t\ttry (var os = new BufferedOutputStream(new FileOutputStream(tempFile), BUFFER_SIZE)) {\n\t\t\t\t\tIOUtils.copy(request.getInputStream(), os);\n\t\t\t\t} catch (IOException e) {\n\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t}\n\n\t\t\t\tbyte[] metadataBytes = null;\n\t\t\t\ttry (var is = new TarArchiveInputStream(new BufferedInputStream(new FileInputStream(tempFile), BUFFER_SIZE))) {\n\t\t\t\t\tTarArchiveEntry entry;\n\t\t\t\t\twhile ((entry = is.getNextTarEntry()) != null) {\n\t\t\t\t\t\tif (entry.getName().equals(\"metadata.gz\")) {\n\t\t\t\t\t\t\tvar baos = new ByteArrayOutputStream();\n\t\t\t\t\t\t\tvar copied = copyWithMaxSize(new GZIPInputStream(is), baos, MAX_METADATA_SIZE);\n\t\t\t\t\t\t\tif (copied == -1)\n\t\t\t\t\t\t\t\tthrow new ClientException(SC_NOT_ACCEPTABLE, \"Metadata exceeds maximum size: \" + MAX_METADATA_SIZE);\n\t\t\t\t\t\t\tmetadataBytes = baos.toByteArray();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (IOException e) {\n\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t}\n\t\t\t\tif (metadataBytes == null)\n\t\t\t\t\tthrow new ClientException(SC_BAD_REQUEST, \"Metadata not found\");\n\n\t\t\t\tString name = null;\n\t\t\t\tString version = null;\n\t\t\t\tString platform = null;\n\t\t\t\tvar metadata = (MappingNode) new Yaml().compose(new InputStreamReader(new ByteArrayInputStream(metadataBytes)));\n\t\t\t\tfor (var tuple : metadata.getValue()) {\n\t\t\t\t\tvar keyNode = (ScalarNode) tuple.getKeyNode();\n\t\t\t\t\tif (keyNode.getValue().equals(\"name\")) {\n\t\t\t\t\t\tname = ((ScalarNode) tuple.getValueNode()).getValue();","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-plugin/server-plugin-pack-gem/src/main/java/io/onedev/server/plugin/pack/gem/GemPackHandler.java#L134-L170","documentation":"While uploading a gem, GemPackHandler scans the tar for metadata.gz and inflates it with a hard size cap (MAX_METADATA_SIZE). copyWithMaxSize signals overflow with -1 and the handler throws a 406 ClientException because the decompressed metadata would exceed the allowed limit. This guards against decompression bombs.","triggerScenarios":"Pushing a gem package whose metadata.gz decompresses to more than MAX_METADATA_SIZE bytes — e.g. an extremely large gemspec, or a malicious/corrupt archive with a compression bomb named metadata.gz.","commonSituations":"Building gems with huge embedded files listed in the gemspec; repackaging legacy gems with oversized metadata; uploading a maliciously crafted .gem to test/abuse the registry.","solutions":["Shrink the gem's metadata (trim gemspec: files list, description, dependencies) and rebuild.","Reduce what gets packaged (use gemspec.files/filters to exclude large generated files).","If legitimately huge metadata is required, increase the registry's metadata size limit in the plugin configuration/server code."],"exampleFix":"# before\ngemspec.files = Dir[\"**/*\"]\n# after\ngemspec.files = Dir[\"lib/**/*.rb\", \"bin/*\", \"*.gemspec\"]","handlingStrategy":"validation","validationCode":"# check decompressed metadata size before upload\nsize=$(tar -xOf mygem.gem metadata.gz | gunzip | wc -c)\n[ \"$size\" -lt 1048576 ] || { echo 'metadata too large'; exit 1; }","typeGuard":null,"tryCatchPattern":"try { upload(gemFile) } catch (e) { if (e.httpStatus === 406 && /Metadata exceeds maximum size/.test(e.message)) { rebuildWithSmallerMetadata(); retry(); } else { throw e; } }","preventionTips":["Keep gemspec files/description minimal to keep metadata small.","Pre-check metadata size in CI before publishing.","Never upload untrusted third-party .gem files without inspecting metadata.gz."],"tags":["gem","package-upload","size-limit","payload"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}