Security best practices: HTTPS outcalls
Do not store sensitive data such as API keys in canisters
Security concern
Sensitive data is a broad term that varies depending on your application logic and behaviour. Here is a non-exhaustive list of secrets that are typically considered sensitive, such as API keys or tokens:
- Secrets that allow interaction with non-public endpoints.
- Secrets that allow querying or modifying endpoints with confidential data.
- API tokens that are fee-based.
By default, the data stored inside your canister is unencrypted. Therefore if your canister is installed on a malicious replica, it can easily retrieve and steal your keys, tokens, and secrets in plain text.
Recommendation
Make sure you don’t store sensitive data inside your canister.
Data confidentiality security recommendations.
Ensure your canisters have a sufficiently large quota with the HTTP server
Security concern
When an HTTPS outcall is performed, it is amplified by the number of replicas in the subnet. The target web server will receive not only one request, but as many requests as the number of nodes in the subnet.
Most web servers implement some sort of rate limiting; this is a mechanism used to restrict the number of requests a client can make to a web server within a specific time period, preventing abuse or excessive usage of their API(s).
Recommendation
You should consider such rate limits when designing and implementing your canisters. Rate limits are enforced using different time granularities, e.g., seconds or minutes. For second-granularity enforcement, make sure that the simultaneous requests by all subnet replicas do not violate the quota. Violations may lead to temporary or permanent bans.
Only make HTTPS outcall requests to idempotent endpoints
Security concern
As mentioned before, if an HTTPS outcall is performed it is amplified by the number of replicas in the subnet. That means the queried endpoint will receive the same request several times. This is especially risky in requests that change the endpoint state, given that one HTTPS outcall could lead to unintentionally changing the endpoint state several times.
Recommendation
Make sure the endpoints, called by an HTTPS outcall, are idempotent, such that the queried endpoint has the same behavior with the same request payload, no matter the number of times it is called.
Some servers support the use of idempotency keys. These keys are random unique strings submitted in the HTTP request as headers. If used with the HTTPS outcalls feature, all requests sent by each honest replica will contain the same idempotency key. This allows the server to recognize duplicated requests (i.e requests with the same idempotency key), handle just one and modify the server state only once. Note that this is a feature that must be supported by the server.
Ensure HTTPS responses are identical
Security concern
When replicas of a subnet receive HTTP responses, these responses must be identical. Otherwise, consensus won’t be achieved and the HTTP response will be rejected, but still charged.
Recommendation
Make sure the HTTP responses sent to the consensus layer are identical.
Ideally the HTTP responses returned by the queried endpoint would always be the same. However, most of the time this is not possible to control and the responses include random data (e.g the response includes timestamps, cookie values or some sort of identifiers). In those cases make sure to use the transformation functions to guarantee that the responses received by each replica are identical by removing any random data or extracting only the relevant data.
This applies to the HTTP response body and headers. Make sure to consider both when applying the transformation functions. Response headers are often overlooked and lead to failure because of failed consensus.
Be aware of HTTP request and response sizes
Security concern
The pricing of HTTPS outcalls is determined by the size of the HTTP request and the maximal response size, among other variables. Thus, if big requests are made, this could quickly drain the canister’s cycles balance. This can be risky in scenarios where HTTPS outcalls are triggered by user actions (rather than a heartbeat or timer invocation).
Recommendation
When using HTTPS outcalls, be mindful of the HTTP request and response sizes. Ensure that the size of the request issued and the size of the HTTP response coming from the server are reasonable.
When making an HTTPS outcall it is possible – and highly recommended – to define the max_response_bytes
parameter, which allows you to set the maximum allowed response size. If this parameter is not defined, it defaults to the hard response size limit of the HTTPS outcalls feature, which is 2MiB. The cycle cost of the response is always charged based on the max_response_bytes
or 2MB if not set.
Finally, be aware that users may incur cycles costs for HTTPS outcalls in case these calls can be triggered by user actions.
Perform input validation in HTTPS outcalls
Security concern
HTTPS outcalls that use user-submitted data are susceptible to various injection attacks. This may lead to several issues, such as the ones previously mentioned.
Recommendation
Perform input validation when using user-submitted data in the HTTPS outcalls.