{"record":{"id":"4361ac7c827a8e59","repo":"rustfs/rustfs","slug":"remote-tier-returned-an-oversized-object-version-i","errorCode":null,"errorMessage":"remote tier returned an oversized object version id header","messagePattern":"remote tier returned an oversized object version id header","errorType":"validation","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"crates/ecstore/src/client/provider_versions.rs","lineNumber":185,"sourceCode":"                }\n            });\n        };\n        if value == \"null\" {\n            return Ok(RemoteVersion::SuspendedNull);\n        }\n        Ok(RemoteVersion::Exact(value.to_string()))\n    }\n}\n\npub(crate) fn validate_remote_version_id(version_id: &str) -> Result<(), Error> {\n    if version_id.is_empty() {\n        return Err(Error::new(\n            ErrorKind::InvalidData,\n            \"remote tier returned an empty object version id header\",\n        ));\n    }\n    if version_id.len() > MAX_REMOTE_VERSION_ID_LEN {\n        return Err(Error::new(\n            ErrorKind::InvalidData,\n            \"remote tier returned an oversized object version id header\",\n        ));\n    }\n    if version_id.chars().any(char::is_control) {\n        return Err(Error::new(\n            ErrorKind::InvalidData,\n            \"remote tier returned an object version id containing control characters\",\n        ));\n    }\n    Ok(())\n}\n\n#[cfg(test)]\nmod tests {\n    use super::{BucketVersioningState, ConditionalCreateCapability, ProviderVersionCapabilities, RemoteVersion};\n    use http::{HeaderMap, HeaderValue};\n","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/rustfs/rustfs/blob/9e6e02ea09c86bedf44c7bd64a74ea02a0cff1de/crates/ecstore/src/client/provider_versions.rs#L167-L203","documentation":"validate_remote_version_id caps remote version IDs at MAX_REMOTE_VERSION_ID_LEN (1024 bytes in crates/ecstore/src/client/provider_versions.rs:23); a longer raw version header is rejected as InvalidData. Real S3 version IDs are short base64 strings, so an oversized header signals a broken or hostile endpoint, and accepting it would let unbounded data into object metadata.","triggerScenarios":"A remote-tier object response carries a version-id header longer than 1024 characters - garbage appended by a malfunctioning gateway, error text placed in the header slot by a non-S3 service, or deliberately malformed responses from an adversarial endpoint.","commonSituations":"Buggy load balancers appending data to headers; tier endpoints that are not S3 responding with their own error payloads; fuzzing or hostile middleboxes on the path to the tier.","solutions":["Inspect the raw headers of the failing response to confirm the header's actual content and length.","Point the tier at a compliant S3 endpoint or remove the misbehaving intermediary.","Only raise the limit if a legitimate provider genuinely emits longer IDs, and do it deliberately with a documented reason - never remove the cap."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match provider_caps.raw_version_id(&headers) {\n    Ok(v) => Ok(v),\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => {\n        tracing::error!(event = \"remote_version_header_invalid\", result = \"rejected\", \"oversized version-id header from tier\");\n        Err(e)\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Monitor response-header sizes on tier paths; sudden growth signals a broken intermediary.","Keep the 1024-byte cap - legitimate S3 version IDs are far shorter.","Isolate tier traffic from load balancers known to append data to headers."],"tags":["rust","s3","remote-tier","versioning","header-validation","limits"],"backgroundTag":"invalid-response-header","analyzedSha":"9e6e02ea09c86bedf44c7bd64a74ea02a0cff1de","analyzedAt":"2026-08-16T20:34:17.560Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}