For the complete documentation index, see llms.txt. This page is also available as Markdown.

75032 bc insight rpc enable admin false is a dead flag admin namespace registered regardless on every base consensus binary

Submitted on Apr 26th 2026 at 19:59:11 UTC by @gzeon for Audit Comp | Base Azul

  • Report ID: #75032

  • Report Type: Blockchain/DLT

  • Report severity: Insight

  • Target: https://github.com/base/base/tree/v0.8.0-rc.24

  • Impacts:

    • Temporary freezing of network transactions by delaying one block by 500% or more of the average block time of the preceding 24 hours beyond standard difficulty adjustments

Description

Brief

The base-consensus CLI flag --rpc.enable-admin is parsed (crates/client/cli/src/rpc.rs:32), stored on RpcBuilder.enable_admin (crates/consensus/rpc/src/config.rs:13), and never read by the runtime gate at crates/consensus/service/src/actors/rpc/actor.rs:120-123. The gate is if let Some(network_admin) = network_admin, where network_admin is unconditionally Some(_) for full-node mode (crates/consensus/service/src/service/node.rs:552). The admin namespace is registered on every base-consensus listener regardless of the operator's enable_admin selection, including admin_stopSequencer, which halts block production by setting self.is_active = false (crates/consensus/service/src/actors/sequencer/admin_api_impl.rs:191).

The default consensus RPC binding is 0.0.0.0:9545 (crates/client/cli/src/rpc.rs:25). The middleware stack is timeout + concurrency + load-shed + healthz (actors/rpc/actor.rs:67-89); no authentication. Any caller able to send an HTTP POST to the bound port can call any registered admin method. The defect ships in every base-consensus binary distributed to validators, third-party operators, and HA cluster deployments — not Coinbase-operated infrastructure.

Vulnerability Details

The flag's lifecycle:

// crates/client/cli/src/rpc.rs:31-32 — CLI parsing
#[arg(long = "rpc.enable-admin", env = "BASE_NODE_RPC_ENABLE_ADMIN")]
pub enable_admin: bool,

// crates/client/cli/src/rpc.rs:72 — wired into RpcBuilder
enable_admin: args.enable_admin,

// crates/consensus/rpc/src/config.rs:13 — field on RpcBuilder
pub enable_admin: bool,

The runtime gate that decides whether to register the admin module:

network_admin is unconditionally Some(_) in full-node mode at crates/consensus/service/src/service/node.rs:552. --rpc.enable-admin=false has no runtime effect.

Impact

Severity: HIGH (network-transaction freezing exceeding 500% of average block time).

Methods reachable unauthenticated on the bound listener (mutating only):

An unauthenticated caller who reaches the consensus RPC of a sequencer-mode node can invoke admin_stopSequencer even when the operator did not enable admin RPC. This sets is_active = false; the sequencer build loop only emits new payloads while is_active is true (actor.rs sequencer loop), so block production remains stopped until an authorized operational action restarts sequencing. On Base's 2 s block time, any stop lasting over 10 s maps directly to the 500% one-block-delay HIGH bracket. The bug also exposes admin_overrideLeader (HA conductor leader override), admin_setRecoverMode, admin_resetDerivationPipeline, and admin_startSequencer (the latter is partially gated downstream — it requires the supplied head to match the engine's current unsafe head per admin_api_impl.rs:158-170, so it is restart-only, not arbitrary-head injection).

The --rpc.enable-admin flag is the documented mechanism to separate the admin namespace from the read namespaces (optimism_* always, ws_* when ws_enabled) on the same listener. The HA Conductor Cluster topology distributed in this codebase requires inter-node admin RPC for leader election (admin_overrideLeader exists for this purpose). Operators who deploy mixed-purpose listeners — public read endpoints for downstream consumers + internal admin for HA — rely on the flag to gate the namespaces independently. The dead gate breaks that separation: the admin namespace registers on every listener regardless of operator intent.

The defect is in published binary code, code-review-discoverable, and independent of any operator's deployment. The "Base-operated infrastructure" exclusion does not apply.

References

  • Dead-flag chain: crates/client/cli/src/rpc.rs:32, 72; crates/consensus/rpc/src/config.rs:13; crates/consensus/service/src/actors/rpc/actor.rs:120-123; crates/consensus/service/src/service/node.rs:552.

  • admin_stopSequencer flips is_active at crates/consensus/service/src/actors/sequencer/admin_api_impl.rs:191.

  • HTTP middleware stack (no auth): crates/consensus/service/src/actors/rpc/actor.rs:67-89.

  • Default 0.0.0.0 binding: crates/client/cli/src/rpc.rs:25.

Bug introduction

4d7d12db chore(cli): full cli arg port (#475) (2026-01-14) introduced the RpcArgs.enable_admin flag. c9758ee1 feat(devnet): Three-Node HA Conductor Cluster (#1542) (2026-03-21) introduced crates/consensus/service/src/actors/rpc/actor.rs with the runtime gate that never reads the flag. Present in v0.7.0-rc.1 through v0.8.0-rc.24; never patched.

Proof of Concept

The test below replicates the runtime gating logic from RpcActor::start (crates/consensus/service/src/actors/rpc/actor.rs:120-123) verbatim, with RpcBuilder.enable_admin: false (the operator's documented opt-out) and network_admin: Some(_) (full-node mode). It launches the same jsonrpsee server RpcActor uses, then probes every admin method. Any response other than -32601 Method not found proves the method is registered on the listener despite enable_admin: false. A control method that genuinely does not exist returns -32601, isolating the registration outcome to the dead gate.

Append to the existing mod tests block of crates/consensus/service/src/actors/rpc/actor.rs. Add serde_json.workspace = true to crates/consensus/service/Cargo.toml under [dev-dependencies].

Verbatim cargo output (against v0.8.0-rc.24 HEAD 819ea306):

All nine admin methods are registered with enable_admin: false; the control returns -32601.

Fix

After this change, the PoC's admin-method probes return -32601 and the control matches. Admin methods become reachable only when the operator explicitly sets --rpc.enable-admin.

Was this helpful?