Nym Security Review

Security audit of Nym core components

9 mins Read

Introduction

In July 2021, Nym underwent a security audit by Jean-Philippe Aumasson, a renowned security expert. The goal was to identify potential vulnerabilities and defects in the Nym codebase, focusing on cryptography, code security, and protocol security. The review aimed to ensure the integrity and robustness of the system, covering key aspects of its architecture and implementation. You can see the full audit report here.

Summary of the Audit

The audit took place in the summer of 2021. The scope of the audit covered multiple repositories of the Nym project, including:

  • Nym’s Main Repository: nymtech/nym, which implements the mixnode, gateway, and validator services.
  • Sphinx Mixnet Packet Format: nymtech/sphinx, used by mixnodes.
  • Coconut Threshold Blind Signature Protocol: nymtech/coconut, used for credential issuance.

The audit involved reviewing the latest version of the code in the develop branch, which was regularly refreshed due to the project's fast-paced evolution. The Nym team provided JP Aumasson full access to the codebase, detailed project specifications, research papers, and supporting documentation.

Key Focus Areas of the Audit

The audit focused on three main areas: code security, cryptography, and protocol design. The auditors thoroughly examined Nym’s codebase to identify vulnerabilities, looking for common issues like unsafe coding patterns and mishandled errors. Special attention was given to memory safety and avoiding pitfalls like integer overflows.

The cryptographic review covered a wide range of core primitives employed by Nym, such as AES-128-CTR, BLAKE2b, ChaCha, Ed25519, and others. The goal was to ensure proper implementation of these algorithms and verify their resistance to side-channel attacks, misuse of parameters, and flaws in randomness generation.

In addition to reviewing the individual components, the audit also looked into the protocols that define the core functionality of Nym. This involved examining the Sphinx packet format and the Coconut threshold blind signature protocol to identify any weaknesses that could compromise privacy or security. The review focused on potential information leaks threatening user anonymity, as well as vulnerabilities like MAC verification bypasses, small subgroup attacks, and flaws in cryptographic operations such as BLS12-381 arithmetic and zero-knowledge proofs.

Overview of Findings

Nine security vulnerabilities were discovered during the audit. None were rated as critical, two as high, one as medium, and six as low. Additionally, 17 observations were made, offering recommendations for further strengthening the Nym network. Below, we provide an overview of the fixes implemented to address all identified security vulnerabilities.

S-SPHX-01: Missing validations of keys (Low)

The issue identified in nymtech/sphinx regarding insufficient validation of private and public keys has been addressed by migrating to the x25519 library, which inherently enforces key validity through its design. The x25519 implementation ensures that private keys are correctly clamped, meaning they are automatically constrained to a valid subset of scalars, eliminating the risk of using invalid private keys. Additionally, while x25519 does not explicitly validate public keys, its Montgomery ladder implementation inherently prevents certain invalid curve points from being used. This mitigates the risk of encountering points at infinity or other malformed public keys. Furthermore, the key exchange process ensures that an all-zero shared secret can be detected and rejected if necessary. By leveraging x25519, we have significantly improved key validation, reducing the risk of invalid or improperly formatted keys being used within the system. This effectively resolves the concerns raised in the audit regarding key validation.

S-COCO-01: Hash-to-scalar biased distribution (Low)

The hashing process to derive a scalar in the BLS12-381 field previously involved mapping a hash function output directly to a scalar field element. However, this approach introduced bias due to the modular reduction operation (mod p), which can result in a non-uniform distribution when the hash output does not perfectly align with the field's prime modulus. To address this issue, we replaced the existing hash-to-scalar function with the hash_to_field function from the bls12_381 crate. This function follows the standardized hash-to-field specification, ensuring a uniform and unbiased mapping of hash outputs to field elements. Additionally, the zk-Nym protocol, which replaced the Coconut protocol, also relies on this function for its hashing operations, ensuring consistency and correctness in cryptographic computations.

S-COCO-02: keygen-cli key files permissions (Low)

The auditors noted that the keygen-cli key files have default permissions, but they should have more restricted permissions for better security. This issue did not require any changes, as keygen-cli was only used in the early stages of our Coconut implementation. It is no longer part of the main Nym repository and is not in active use. Since the tool became obsolete, no further action was needed regarding its file permissions.

S-CRYP-01: Potential stream cipher IV reuse (High)

The issue involves a function that encrypts data using an initialization vector (IV). If no IV is provided, the function defaults to using a zero IV, which could result in IV reuse. This issue has been resolved by introducing the AES-GCM-SIV protocol during the registration phase. To prevent downgrade attacks, we have removed the option to use the legacy AES-128-CTR key for communication between the client and gateway. As long as both the client and gateway are updated, they will always generate a random, non-zero IV.

S-PROT-01: Potential double spend of credentials (High)

The auditors noticed that the reviewed version of Coconut lacked a double-spending detection mechanism, which could have allowed multiple gateways to incorrectly validate a credential as unused at the same time. However, the Coconut bandwidth contract was later updated to track credential usage by storing state on-chain, addressing this issue. Additionally, Coconut has since been replaced by the zk-nyms protocol, which includes built-in double-spending detection functionality.

S-NYM-01: Dependencies with known vulnerabilities (Medium)

The auditors identified that several components in the Nym project were relying on older versions of dependencies with known security vulnerabilities. For instance, the Sphinx repository used an insecure version of the generic-array crate, Nym's core repository relied on an outdated tokio, and the Nym client had several crates with known security issues, some of which appeared to be exploitable within the Nym context. Following the auditors' recommendation, we regularly updated the dependencies. We now actively manage our dependencies through Dependabot, which continuously monitors and automatically detects outdated or vulnerable packages in our repositories. See the Dependabot fixes continuously applied in our repository.

S-NYM-02: Decryption failure not handled (Low)

The issue identified in the code occurs in the recover_identifier function in nym/common/nymsphinx/acknowledgments/identifier.rs, where decryption failures, such as invalid parameters, are not properly handled. This can lead to panic or other insecure states. A similar problem exists in the recover_plaintext function in nym/common/nymsphinx/src/receiver.rs. The failure to manage decryption errors could potentially result in the system entering an unstable or insecure state. After carefully reviewing the functions, we concluded that the first example provided, in recover_identifier, is a non-issue. It is impossible to provide incorrect parameters, as everything is parameterized with AckEncryptionAlgorithm (link), meaning any invalid values would be caught at compile time. The second case they mentioned, recover_plaintext, no longer exists. However, the code that replaced it, recover_plaintext_from_regular_packet, had a theoretically possible failure case if we were to modify some parameters to unusual values. We've addressed this by adding proper error handling to ensure the system remains stable, even in edge cases.

S-NYM-03: Panic in fragment IDs generation (Low)

The code used for generating new fragment IDs randomly selects an i32 value and takes its absolute value. However, this approach can lead to panic in cases where the randomly chosen value is i32::MIN, as its absolute value cannot be represented within the bounds of an i32. This results in an 'attempt to negate with overflow' error due to the limitations of 2-complement encoding. We agree with the severity rating being set too low for this issue, as the likelihood of encountering this case is approximately 1 in 4 billion. However, we have addressed the issue by implementing the auditor's recommended fix to prevent potential panics and unexpected crashes, especially when millions of users generate thousands of fragment IDs.

S-NYM-04: Mnemonic not zeroized (Low)

The issue identified highlighted that the BIP39 mnemonic used for connecting the nymd service was not being zeroized after use, resulting in multiple copies of the mnemonic persisting in memory. This increased the risk of exposure, as mnemonics are more easily identifiable in memory compared to raw cryptographic keys. To address this, we have implemented several mitigations. In the Rust components, we have integrated the zeroize crate to ensure that any memory containing the mnemonic is securely erased as soon as it goes out of scope. Since JavaScript is a garbage-collected language and does not provide direct control over memory disposal, we have taken a different approach to mitigate exposure in the JavaScript runtime. Specifically, we have modified the system so that the JavaScript runtime terminates once the mnemonic has been passed to the Rust layer. This ensures that all instances of the mnemonic within JavaScript memory are cleared upon runtime shutdown. The mnemonic is transferred to Rust as early as possible, reducing its exposure in JavaScript. Once within Rust, zeroize ensures that all instances of the mnemonic are securely erased once they are no longer needed. With these changes, we have significantly minimized the mnemonic’s presence in memory, reducing the risk of exposure and ensuring that sensitive data is securely managed and erased.

Last words

We would like to thank the JP Aumasson for his expertise and dedication throughout this audit process. We also appreciate the collaboration and professionalism demonstrated during both the planning and execution stages of the audit. Our ongoing commitment to security remains a top priority, and we look forward to continued partnerships with security experts to uphold the highest standards for our ecosystem.

Share
HERO NEW1.svg

Introducing NymVPN

Experience the world’s most private VPN. Advanced privacy built for the age of AI, starting at $5.49 / month for up to 10 devices. Get NymVPN today and save up to 60%.

Artboard 1.svg