Security best practices: Important resources and further reading
Intermediate
Security
Concept
Overview
Below are resources which cover security best practices for technologies you are likely using in your dapp. These best practices are equally important as our Internet Computer specific guidelines and should be studied carefully. They can be useful to reference when developing secure dapps or executing security reviews.
General
- How to audit an Internet Computer canister by Joachim Breitner
- OWASP application security verification standard
- OWASP top ten
Rust
- Secure Rust guidelines, in particular unsafe code, overflows and Cargo-audit
- For overflowing operations, consider using
saturated
orchecked
variants of these operations, such assaturated_add
,saturated_sub
,checked_add
,checked_sub
, etc. See e.g. the Rust docs foru32
.
- For overflowing operations, consider using
Crypto
- OWASP cryptographic failures points out issues related to cryptography, or the lack thereof.
- OWASP application security verification standard (see Section V6)
- Use the Web Crypto API. Storing key material in the browser storage (such as sessionStorage or localStorage) is considered unsafe because these keys can be accessed by JavaScript code, e.g. in an XSS attack. To protect the private key from direct access, use Web Crypto's generateKey with
extractable=false
. See also the encrypted notes example.
Web security
- Resources for setting security headers:
- SSL server test
- Don’t use features that could lead to an XSS vulnerability, such as e.g. @html in Svelte.
- Log out securely. Clear all session data (especially sessionStorage and localStorage), clear IndexedDB, etc. on logout. Make sure other browser tabs showing the same origin are logged out if the logout is triggered in one tab. This may not happen automatically when agent-js is used, since agent-js keeps the private key in memory once initialized.
Testing
These are some useful references for testing canisters which don't necessarily relate to security. However, having good test coverage is essential for developing secure applications.
- In effective Rust canisters: test upgrades, make code target-independent
- Consider PocketIC for canister testing