Building on Avalanche? Ava Labs can cover up to 75% of your audit, and we take 10% off our quote. Avalanche audits: up to 75% covered. See how

Work & reportsReport

NEAR IntentsNEAR Intents Passkeys Pull Request Security Review

Guvenkaya reviewed the NEAR Intents pull request that adds passkey signature support.

NEAR Intents logo

Date of engagement: 6th February 2025 - 10th February 2025

  • Timur GüvenkayaPrincipal advisor

Engagement Dashboard

Audit results

Guvenkaya conducted a security assessment of the NEAR Intents Passkeys Pull Request from 6th February 2025 to 10th February 2025. During this engagement, a total of 5 findings were reported. 1 of the findings was medium and the remaining were informational severity. All issues were either fixed, acknowledged, or scheduled per the remediation status.

Engagement record

Client
NEAR Intents
System
NEAR Intents passkeys pull request #43
Review period
6th February 2025 - 10th February 2025
Paths in scope
1
Principal advisor
Timur Güvenkaya

Timeline

  1. Review start6th February 2025
  2. Draft report10th February 2025
  3. Final report6th March 2025

Findings by severity

  • Critical 0
  • High 0
  • Medium 1
  • Low 0
  • Informational 4

Finding status at final report

5Raised
1Fixed
1Scheduled
3Acknowledged

Remediation complexity

3Simple
1Moderate
1Complex

Impact

1Severe
4Negligible

Likelihood

5Rare

Advisory and Client

The advisory

Guvenkaya specializes in security for digital assets and financial infrastructure, from smart contracts and protocols to applications, infrastructure, custody and cryptography.

Our team, including the sitting Heads of Security at Gauntlet and Agora, brings experience from Kraken, OpenZeppelin, Binance, ZKsync, Nillion, Invicti and EY. Across the team: 200+ security reviews, $30B+ in volume secured, 13 published cryptography research papers, and credentials including OSCP, OSWE and CISM.

  • Every reviewer has a public bio and is named before you sign. We match expertise to your system, with a principal leading scoping and checking findings.

The client

NEAR Intents is a cross-chain liquidity protocol for swaps, payments and asset onboarding. Users specify the assets and outcome they want, while the system coordinates routing and execution across supported blockchains. Wallets, applications and agents can integrate these capabilities into their own products.

Applications obtain quotes from competing solvers. Signed intents express the authorized asset movements, which the Verifier contract validates and executes on NEAR. Developers can integrate through a widget or API; the 1Click API handles quote requests, intent creation and execution tracking, reducing the need to build separate integrations for each supported chain and asset pair.

  • Cross-chain swaps let users exchange an asset on one network for an asset on another.
  • Cross-pay lets a sender use one token while the recipient receives a preferred asset on another supported chain.
  • Asset onboarding lets a wallet or application accept deposits from a user's existing chain through the same network.

Scope and Review Boundaries

Review depths

Deep
Line-by-line review with explicit attack hypotheses, adversarial reasoning about state transitions, and reproduction attempts for each hypothesis that survived reading.
Supporting
The code was read for its effect on a reviewed flow. Behaviour outside that effect was not assessed.
Targeted
Entry points were exercised or triaged against the flow's security properties rather than read in full.

This is the code we read, and how closely. 1 paths are in scope. Each path links to the file at the reviewed commit.

PathReview depthScope note
https://github.com/near/intents/pull/43DeepPasskeys Pull Request

Out of scope

The audit will include reviewing the code for security vulnerabilities. The audit does not include a review of the tests and dependencies.

Assessment Framework

Guvenkaya rates findings by likelihood and impact so remediation can be prioritized by technical risk, business context, and the decision the engagement is meant to support.

Rating chain applied to every finding

  1. 01 Likelihood Likely, possible or rare
  2. 02 Impact Severe, moderate or negligible
  3. 03 Severity Derived from the matrix below
  4. 04 Remediation complexity Simple, moderate or difficult
  5. 05 Status Not fixed, fixed, acknowledged or scheduled

Impact

ImpactWhat it means here
SevereExploitation could result in critical loss or compromise, such as full system control, substantial financial loss, or severe reputational damage.
ModerateExploitation may lead to limited data loss, partial compromise, moderate financial impact, or noticeable degradation of services.
NegligibleExploitation has minimal impact, such as minor data exposure without significant consequences or slight inconvenience without substantial disruption.

Likelihood

LikelihoodWhat it means here
LikelyThe vulnerability is easily discoverable and not overly complex to exploit.
PossibleThe vulnerability presents some challenges either in discovery or in the complexity of the attack.
RareThe vulnerability is either very difficult to discover or complex to exploit, or both.

This matrix provides a nuanced view, taking into account both the ease of discovering a vulnerability and the complexity involved in exploiting it.

Attack Complexity \ Discovery EaseObviousConcealedHidden
ComplexPossibleRareRare
ModerateLikelyPossibleRare
StraightforwardLikelyPossiblePossible

Severity

SeverityWhat it means here
CriticalAssigned to vulnerabilities with severe impact and a likely likelihood of exploitation.
HighFor vulnerabilities with either severe impact but only a possible likelihood, or moderate impact with a likely likelihood.
MediumUsed for vulnerabilities with severe impact but a rare likelihood, moderate impact with a possible likelihood, or negligible impact with a likely likelihood.
LowFor vulnerabilities with moderate impact and rare likelihood, or negligible impact with a possible likelihood.
InformationalThe lowest severity rating, typically for vulnerabilities with negligible impact and a rare likelihood of exploitation.
Likelihood \ ImpactSevereModerateNegligible
LikelyCriticalHighMedium
PossibleHighMediumLow
RareMediumLowInformational

Remediation complexity

This measures how difficult it is to remediate a finding once it has been identified.

Remediation complexityWhat it means here
SimplePatches or fixes are readily available and easily implemented.
ModerateRequires some time and resources to remediate, but well within the capabilities of most organizations.
DifficultRemediation requires significant resources, specialized skills, or substantial changes to systems or architecture.

Finding status

This tracks the client's response to each finding and whether remediation has been completed, accepted, or scheduled.

StatusWhat it means here
Not FixedIndicates that the vulnerability has been identified but no remedial action has been taken yet. This status is crucial for newly discovered vulnerabilities or those awaiting prioritization.
FixedThis status is applied when the vulnerability has been successfully remediated. It implies that appropriate measures, such as patching, configuration changes, or architectural modifications, have been implemented to resolve the issue.
AcknowledgedThis status is used for vulnerabilities that have been recognized, but for various reasons (such as risk acceptance, cost, or other business decisions), have not been fixed. It indicates that the risk posed by the vulnerability is known and has been consciously accepted.
ScheduledThis status indicates that the vulnerability has been acknowledged and a plan is in place to fix it in the future. It signifies that while remediation hasn't yet occurred, the issue has been prioritized and is part of the planned development roadmap.

Findings Summary

5All findings
0 Critical
0 High
1 Medium
0 Low
4 Informational

Findings register

FindingImpactLikelihoodSeverityRemediation complexityStatus
GUV-1: Potential DoS of The Main Functionality Through Malicious SolversSevereRareMediumModerateScheduled
GUV-2: Anyone Can Fake The Passkey Signature For Their Own AccountNegligibleRareInformationalComplexAcknowledged
GUV-3: Unsafe Callback URL ValidationNegligibleRareInformationalSimpleAcknowledged
GUV-4: Insufficient Nonce Entropy ValidationNegligibleRareInformationalSimpleAcknowledged
GUV-5: Different Signature Malleability For Each CurveNegligibleRareInformationalSimpleFixed

Detailed Findings

GUV-1: Potential DoS of The Main Functionality Through Malicious Solvers

Severity
Medium
Impact
Severe
Likelihood
Rare
Remediation Complexity
Moderate
Status
Scheduled

Description

Malicious solvers can cause service degradation or denial of service (DoS) to frontends and any systems relying on solver bus data.

Causes That Make This Attack Possible:

  • Frontends typically are optimizing to give the best quote to the user
  • Solver bus simulates intents and aggregates quotes submitted via websockets
  • A time gap exists between the solver bus's intent simulation and user signature submission
  • Quote submission to the solver bus is unrestricted
  • The failure of one intent causes all other intents to fail:
core:execute_signed_intents:core/src/engine/mod.rs
pub fn execute_signed_intents(                    mut self,                    signed: impl IntoIterator<Item = MultiPayload>,                ) -> Result<Transfers> {                    for signed in signed {                        self.execute_signed_intent(signed)?;                    }                    self.finalize()                }
  • An attacker controls multiple solvers with deposited funds for popular token pairs, consistently submitting the best prices. The solver's available funds aren't verified after intent simulation
  • The solver bus returns quotes including the attacker's quote. Frontends likely select the attacker's quote due to its superior pricing
  • The user signs the transaction and submits it to the smart contract
  • A single malicious intent causes the entire transaction to fail, even if other intents were valid, due to the execution loop's error handling
  • By repeating this process for each quote request, the attacker prevents reliable intent execution. This risk is heightened during early adoption when solver numbers are limited

Impact

  • Reputation damage
  • Inability for regular users to execute intents (griefing)

Recommendation

Implement a solver reputation system (possibly using a trusted solver list), economic penalties, and progressive timeout/backoff for unreliable solvers. This could be implemented with the addition of API keys.

Remediation

The NEAR Intents team has acknowledged the issue and will fix it soon by introducing API keys and/or reputaion-based filteting for solvers on Solver Bus level.

GUV-2: Anyone Can Fake The Passkey Signature For Their Own Account

Severity
Informational
Impact
Negligible
Likelihood
Rare
Remediation Complexity
Complex
Status
Acknowledged

Description

It was observed that, anyone can generate a valid P256 key, add their public key through the add_public_key function, sign the required data, and successfully pass the smart contract verification. This effectively allows users to trick the smart contract into believing that an object was signed by a passkey when it wasn't. The significance of this issue depends on whether there's a need to differentiate between passkey and hardware key signatures, or if there are special benefits planned for passkey users.

Impact

Users can fake signatures without utilizing passkeys

Recommendation

To ensure the passkey is genuine and from a verified source, you should:

Offchain - During Registration:

  • Obtain the attestation certificate (CA and device) from the blob at https://fidoalliance.org/metadata/ or other sources
  • Verify the device's AAGUID, certificate chain, and newly generated public key
  • If verification succeeds, call the smart contract to add the public key (consider mapping between AAGUID/credential_id &pubkey). Disable unverified public key additions for P256 signatures

Offchain - During Signing: Sign the intents object without the public_key field and send it to SC

Onchain:

  • Verify the flags and attestedData = true, then fetch the stored public key (using credential ID/AAGUID)
  • Check the signature against the known public key
  • Perform regular verifications (nonce, signer matches public key, etc.)

Remediation

The NEAR Intents team has acknowledged the issue but it won’t be fixed since it is allowed by design.

GUV-3: Unsafe Callback URL Validation

Severity
Informational
Impact
Negligible
Likelihood
Rare
Remediation Complexity
Simple
Status
Acknowledged

Description

The Nep413Payload structure and with_callback_url function in Nep413Payload implementation accepts callback URLs without any validation, potentially allowing malicious or unsafe URLs to be passed.

nep413:nep413/src/lib.rs
#[near(serializers = [borsh, json])]#[serde(rename_all = "camelCase")]#[derive(Debug, Clone)]pub struct Nep413Payload {    pub message: String,     #[serde_as(as = "Base64")]    pub nonce: [u8; 32],     pub recipient: String,     #[serde(default, skip_serializing_if = "Option::is_none")]    pub callback_url: Option<String>,} // ... existing code ...#[inline]pub fn with_callback_url(mut self, callback_url: String) -> Self {self.callback_url = Some(callback_url);self}

Impact

This allows arbitrary strings to be used as callback URLs, including:

  • Dangerous protocols (e.g., file://, data://)
  • Malformed URLs
  • URLs with null bytes or other control characters

If any off-chain component processes these callback URLs, it could be vulnerable to exploitation.

Recommendation

Implement proper URL validation in the with_callback_url and write a custom deserializer to verify Url on the parsing level in Nep413Payload.

Remediation

The NEAR Intents team has acknowledged the issue but it won’t be fixed since it is allowed by design.

GUV-4: Insufficient Nonce Entropy Validation

Severity
Informational
Impact
Negligible
Likelihood
Rare
Remediation Complexity
Simple
Status
Acknowledged

Description

Any signed payload accepts any 32-byte array as a nonce without validating its entropy or randomness.

poc:test_zero_nonce_security
#[test]fn test_zero_nonce_security() {    let zero_nonce_payload = Nep413Payload {        message: payload.message.clone(),        nonce: [0u8; 32],  // Zero nonce accepted        recipient: payload.recipient.clone(),        callback_url: None,    };}

Impact

If you’re only using the nonce as a once-per-user unique value there are no problems. However, It is still safer and more standard to generate a random nonce of sufficient length (128 bits+) so you avoid accidental collisions and stay in line with typical cryptographic best practices.

Recommendation

Implement proper nonce validation and generation

Remediation

The NEAR Intents team has acknowledged the issue but it won’t be fixed since it is allowed by design.

GUV-5: Different Signature Malleability For Each Curve

Severity
Informational
Impact
Negligible
Likelihood
Rare
Remediation Complexity
Simple
Status
Fixed

Description

Each cryptographic curve implements signature malleability differently:

  • SeckP: Not Allowed. Uses ecrecover with a true flag to enable malleability checks
  • Ed25519: Allowed. Uses env::ed25519_verify
  • P256: Allowed. Implements passkey verification without signature malleability checking

The behavior of signature malleability should be unified across all curves. Having consistent security properties would simplify threat modeling, debugging, and tracking.

Impact

While nonces currently protect against replay attacks, disallowing malleability for all curves would be more secure. Future code changes, such as adding functions without nonce validation, could introduce vulnerabilities if malleability remains inconsistent.

Recommendation

Enable signature malleability checks across all curves.

Remediation

The NEAR Intents team has fixed the issue by enabling signature malleability checks for all curves in these PRs:

The web version and the PDF (16 pages) are generated from the same source. The report as first delivered is kept in the public reports archive.

Tell us what you need to secure.

Describe your system, main concern, and deadline. We’ll reply with scoping questions and a proposed next step.

Discuss your scope