Repository navigation
fix(ic-agent): return errors instead of panicking on malformed certified data; release 0.49.3 - #744
Merged
Merged
Conversation
…ied data A subnet can sign a certificate whose tree is well-formed but whose contents are not. Several lookups trusted that shape and panicked: - `lookup_incomplete_subnet`: `Principal::from_slice` on a node label longer than 29 bytes. - `lookup_canister_ranges`: `shard[0]` when `/canister_ranges/<id>` is a bare leaf. - `lookup_api_boundary_nodes`: `path[0]` when `/api_boundary_nodes` is a bare leaf. - `fetch_subnet_by_canister`: `Principal::from_slice` on the delegation's `subnet_id` (NNS-signed, so not reachable in practice). Use `Principal::try_from_slice` and reject unexpected path shapes with `CertificateVerificationFailed`, and add regression tests. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Bump all workspace crates 0.49.2 -> 0.49.3. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Rust 1.99 clippy flags `clippy::double_must_use` on the code generated by async-trait 0.1.89, which fails the lint job under `-D warnings` on every `#[async_trait]` trait. async-trait 0.1.92 no longer triggers it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🟢 Approval recommended
The targeted guards preserve valid-data behavior, regression tests cover the reported malformed-tree cases, and no blocking issues remain.
No open issues 🎉
What changed in this PR
This PR hardens ic-agent against malformed certified data by returning errors instead of panicking, and prepares release 0.49.3.
Changes:
- Adds fallible principal parsing and tree-path validation, with three malformed-tree regression tests.
- Updates workspace versions and release notes, including the earlier root-attested subnet-routing fix.
- Updates the locked
async-traitdependency and addssyn3 to address the reported Clippy failure.
| File | Description |
|---|---|
ic-agent/src/agent/response_authentication.rs |
Validates malformed node IDs and tree paths; adds regression tests. |
ic-agent/src/agent/mod.rs |
Returns an error for oversized delegation subnet IDs. |
CHANGELOG.md |
Documents the fixes in release 0.49.3. |
Cargo.toml |
Bumps workspace and internal dependency versions to 0.49.3. |
Cargo.lock |
Records release versions and the procedural-macro dependency update. |
Review effort: Balanced
lwshang
marked this pull request as ready for review
October 22, 2026 12:28
|
✅ No security or compliance issues detected. Reviewed everything up to 22a26f3. Security OverviewDetected Code Changes
|
raymondk
approved these changes
Oct 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A subnet can sign a certificate that verifies correctly but has an unexpected shape inside. Several lookups in
ic-agentassumed the shape and would panic. They now return anAgentError:lookup_incomplete_subnetPrincipal::from_slicepanics on a/subnet/<id>/node/<label>longer than 29 bytestry_from_slice→AgentError::PrincipalErrorlookup_canister_rangesshard[0]panics when/canister_ranges/<id>is a bare leafCertificateVerificationFailedlookup_api_boundary_nodespath[0]panics when/api_boundary_nodesis a bare leafCertificateVerificationFailedfetch_subnet_by_canisterPrincipal::from_slice(&delegation.subnet_id)panics on a blob longer than 29 bytestry_from_slice→AgentError::PrincipalErrorAffected public APIs:
Agent::fetch_subnet_by_id,Agent::fetch_subnet_by_canister(and thereforeget_subnet_by_canister),Agent::fetch_api_boundary_nodes_by_{canister,subnet}_id.Only a subnet that signs malformed state can trigger these. That matters for cloud engines, which are not trusted the way regular subnets are. The delegation
subnet_idcase is NNS-signed, so it isn't reachable in practice; this change just makes it fail gracefully. A core protocol teammate reported these issues.check_delegationalready handled the shard-path case safely; this change makes the other lookups consistent with it.Release
The second commit prepares 0.49.3. It bumps all workspace crates and
Cargo.lock, and cuts theUnreleasedchangelog section, which also contains #743.CI fix
The third commit bumps
async-traitfrom 0.1.89 to 0.1.92 inCargo.lock. Rust 1.99's clippy flagsdouble_must_useon code generated by#[async_trait], which brokelintfor any branch based onmain; the problem was already there before this PR. The new version pulls insyn3, and both crates need Rust 1.71 or newer, so the MSRV (1.88) is unaffected. I checked this withcargo +1.88.0 check --workspace.Testing
response_authentication.rsbuild malformed trees for the first three cases. Each test panics onmainand passes on this branch.cargo test -p ic-agent --lib: 61 passed.delegation.subnet_idcase has no test, because building it would require a delegation that passes verification.🤖 Generated with Claude Code