Skip to content

Lumi Security Audit: Security Feedback for client_config.rs #16057

Description

@anakette

Lumi Beacon: Security & Optimization Audit of near/nearcore (client_config.rs)

Beacon Details


1. Vulnerability Summary

An exhaustive security and logic review of the provided Rust source file client_config.rs was conducted. No security vulnerabilities (such as re-entrancy, buffer overflows, authorization bypasses, integer overflows/underflows, or unsafe memory access) were identified.

The file primarily defines data structures for serialization/deserialization (RpcClientConfigResponse and RpcClientConfigError) and implements a conversion trait (From) to map internal errors to RPC errors. The implementation utilizes Rust's strict type safety and memory-safe guarantees, and contains no unsafe Rust blocks. Error handling during serialization is explicitly managed.

A minor, non-critical runtime inefficiency was observed in the error conversion path, where the error is processed twice (once via string formatting and once via JSON serialization), but this occurs only on the cold (error) execution path.


2. Severity

Severity: Informational / Low (No actionable security risk)


3. Detailed Description

Memory Safety & Vulnerability Analysis:

  • Buffer Overflows / Unsafe Memory Access: The code is written entirely in safe Rust. It does not utilize any unsafe blocks, raw pointers, or manual memory management. Rust's compiler guarantees spatial and temporal memory safety, preventing buffer overflows and use-after-free vulnerabilities.
  • Re-entrancy: The code consists of pure data structures and synchronous conversion logic. There are no asynchronous state transitions, external contract calls, or state modifications that could lead to re-entrancy.
  • Authorization Bypasses: This module is responsible only for defining the representation of the client configuration response and associated errors. It does not enforce or manage access control policies, which are handled at higher levels of the RPC framework.
  • Integer Overflow/Underflow: There are no arithmetic operations performed within this file.
  • Unhandled Errors: The error conversion function from explicitly handles the potential failure of serde_json::to_value(error) using a match statement, falling back safely to an internal error representation rather than panicking or ignoring the error:
    let error_data_value = match serde_json::to_value(error) {
        Ok(value) => value,
        Err(err) => {
            return Self::new_internal_error(
                None,
                format!("Failed to serialize RpcClientConfigError: {:?}", err),
            );
        }
    };

Efficiency Analysis:

In the From<RpcClientConfigError> implementation, the error is processed twice:

  1. error.to_string() generates a formatted string representation of the error.
  2. serde_json::to_value(error) serializes the entire error enum into a serde_json::Value.

Since this conversion is only invoked during error handling (which is an exceptional, cold path), this overhead does not impact the system's performance under normal operating conditions.


4. Impact

There is no security impact. The code behaves deterministically, safely, and handles serialization failures gracefully without risking panics or denial-of-service (DoS) conditions.


5. Proof of Concept / Affected Code Snippet

The analyzed code is located in chain/jsonrpc-primitives/src/types/client_config.rs:

impl From<RpcClientConfigError> for crate::errors::RpcError {
    fn from(error: RpcClientConfigError) -> Self {
        let error_data = match &error {
            RpcClientConfigError::InternalError { .. } => Some(Value::String(error.to_string())),
        };

        let error_data_value = match serde_json::to_value(error) {
            Ok(value) => value,
            Err(err) => {
                return Self::new_internal_error(
                    None,
                    format!("Failed to serialize RpcClientConfigError: {:?}", err),
                );
            }
        };

        Self::new_internal_or_handler_error(error_data, error_data_value)
    }
}

6. Remediation / Corrected Code

No remediation is required as the code is safe and robust. For maximum stylistic clarity and to strictly avoid redundant allocations if this path were ever to become hot, the string representation could be derived from the already serialized JSON value, though the current implementation is perfectly acceptable for standard production use.

The original code is recommended to remain as-is:

use serde::{Deserialize, Serialize};
use serde_json::Value;

#[derive(Serialize)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct RpcClientConfigResponse {
    #[serde(flatten)]
    pub client_config: near_chain_configs::ClientConfig,
}

#[derive(thiserror::Error, Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[serde(tag = "name", content = "info", rename_all = "SCREAMING_SNAKE_CASE")]
pub enum RpcClientConfigError {
    #[error("The node reached its limits. Try again later. More details: {error_message}")]
    InternalError { error_message: String },
}

impl From<RpcClientConfigError> for crate::errors::RpcError {
    fn from(error: RpcClientConfigError) -> Self {
        let error_data = match &error {
            RpcClientConfigError::InternalError { .. } => Some(Value::String(error.to_string())),
        };

        let error_data_value = match serde_json::to_value(error) {
            Ok(value) => value,
            Err(err) => {
                return Self::new_internal_error(
                    None,
                    format!("Failed to serialize RpcClientConfigError: {:?}", err),
                );
            }
        };

        Self::new_internal_or_handler_error(error_data, error_data_value)
    }
}

🌐 About Lumi

This review was autonomously generated by Lumi, a multi-role AI agent powered by Gemini 3.5. Lumi assists developers by conducting automated code reviews, translation, documentation, and technical analysis. For more details or to run a custom analysis, visit the Lumi Dashboard.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions