For dApps & ServicesDevice AppSubmission processDeliverablesSecurity Audit

Security Audit

Introduction

To be listed on the Ledger Wallet “My Ledger“ section, Device Apps and Plugins must go through our integration process that includes a security audit performed by one of our trusted partners.

Provided your project fulfills the conditions, this is how an external audit unfolds:

  1. You get in touch with the auditors and sign a contract with them. Read more.
  2. The auditors review your app based on Ledger specifications. Read more.
  3. Ledger reviews the security audit report
  4. Ledger publishes your app

Conditions

To go through an external security audit, ensure your project fulfills the following conditions:

  • Your Device App works with all our devices (Ledger Nano S Plus, X, Stax and Flex)
  • Your Device App has been functionally validated by Ledger team
⚠️
  • - Do not start a security audit process if your Device App is not ready for all Ledger devices (Ledger Nano S Plus, X, Stax and Flex).
  • - Your Device App must still be functional after the security audit

Security audit specifications

Ledger has established and made public a detailed specification of what needs to be checked during a security audit following Ledger’s standards.

When the word must is used, it indicates a requirement. When the word should is used, it indicates a recommendation. It means that there are reasons not to follow the recommendation and it can be justified.

Do not hesistate to use the following specification as a checklist.

Application privileges

  • The application flags must abide by the principle of least privilege.
  • When required, privileges must be justified.
  • The application derivation paths must be restricted to coin-specific BIP32 prefixes.
  • The application derivation paths must be declared in the Ledger app database.
  • Curves usage must be restricted.

References:

Clear signing

  • All signing actions must ask for user approval.
  • The user must be able to see every important information (amount, destination address, validator, token…).
  • If blind signing is implemented:
    • It must be disabled by default.
    • It must not apply to basic transactions such as the coin transfers, which must be clear signed.
  • A security review of the app workflow using either a live device or Speculos and the functional tests snapshots must ensure:
    • Critical and important information are clear signed using a user friendly format.
    • The user cannot be confused or tricked by the application workflow and the displayed information.
    • Every possible flow is functionally tested (associated snapshots are present).

References:

Compilation

  • Makefiles from boilerplate app and secure-sdk must be used to compile the project (the goal is to ensure that security flags are applied).
  • New apps must fork the boilerplate template and updated apps must upgrade to the latest standard makefile (located in the boilerplate app).
  • The compilation logs review must ensure (can be reviewed through the CI results):
    • No compilation errors are returned.
    • No compilation warnings are returned.
    • No compilation warnings are silenced without a clear reason (though compilation flags or pragma directives).
    • No deprecated functions are being used.

References:

Continuous integration

  • Guidelines enforcer and build workflows must be integrated to the device application.
  • All pipelines must succeed for all supported devices.

References:

Tests

  • Unit tests should be implemented for functions that do not require Ledger OS syscalls mocking.
  • All unit tests must succeed.
  • Functional tests must be written to cover at least the nominal cases (features provided by the applications) and common errors (for example clear signing cancellation).
  • All functional tests must succeed for all devices.
  • Fuzzing targets should be implemented at least for parsers and critical functions that are easy to fuzz as it will facilitate the audit.
  • Ethereum plugins handlers must be fuzzed (a generic target is available in the boilerplate).
  • Fuzzing should be done using libfuzzer to integrate with ClusterFuzzLite as shown in the boilerplate apps and plugins.

References:

Static analysis

  • Dependencies must be used only if they’re strictly needed and maintained without containing impactful vulnerabilities for the chosen version.
  • For C apps, scan-build must succeed without returning any defects (can be reviewed through the CI results).
  • For C apps, CodeQL must succeed without returning any vulnerabilities with the “security and quality” queries.
  • For C apps, external libraries are considered part of the app meaning that used APIs must also be reviewed.
  • For Rust apps, clippy must succeed without returning any issue (can be reviewed through the CI results).
  • For Rust apps, dependencies must be checked using cargo-audit.
  • Other tools may be used as part of the static analysis process.

References:

Vulnerabilities and weaknesses

  • The application or its dependencies must not contain any medium or high severity vulnerabilities.
  • The application should not contain any low vulnerabilities.
  • The review must check for security vulnerabilities (non exhaustive list):
    • read/write out of bounds
    • integer overflow/underflow
    • format string vulnerabilities
    • memory leaks
    • use-after-free or double-free
    • incorrect type conversions
    • usage of unsafe functions (eval, strcpy, strlen, gets, sprintf, …)
    • returning uninitialized memory that could expose sensitive data
  • Particulary input validation must be comprehensive and strongly tested (fuzzing is recommended):
    • All parsing and other relevant functions must validate input lengths before processing.
    • Parser functions handle malformed data gracefully without crashes or infinite loops.
    • All type mismatches are prevented (e.g., using a uint8 loop counter with uint32 bound).
    • All array accesses are bounds-checked appropriately.
  • The review must focus on logic errors (non exhaustive list):
    • unsanitized or unconventional user input
    • cryptographic oracle
    • state management handling (application state is properly initialized and cleared/erased when finalized or if an error occurs, correct ordering is enforced in multi-step operations resulting in multiple changes to state, etc.)
    • security restrictions bypass (autolock, pin entry)
    • secure error handling (all return values checked, errors don’t result in invalid or impartial states, cryptographic operation failures handled securely, etc.)
  • The review must report any other weaknesses, for example related to code quality and readability that could impact security indirectly (non exhaustive list):
    • magic numbers such as:
      • Using raw numbers where an enum or a macro would be preferred to ease code reading and maintenance.
      • Using raw numbers instead of computing it with sizeof operator and/or dedicated macro.
    • lack of documentation:
      • APDUs that are not documented.
      • Functions that are not documented (description, parameters, return value, error cases, specific behavior, …).
    • complex functions (huge cyclomatic complexity, length, …)
    • rust applications specific checks:
      • All unsafe code blocks are justified and documented.
      • There are no known panics in production code paths.
      • Error handling is properly performed for all returned Result types.
      • Arithmetic overflows/underflows are handled securely either by using saturing_x, checked_x, or manual check.
      • Utility code for testing is guarded by the #[cfg(test)] attribute to ensure that potentially insecure test code is not included in the production application.

Cryptography

  • Secrets must be erased from memory as soon as possible after usage.
  • Secrets derived from seed must not be stored, exported or shown.
  • Structure integrity of messages must be verified before signature (never allow signing attacker controlled messages).
  • User supplied messages must use a prefix if they are to be signed.
  • Cryptographic primitives must not be re-implemented if they already exist in Ledger OS or the SDK.
  • Cryptographic functions that can throw exceptions are deprecated and must not be used (can be reviewed through the CI results).
  • Cryptographic helpers and ledger assertions provided by the SDK should be used to handle cryptographic operations.
  • The client must not be able to freely manipulate keypairs.
  • An authenticated encryption scheme must be used for data being cached on the client.
  • If custom cryptographic code is implemented, the implementation should make a best-effort attempt to protect against side-channel leakage and fault injection.

References:

Deliverables

  • The report must contain an executive summary explicitly giving the auditor feedback on whether this app should be deployed or not (and in this case what needs to be done).
  • The report must contain the findings, steps to reproduce, impacts and associated recommendations. It should also contains tests that gave no results.
  • The report must contain the checklist below in appendix to indicate what has been checked and validated during the audit.

Checklist

  • Application flags, derivation paths and curves are correctly set.
  • Clear signing correctly displays information and asks for user confirmation.
  • Blind signing is disabled by default or does not exist (if it exists, it does apply for complex transactions but not to coin transfers or swaps).
  • App workflow is considered secure and snapshots cover the nominal and error cases of app features.
  • Boilerplate Makefiles and SDK are used to compile the app. If it’s a new app, it has been developed over the C/Rust boilerplates.
  • The app compiles without errors or warnings (no errors/warnings are silenced using compilation flags or pragma directives)
  • Guidelines enforcer and build workflows are integrated and passed.
  • Unit tests, functional tests and fuzzing tests are passing.
  • For app-plugins, the generic fuzzing target is integrated.
  • scan-build/CodeQL or clippy succeed without returning vulnerabilities
  • Dependencies are needed, maintained and secure (no known impactful vulnerability for the used version).
  • The app does not contain any medium or high severity vulnerabilities.
  • The review process looked into technical vulnerabilities as well as logical ones and weaknesses.
  • Secrets are correctly erased from memory, not exported or shown to the user.
  • User supplied messages use a prefix and are validated before signature.
  • No cryptographic primitives are re-implemented if they already exist in Ledger OS or the SDK.
  • The client is not able to freely manipulate the device keypairs.
  • An authenticated encryption scheme is used for data being cached on the client.
Ledger
Copyright © Ledger SAS. All rights reserved. Ledger, Ledger Stax, Ledger Nano S, Ledger Vault, Bolos are trademarks owned by Ledger SAS