---
title: Security Audit
category: reference
---

# Security Audit

## Introduction

To be listed on the  “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](../../getting-started#security-audit).

Provided your project fulfills the [conditions](#conditions), this is how an external audit unfolds:

1. You get in touch with the auditors and sign a contract with them. [Read more](../../getting-started#security-audit).
2. The auditors review your app based on Ledger specifications. [Read more](#security-audit-specifications).
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

> **Warning:** <ul>
>   <li>- 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).</li>
>   <li>- Your Device App must still be functional after the security audit </li>
> </ul>

## 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:**

- [BIP32 prefix restrictions](../../references/app-permissions#restrict-apps-to-coin-specific-bip32-prefix)
- [Application parameters](../../integration/requirements/security#application-parameters-minimal-and-declared)

### 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:**

- [Signing settings](../../integration/requirements/security#signing-settings)

### 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:**

- [Development requirements](../../integration/requirements/development)

### Continuous integration

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

**References:**

- [Development requirements](../../integration/requirements/development)

### 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:**

- [Development requirements](../../integration/requirements/development)
- [Be wary of unstrusted input](../../explanation/security-specificities#be-wary-of-untrusted-input)
- [Good practices for transaction handling](../../explanation/architecture-good-practices#good-practices-for-transaction-handling)

### 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:**

- [Security requirements](../../integration/requirements/security)

### 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:**

- [General cryptography concepts](../../explanation/cryptography)
- [Cryptography reference](../../references/cryptography-api)
- [Cryptography examples](../../references/cryptography-api-examples)

### 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.
