Add security best practice sections (#14798)
This commit is contained in:
parent
74c83e6854
commit
60611ae8a0
|
@ -13,6 +13,7 @@ $ npm install
|
|||
|
||||
This command starts a local development server and open up a browser window.
|
||||
Most changes are reflected live without having to restart the server.
|
||||
(You might have to run build.sh first if you run into failures)
|
||||
|
||||
```
|
||||
$ npm run start
|
||||
|
|
|
@ -84,6 +84,39 @@ _assign_ account ownership, meaning changing owner to different program id. If
|
|||
an account is not owned by a program, the program is only permitted to read its
|
||||
data and credit the account.
|
||||
|
||||
## Verifying validity of unmodified, reference-only accounts
|
||||
|
||||
For security purposes, it is recommended that programs check the validity of any
|
||||
account it reads but does not modify.
|
||||
|
||||
The security model enforces that an account's data can only be modified by the
|
||||
account's `Owner` program. Doing so allows the program to trust that the data
|
||||
passed to them via accounts they own will be in a known and valid state. The
|
||||
runtime enforces this by rejecting any transaction containing a program that
|
||||
attempts to write to an account it does not own. But, there are also cases
|
||||
where a program may merely read an account they think they own and assume the
|
||||
data has only been written by themselves and thus is valid. But anyone can
|
||||
issues instructions to a program, and the runtime does not know that those
|
||||
accounts are expected to be owned by the program. Therefore a malicious user
|
||||
could create accounts with arbitrary data and then pass these accounts to the
|
||||
program in the place of a valid account. The arbitrary data could be crafted in
|
||||
a way that leads to unexpected or harmful program behavior.
|
||||
|
||||
To check an account's validity, the program should either check the account's
|
||||
address against a known value or check that the account is indeed owned
|
||||
correctly (usually owned by the program itself).
|
||||
|
||||
One example is when programs read a sysvar. Unless the program checks the
|
||||
address or owner, it's impossible to be sure whether it's a real and valid
|
||||
sysvar merely by successful deserialization. Accordingly, the Solana SDK [checks
|
||||
the sysvar's validity during
|
||||
deserialization](https://github.com/solana-labs/solana/blob/a95675a7ce1651f7b59443eb146b356bc4b3f374/sdk/program/src/sysvar/mod.rs#L65).
|
||||
|
||||
If the program always modifies the account in question, the address/owner check
|
||||
isn't required because modifying an unowned (could be the malicious account with
|
||||
the wrong owner) will be rejected by the runtime, and the containing transaction
|
||||
will be thrown out.
|
||||
|
||||
## Rent
|
||||
|
||||
Keeping accounts alive on Solana incurs a storage cost called _rent_ because the
|
||||
|
|
|
@ -171,6 +171,26 @@ that this method only supports fixed sized types. Token utilizes the
|
|||
trait to encode/decode instruction data for both token instructions as well as
|
||||
token account states.
|
||||
|
||||
### Multiple instructions in a single transaction
|
||||
|
||||
A transaction can contain instructions in any order. This means a malicious
|
||||
user could craft transactions that may pose instructions in an order that the
|
||||
program has not been protected against. Programs should be hardened to properly
|
||||
and safely handle any possible instruction sequence.
|
||||
|
||||
One not so obvious example is account deinitialization. Some programs may
|
||||
attempt to deinitialize an account by setting its lamports to zero, with the
|
||||
assumption that the runtime will delete the account. This assumption may be
|
||||
valid between transactions, but it is not between instructions or cross-program
|
||||
invocations. To harden against this, the program should also explicitly zero out the
|
||||
account's data.
|
||||
|
||||
An example of where this could be a problem is if a token program, upon
|
||||
transferring the token out of an account, sets the account's lamports to zero,
|
||||
assuming it will be deleted by the runtime. If the program does zero out the
|
||||
account's data, a malicious user could trail this instruction with another that
|
||||
transfers the tokens a second time.
|
||||
|
||||
## Signatures
|
||||
|
||||
Each transaction explicitly lists all account public keys referenced by the
|
||||
|
|
Loading…
Reference in New Issue