AI-generated audit finding — this issue was opened from an automated security/correctness audit. It has not been triaged by a human yet; verify the reasoning, reproducibility, and severity before acting on it.
Low: AsyncEnumerablePipeReader.Complete fire-and-forgets enumerator disposal, so cleanup failures can become unobserved — NARROWED
Affected code:
Verification:
Partially confirmed, and narrowed from the original wording.
The concrete issue is the discarded task. If a caller-provided async enumerator throws from DisposeAsync(), that exception has no observer because Complete() returns void and the internal cleanup task is explicitly ignored. In practice this means a cleanup failure can surface later as an unobserved task exception rather than at the point where IceRPC completes the payload.
I did not confirm the broader "not thread-safe" claim as a standalone defect. The surrounding OutgoingRequest, IncomingRequest, and payload-reader lifecycles in this repository are explicitly single-owner and not thread-safe by contract, so the unsynchronized _isCompleted guard is better understood as an implementation assumption than as a verified bug on its own.
Impact:
- Exceptions thrown by a caller's async-enumerator cleanup path can be detached from the originating operation.
- Cleanup failures are harder to diagnose because they are not surfaced through the
Complete() call that triggered disposal.
Recommendation:
- Ensure the cleanup task cannot fault unobserved. The simplest fix is to wrap
_asyncEnumerator.DisposeAsync() in try/catch and route failures to a known observer.
- If cleanup failures should be actionable, redesign this path so the owner can await disposal instead of forcing it through a fire-and-forget
Complete().
- Add a regression test with an async enumerator whose
DisposeAsync() throws.
Status: Valid, Low severity (narrowed from the original Medium finding).
Source report: src-IceRpc.Slice-audit-2026-04-14.md (finding ``AsyncEnumerablePipeReader.Complete fire-and-forgets enumerator disposal, so cleanup failures can become unobserved — **NARROWED**)
Severity (auditor-assigned): Low
Low:
AsyncEnumerablePipeReader.Completefire-and-forgets enumerator disposal, so cleanup failures can become unobserved — NARROWEDAffected code:
CompletelaunchesDisposeEnumeratorAsync()and discards the returned taskDisposeEnumeratorAsyncswallows_moveNextfailures and then awaits_asyncEnumerator.DisposeAsync()without observing or catching a fault from that callVerification:
Partially confirmed, and narrowed from the original wording.
The concrete issue is the discarded task. If a caller-provided async enumerator throws from
DisposeAsync(), that exception has no observer becauseComplete()returnsvoidand the internal cleanup task is explicitly ignored. In practice this means a cleanup failure can surface later as an unobserved task exception rather than at the point where IceRPC completes the payload.I did not confirm the broader "not thread-safe" claim as a standalone defect. The surrounding
OutgoingRequest,IncomingRequest, and payload-reader lifecycles in this repository are explicitly single-owner and not thread-safe by contract, so the unsynchronized_isCompletedguard is better understood as an implementation assumption than as a verified bug on its own.Impact:
Complete()call that triggered disposal.Recommendation:
_asyncEnumerator.DisposeAsync()intry/catchand route failures to a known observer.Complete().DisposeAsync()throws.Status: Valid, Low severity (narrowed from the original Medium finding).
Source report: src-IceRpc.Slice-audit-2026-04-14.md (finding ``AsyncEnumerablePipeReader.Complete
fire-and-forgets enumerator disposal, so cleanup failures can become unobserved — **NARROWED**)Severity (auditor-assigned): Low