Skip to content

Commit 8b37687

Browse files
authored
fix: perform certificate delegation canister range check unconditionally (#1083)
* fix: perform certificate delegation canister range check unconditionally * chore: update changelog
1 parent 00e4445 commit 8b37687

File tree

4 files changed

+22
-20
lines changed

4 files changed

+22
-20
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- fix: add declaration maps and typescript source code to published packages
99
- feat: enables type inference for the arguments and return types of `FuncClass`.
1010
- feat: enables type inference for the fields of `ServiceClass`.
11+
- fix: perform the canister range checks unconditionally for delegations when constructing a `Certificate` instance.
1112

1213
## [3.1.0] - 2025-07-24
1314

packages/agent/src/canisterStatus/index.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -308,9 +308,7 @@ export const fetchNodeKeys = (
308308

309309
const canisterInRange = check_canister_ranges({ canisterId, subnetId, tree });
310310
if (!canisterInRange) {
311-
throw TrustError.fromCode(
312-
new CertificateNotAuthorizedErrorCode(canisterId, delegation.subnet_id),
313-
);
311+
throw TrustError.fromCode(new CertificateNotAuthorizedErrorCode(canisterId, subnetId));
314312
}
315313

316314
const subnetLookupResult = lookup_subtree(['subnet', delegation.subnet_id, 'node'], tree);

packages/agent/src/certificate.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {
1818
import { Principal } from '@dfinity/principal';
1919
import * as bls from './utils/bls.ts';
2020
import { decodeTime } from './utils/leb.ts';
21-
import { MANAGEMENT_CANISTER_ID } from './agent/index.ts';
2221
import { bytesToHex, concatBytes, hexToBytes, utf8ToBytes } from '@noble/hashes/utils';
2322
import { uint8Equals } from './utils/buffer.ts';
2423
import { sha256 } from '@noble/hashes/sha2';
@@ -304,25 +303,25 @@ export class Certificate {
304303

305304
await cert.verify();
306305

307-
if (this._canisterId.toString() !== MANAGEMENT_CANISTER_ID) {
308-
const canisterInRange = check_canister_ranges({
309-
canisterId: this._canisterId,
310-
subnetId: Principal.fromUint8Array(new Uint8Array(d.subnet_id)),
311-
tree: cert.cert.tree,
312-
});
313-
if (!canisterInRange) {
314-
throw TrustError.fromCode(
315-
new CertificateNotAuthorizedErrorCode(this._canisterId, d.subnet_id),
316-
);
317-
}
306+
const subnetIdBytes = d.subnet_id;
307+
const subnetId = Principal.fromUint8Array(subnetIdBytes);
308+
309+
const canisterInRange = check_canister_ranges({
310+
canisterId: this._canisterId,
311+
subnetId,
312+
tree: cert.cert.tree,
313+
});
314+
if (!canisterInRange) {
315+
throw TrustError.fromCode(new CertificateNotAuthorizedErrorCode(this._canisterId, subnetId));
318316
}
317+
319318
const publicKeyLookup = lookupResultToBuffer(
320-
cert.lookup_path(['subnet', d.subnet_id, 'public_key']),
319+
cert.lookup_path(['subnet', subnetIdBytes, 'public_key']),
321320
);
322321
if (!publicKeyLookup) {
323322
throw TrustError.fromCode(
324323
new MissingLookupValueErrorCode(
325-
`Could not find subnet key for subnet 0x${bytesToHex(d.subnet_id)}`,
324+
`Could not find subnet key for subnet ID ${subnetId.toText()}`,
326325
),
327326
);
328327
}

packages/agent/src/errors.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { Principal } from '@dfinity/principal';
2-
import { type HttpDetailsResponse, type NodeSignature, type ReplicaRejectCode } from './agent/api.ts';
2+
import {
3+
type HttpDetailsResponse,
4+
type NodeSignature,
5+
type ReplicaRejectCode,
6+
} from './agent/api.ts';
37
import { type RequestId } from './request_id.ts';
48
import { type Expiry, type RequestStatusResponseStatus } from './agent/http/index.ts';
59
import { type HttpHeaderField } from './agent/http/types.ts';
@@ -237,14 +241,14 @@ export class CertificateNotAuthorizedErrorCode extends ErrorCode {
237241

238242
constructor(
239243
public readonly canisterId: Principal,
240-
public readonly subnetId: Uint8Array,
244+
public readonly subnetId: Principal,
241245
) {
242246
super();
243247
Object.setPrototypeOf(this, CertificateNotAuthorizedErrorCode.prototype);
244248
}
245249

246250
public toErrorMessage(): string {
247-
return `The certificate contains a delegation that does not include the canister ${this.canisterId.toText()} in the canister_ranges field. Subnet ID: 0x${bytesToHex(this.subnetId)}`;
251+
return `The certificate contains a delegation that does not include the canister ${this.canisterId.toText()} in the canister_ranges field. Subnet ID: ${this.subnetId.toText()}`;
248252
}
249253
}
250254

0 commit comments

Comments
 (0)