Lumi Beacon: Security & Optimization Audit of near/nearcore (prepare.rs)
Beacon Details
GitHub Issue: Inconsistent VMKind Routing and Configuration Inconsistency in prepare_contract
1. Vulnerability Summary
The prepare_contract function in prepare.rs accepts both a config reference (which contains config.vm_kind) and a standalone kind: VMKind parameter. The function uses config.vm_kind to route the contract to either the prepare_v3 or prepare_v2 pipeline, but then passes the standalone kind argument to the selected pipeline. This design introduces a dual-source-of-truth flaw where a mismatch between config.vm_kind and kind can result in incorrect WASM preprocessing, invalid gas instrumentation, or execution-time failures.
2. Severity
Medium
3. Detailed Description
The entry point for WASM compilation preparation is defined as:
pub fn prepare_contract(
original_code: &[u8],
config: &Config,
kind: VMKind,
) -> Result<Vec<u8>, PrepareError>
Within the function body, the routing logic is determined as follows:
if config.reftypes_bulk_memory || config.vm_kind == VMKind::Wasmtime {
prepare_v3::prepare_contract(original_code, features, config, kind)
} else {
prepare_v2::prepare_contract(original_code, features, config, kind)
}
If a caller invokes prepare_contract with config.vm_kind configured to VMKind::Wasmtime but passes VMKind::NearVM as the kind argument, the contract preparation will be routed to the prepare_v3 pipeline. However, the prepare_v3 module will run with kind set to VMKind::NearVM.
Because different virtual machines require distinct gas metering, limit validations, and stack-height instrumentation passes, this mismatch can lead to:
- Applying instrumentation patterns designed for one VM target to a contract intended for execution on a different VM.
- Inconsistencies in contract validation limits (such as block limits or operand stack constraints), leading to situations where validation checks succeed during preparation but fail during actual deployment or execution.
4. Impact
- Consensus Divergence: If different nodes compile or instrument the same contract differently due to mismatched configurations, it can cause non-deterministic gas calculation or execution behavior, potentially resulting in chain forks.
- Unexpected VM Panics / Failures: The target VM runtime may fail to load the prepared WASM module if the instrumentation rules applied do not match its expected format or constraints.
5. Proof of Concept / Affected Code Snippet
The vulnerability lies in the routing logic of prepare_contract in runtime/near-vm-runner/src/prepare.rs:
/// Loads the given module given in `original_code`, performs some checks on it and
/// does some preprocessing.
...
pub fn prepare_contract(
original_code: &[u8],
config: &Config,
kind: VMKind,
) -> Result<Vec<u8>, PrepareError> {
let features = crate::features::WasmFeatures::new(config);
if config.reftypes_bulk_memory || config.vm_kind == VMKind::Wasmtime {
prepare_v3::prepare_contract(original_code, features, config, kind)
} else {
prepare_v2::prepare_contract(original_code, features, config, kind)
}
}
6. Remediation / Corrected Code
To remediate this issue, validate that the standalone kind matches the configured config.vm_kind before routing, or refactor the function signature to eliminate the redundant kind parameter.
Here is the corrected implementation enforcing state consistency:
pub fn prepare_contract(
original_code: &[u8],
config: &Config,
kind: VMKind,
) -> Result<Vec<u8>, PrepareError> {
// Ensure that the VMKind in config matches the dynamic parameter to prevent routing mismatches
debug_assert_eq!(
config.vm_kind, kind,
"VMKind in config ({:?}) must match the parameter kind ({:?})",
config.vm_kind, kind
);
if config.vm_kind != kind {
return Err(PrepareError::Instantiate); // Or a more specific error variant
}
let features = crate::features::WasmFeatures::new(config);
if config.reftypes_bulk_memory || config.vm_kind == VMKind::Wasmtime {
prepare_v3::prepare_contract(original_code, features, config, kind)
} else {
prepare_v2::prepare_contract(original_code, features, config, kind)
}
}
🌐 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.
Lumi Beacon: Security & Optimization Audit of near/nearcore (prepare.rs)
Beacon Details
runtime/near-vm-runner/src/prepare.rsGitHub Issue: Inconsistent VMKind Routing and Configuration Inconsistency in
prepare_contract1. Vulnerability Summary
The
prepare_contractfunction inprepare.rsaccepts both aconfigreference (which containsconfig.vm_kind) and a standalonekind: VMKindparameter. The function usesconfig.vm_kindto route the contract to either theprepare_v3orprepare_v2pipeline, but then passes the standalonekindargument to the selected pipeline. This design introduces a dual-source-of-truth flaw where a mismatch betweenconfig.vm_kindandkindcan result in incorrect WASM preprocessing, invalid gas instrumentation, or execution-time failures.2. Severity
Medium
3. Detailed Description
The entry point for WASM compilation preparation is defined as:
Within the function body, the routing logic is determined as follows:
If a caller invokes
prepare_contractwithconfig.vm_kindconfigured toVMKind::Wasmtimebut passesVMKind::NearVMas thekindargument, the contract preparation will be routed to theprepare_v3pipeline. However, theprepare_v3module will run withkindset toVMKind::NearVM.Because different virtual machines require distinct gas metering, limit validations, and stack-height instrumentation passes, this mismatch can lead to:
4. Impact
5. Proof of Concept / Affected Code Snippet
The vulnerability lies in the routing logic of
prepare_contractinruntime/near-vm-runner/src/prepare.rs:6. Remediation / Corrected Code
To remediate this issue, validate that the standalone
kindmatches the configuredconfig.vm_kindbefore routing, or refactor the function signature to eliminate the redundantkindparameter.Here is the corrected implementation enforcing state consistency:
🌐 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.