Skip to content

[Audit-Medium] named server registration can cross-wire dispatchers w… #4423

@pepone

Description

@pepone

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.

Medium: named server registration can cross-wire dispatchers when the same optionsName is reused — CONFIRMED

Affected code:

Verification:

Confirmed. Two failure modes arise from the same root cause (shared mutable ServerOptions instance per optionsName):

  1. AddIceRpcServer(optionsName, IDispatcher) (line 93-101) wires the dispatcher through IConfigureOptions<ServerOptions> at line 99. Two calls with the same name install two Configure callbacks on the same named options; the last one wins when the options are built.
  2. AddIceRpcServer(optionsName, Action<IDispatcherBuilder>) (line 113-132) resolves the ServerOptions from IOptionsMonitor<ServerOptions>.Get(optionsName) — which returns the same cached instance on every call — and mutates options.ConnectionOptions.Dispatcher at line 125 directly. Two such registrations produce two Server singletons that share one ServerOptions / ConnectionOptions; both listeners end up routing into whichever dispatcher wrote last.

Because DI containers commonly return the last registration for a non-enumerable GetRequiredService<Server>(), the first AddIceRpcServer call's factory might never run at resolve time — but any code that enumerates (GetServices<Server>(), tests, IHostedService registration of both) runs both factories and leaves the options in the last-written state.

Impact:

  • Requests dispatched to the wrong service graph on the wrong listener.
  • Endpoint exposure can drift silently from the configured server address, since dispatchers may encode routing/authorization assumptions.
  • The bug is invisible at registration time and only surfaces at runtime.

Recommendation:

  • Clone ServerOptions (and its nested ConnectionOptions) before mutating Dispatcher inside the factory. Server could also defensively copy options in its constructor, but the DI package owns the named-options contract so the fix belongs here.
  • Reject duplicate server registrations for the same optionsName, or document/enforce that names must be unique. A simple TryAdd-style guard would catch the common case.
  • Add tests covering two server registrations with the same name and asserting that each receives its own dispatcher.

Status: Valid, Medium severity.


Source report: src-IceRpc.Extensions.DependencyInjection-audit-2026-04-14.md (finding named server registration can cross-wire dispatchers when the same optionsName is reused — **CONFIRMED**)

Severity (auditor-assigned): Medium

Metadata

Metadata

Assignees

Labels

ai-auditAI-generated audit finding — needs human triage

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions