OpenZeppelin / OpenZeppelin/guardian

GET /pubkey and GetPubkey silently serve the Falcon identity for an unrecognized scheme

Open
#480 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Rust
Stars
10
Forks
20
Avg merge
2d 11h
Merged PRs (30d)
43

Description

GET /pubkey and GetPubkey silently serve the Falcon identity for an unrecognized scheme

Summary

Both acknowledgement-pubkey handlers treat any scheme value that is not
ecdsa as Falcon, including values that are neither. A typo (scheme=ecsda,
scheme=falcon2, scheme=bogus) returns HTTP 200 with the Falcon
acknowledgement commitment, so a caller that meant ECDSA silently verifies
against the wrong identity instead of getting an error.

Confirmed live: scheme=bogus returns the Falcon commitment.

Where

Identical fall-through in both transports:

  • crates/server/src/api/grpc.rs:240-243
  • crates/server/src/api/http.rs:474-477
let scheme = match req.scheme.as_deref() {
    Some(s) if s.eq_ignore_ascii_case("ecdsa") => SignatureScheme::Ecdsa,
    _ => SignatureScheme::Falcon,
};

The strict parser already exists and is unused here:
SignatureScheme::from (crates/shared/src/lib.rs:32-38) accepts falcon and
ecdsa case-insensitively and returns
Err("unsupported signature scheme: {value}") otherwise.

Why it matters

GUARDIAN holds one acknowledgement identity per signature scheme, and an
account's guardian storage slot holds the one matching its own scheme. A
caller that asks for the wrong identity and is served a valid-looking answer
gets a commitment mismatch far from the cause. That is exactly the
misdiagnosis pattern that #432 / F13 produced on the client side: the failure
pointed at the endpoint rather than at which identity was queried.

Typed SDK callers are not exposed (the Rust client passes
SignatureScheme::as_str(); the TypeScript client's getPubkey(scheme?: SignatureScheme) is typed). The exposure is hand-rolled HTTP and gRPC
callers: curl, operator scripts, and non-first-party integrations.

Proposed behaviour

  • scheme absent: keep serving Falcon. This is the documented default
    (optional string scheme in guardian.proto:235-237, and the /pubkey doc
    comment in http.rs) and must not change.
  • scheme present and recognized (falcon / ecdsa, case-insensitive):
    unchanged.
  • scheme present and unrecognized: reject, naming the value and the
    accepted set. HTTP 400, gRPC INVALID_ARGUMENT.

Delegating to SignatureScheme::from gives all three, and removes the
duplicated inline match from both transports.

Scope note

This adds a new error path to a public endpoint on both transports, so it is a
wire-contract change and needs the AGENTS.md §4 workflow: proto/HTTP surface,
OpenAPI (docs/openapi-client.json, crates/server/src/openapi.rs), both
clients, the error-code reference in docs/TROUBLESHOOTING.md, and tests on
both handlers (grpc.rs:724-740, http.rs:882-892 already cover the
absent/ecdsa cases and are the place to add the rejected case).

Found while reviewing #432 (endpoint commitment scheme binding); pre-existing
and out of scope for that fix.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with SignatureScheme::from in crates/shared/src/lib.rs, then inspect the duplicated scheme handling in crates/server/src/api/grpc.rs and crates/server/src/api/http.rs. Review the existing handler tests at grpc.rs:724-740 and http.rs:882-892, along with the AGENTS.md §4 workflow and named client, OpenAPI, and troubleshooting files. Done means absent and recognized schemes retain their behavior while an unrecognized value returns HTTP 400 or gRPC INVALID_ARGUMENT with tests covering both transports.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.