seungpyoson opened a new issue, #870:
URL: https://github.com/apache/arrow-rs-object-store/issues/870

   **Is your feature request related to a problem or challenge? Please describe 
what you are trying to do.**
   
   Could the 0.13 line receive a maintenance release containing the quick-xml 
security update?
   
   AI assistance: Codex generated the candidate dependency edit, regression 
test and this request text, and ran the validation not attributed to Claude 
Code. Claude Code generated the diagnostic probes and ran the separately 
attributed validation below; Codex and Claude also provided AI reviews. The 
reported execution results are backed by retained command logs.
   
   object_store 0.13.2 requires quick-xml `^0.39.0`, which excludes the fixes 
for [RUSTSEC-2026-0194](https://rustsec.org/advisories/RUSTSEC-2026-0194.html) 
and [RUSTSEC-2026-0195](https://rustsec.org/advisories/RUSTSEC-2026-0195.html). 
DataFusion 55.x and parquet 59.x consumers constrained to object_store 
`^0.13.2` could adopt a compatible patch release through dependency resolution. 
Applications with an exact `=0.13.2` pin would also need to edit that pin.
   
   The goal is to replace the affected quick-xml versions and clear advisory 
checks for consumers still on 0.13. I understand the [severity discussion in 
#786](https://github.com/apache/arrow-rs-object-store/issues/786#issuecomment-4891595702):
 cloud-provider responses are normally trusted. No deployment exploit has been 
demonstrated by this work.
   
   **Describe the solution you'd like**
   
   Would maintainers support a security-focused 0.13 maintenance release and 
create `release/0.13` from v0.13.2 for contribution PRs?
   
   I recognize that [#672 was closed on June 
11](https://github.com/apache/arrow-rs-object-store/issues/672#issuecomment-4684399232)
 after breaking changes landed on main. That decision predates these 
advisories. This request asks whether a maintenance release is now appropriate, 
following the contribution/release process used for #582.
   
   The proposed dependency requirement is `quick-xml = "0.41.0"`: Cargo's 
`^0.41.0` range, restricted to 0.41.x. It keeps the existing `serialize` and 
`overlapped-lists` features and uses the same quick-xml requirement already 
shipped by object_store 0.14.1 and 0.14.2. It excludes quick-xml 0.42, which 
declares Rust 1.86, above object_store's declared 1.85.
   
   If maintainers agree, I can contribute the dependency update and separate 
current-stable CI repairs, following #597's maintenance-branch precedent. The 
namespace regression below is available as an optional test contribution. The 
pre-existing MSRV failure in code enabled by `aws`, `gcp` or `azure` described 
below also needs resolution or an explicit maintainer decision before release 
claims.
   
   **Describe alternatives you've considered**
   
   - Upgrade the complete dependency graph to official object_store 0.14.1 or 
later, which includes #785. Parent dependencies still requiring 0.13 can retain 
the affected copy if only a direct dependency is upgraded.
   - Use temporary advisory ignores, as 
[arrow-rs#10267](https://github.com/apache/arrow-rs/pull/10267) and 
[DataFusion#23298](https://github.com/apache/datafusion/pull/23298) did. A 
compatible fixed release would let 0.13 consumers remove those ignores.
   
   Related to #672, #582, #597, #786, #787 and #785. #786 and #787 were 
resolved on main by #785; this request concerns 0.13.
   
   **Additional context**
   
   The attached local candidate is based on v0.13.2, 
`7a65b75b0d26fd8a282999462cb7030fb85fdcc3`. It changes the requirement and adds 
an S3 listing regression. No object_store public API declarations or feature 
wiring change.
   
   Parsing behavior does change. The upgrade crosses [quick-xml 
0.40.0](https://github.com/tafia/quick-xml/blob/v0.41.0/Changelog.md), which 
changed XML-version handling and normalization rules, raised quick-xml's MSRV 
to 1.79, and removed deprecated NsReader methods unused by object_store. In a 
local S3-list probe generated and executed by Claude Code, an XML 1.0 key 
containing literal U+2028 and U+0085 fails path validation with 0.39.4 but is 
preserved and accepted with 0.41.0. More than 256 namespace declarations on one 
element also becomes a deliberate rejection. This does not establish how a real 
provider encodes those Unicode keys.
   
   Validation on macOS aarch64:
   - Rust 1.98.1: formatting passed; `cargo test --locked --lib --all-features` 
reported 185 passed and 4 ignored, including a separate rerun executed by 
Claude Code.
   - Identical final regression source failed with 0.39.4 by accepting 257 
declarations and passed with 0.41.0. Counts 0, 1 and 256 preserve the expected 
object; 257 and 512 return the namespace-limit error. This checks 
RUSTSEC-2026-0195's per-element limit through the S3 list path. It does not 
test total memory bounds, other XML entry points, or provider responses.
   - Only quick-xml changed between the retained test lockfiles. `--locked` 
refers to generated local lockfiles retained for repeatable comparisons; no 
Cargo.lock is proposed for the upstream patch.
   - A debug-build probe generated and executed by Claude Code through S3 
listing observed 103→5,343 ms on 0.39.4 versus 20→45 ms on 0.41.0 as distinct 
attributes increased from 2,500 to 20,000. This supplies additional evidence 
for the 0194 path; it is a diagnostic probe, not a release-mode benchmark or 
regression assertion.
   - In Claude Code's Rust 1.85.0 runs, quick-xml 0.41.0 passed `cargo check`, 
then both baseline and candidate failed `cargo check --locked --all-features 
--lib` at `src/client/token.rs:81/88` on let chains. The existing 
default-feature MSRV job does not check this `aws`/`gcp`/`azure` path. 
All-feature Rust 1.85 compatibility is not established.
   - Rust 1.98.1 Clippy with all features/targets and `-D warnings` failed with 
the same six diagnostics on pristine v0.13.2 and the candidate: four redundant 
format references in Azure code and two redundant into_iter calls in 
client/list.rs. These checks remain failed. Clippy has not been rerun on Rust 
1.99.0. The latest-stable CI configuration makes repairs relevant to a 
maintenance branch; no such branch CI has been run.
   
   Claude Code also ran `cargo +1.98.1 deny --all-features --locked check 
--config $R/deny-advisories.toml advisories` on private baseline and candidate 
copies, where `$R` was the private review directory. The dedicated 
advisories-only configuration was:
   
   ```toml
   [advisories]
   yanked = "warn"
   ignore = []
   ```
   
   Using cargo-deny 0.19.0 and advisory database 
`ef6173cbc5c50ec8166f9a5b28f07834144373ee` (October 3), that scan reported only 
RUSTSEC-2026-0194 and RUSTSEC-2026-0195 on the baseline and `advisories ok` on 
the candidate. This result covers that standalone candidate graph, dedicated 
configuration and database snapshot.
   
   The repository's default `deny.toml` fails before scanning on both copies: 
cargo-deny 0.19.0 rejects its `unmaintained = "warn"` setting. The 
default-config check remains failed. The probe code, dedicated scan 
configuration and run logs are available on request.
   
   Cloud/emulator integration, Linux, an OOM reproduction, a release-mode 
benchmark, and downstream integration with a patched object_store remain unrun.
   
   The unpublished candidate is `343d8446b5b4649167dcc718a56ca8b1cc99b857`; it 
cannot be fetched from upstream. The complete patch follows for inspection. 
Dependency, CI-repair and optional test contributions would be separated before 
PR submission.
   
   <details>
   <summary>Candidate patch against v0.13.2</summary>
   
   ```diff
   diff --git a/Cargo.toml b/Cargo.toml
   index 6a18922..149d460 100644
   --- a/Cargo.toml
   +++ b/Cargo.toml
   @@ -52,7 +52,7 @@ http-body-util = { version = "0.1.2", optional = true }
    httparse = { version = "1.8.0", default-features = false, features = 
["std"], optional = true }
    hyper = { version = "1.2", default-features = false, optional = true }
    md-5 = { version = "0.10.6", default-features = false, optional = true }
   -quick-xml = { version = "0.39.0", features = ["serialize", 
"overlapped-lists"], optional = true }
   +quick-xml = { version = "0.41.0", features = ["serialize", 
"overlapped-lists"], optional = true }
    rand = { version = "0.10", default-features = false, features = ["std", 
"std_rng", "thread_rng"], optional = true }
    reqwest = { version = "0.12", default-features = false, features = 
["rustls-tls-native-roots", "http2"], optional = true }
    ring = { version = "0.17", default-features = false, features = ["std"], 
optional = true }
   diff --git a/src/aws/client.rs b/src/aws/client.rs
   index ed6e8c4..ad1348c 100644
   --- a/src/aws/client.rs
   +++ b/src/aws/client.rs
   @@ -1073,6 +1073,46 @@ mod tests {
            }
        }
    
   +    #[tokio::test]
   +    async fn test_list_namespace_limit() {
   +        // RUSTSEC-2026-0195: the XML reader must bound namespace 
declarations
   +        // before deserialization can allocate one binding per attribute.
   +        for count in [0, 1, 256, 257, 512] {
   +            let mock = MockServer::new().await;
   +            let namespaces = (0..count)
   +                .map(|index| format!(" 
xmlns:n{index}=\"urn:test:{index}\""))
   +                .collect::<String>();
   +            let body = format!(
   +                
"<ListBucketResult{namespaces}><Contents><Key>test</Key><Size>7</Size>\
   +                 
<LastModified>2026-01-01T00:00:00Z</LastModified></Contents></ListBucketResult>"
   +            );
   +            mock.push(Response::builder().status(200).body(body).unwrap());
   +
   +            let http = 
reqwest::Client::builder().no_proxy().build().unwrap();
   +            let client = Arc::new(S3Client::new(
   +                default_headers_config(&mock),
   +                HttpClient::new(http),
   +            ));
   +            let result = client.list_request(None, 
Default::default()).await;
   +            mock.shutdown().await;
   +
   +            if count <= 256 {
   +                let response = result.unwrap();
   +                assert_eq!(response.result.objects.len(), 1);
   +                assert_eq!(response.result.objects[0].location, 
Path::from("test"));
   +                assert_eq!(response.result.objects[0].size, 7);
   +            } else {
   +                let error = result
   +                    .expect_err(&format!("accepted {count} namespace 
declarations"))
   +                    .to_string();
   +                assert!(
   +                    error.contains("start tag declares more than 256 
namespace bindings"),
   +                    "{count}: {error}"
   +                );
   +            }
   +        }
   +    }
   +
        #[tokio::test]
        async fn test_default_headers_signed_request() {
            let mock = MockServer::new().await;
   ```
   
   </details>
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to