Security best practices
The decisions that actually matter, the four things client-side protection cannot do, and what to do about each of them.
Decide what you are defending against#
| You want to stop | What helps | What does not |
|---|---|---|
| Accident, truncated writes, a bad disk | Atomic writes, integrity, backups | Encryption (irrelevant here) |
| A player editing their save for convenience | Authenticated encryption | Encryption alone — a player with the key can decrypt and re-sign |
| A player editing a save for advantage | Authenticated encryption plus server validation of anything that matters | Client-side checks alone |
| A competitor reading your save structure | Encryption | Obfuscation of field names |
The four gaps, stated plainly#
- Memory is not protected. A process that can read the game's memory can read the plaintext.
- No rollback protection. Replacing a save with an older valid one cannot be detected on the client; that needs a server-side sequence.
- Keys you embed are not keys. Source them from a keystore, a sign-in exchange or a server.
- Client protection is a cost, not a boundary. It raises the effort required. Ranked, competitive or paid state belongs on a server, and the framework deliberately does not pretend otherwise.
Practical hardening checklist#
- Turn on integrity (default SHA-256) — it is nearly free and it turns silent corruption into a reported event.
- Turn on encryption if the save contains anything a player would not want readable. Accept that a determined player can still read it while the game runs.
- Use separate encryption and authentication keys, and keep both out of the build.
- Keep metadata free of secrets: it is readable by design so listings can work without a key.
- Lower
Limits.MaxSaveSizeBytesandMaxMetadataSizeBytesto something your game can actually produce — a ceiling nothing can fit under protects nothing. - Validate anything that affects other players on your server.
- Report security issues privately, per Support, not in a public thread with a proof of concept.
What the package already does for you#
Its part is done by construction, not by configuration: the header and metadata are authenticated, the tag is verified before decryption, decompression is bounded before and during expansion, and an unverifiable file is left strictly alone rather than quarantined as damaged. Available
Next#
- Encryption · Authentication · Key providers
- Limitations — the same honesty applied to the whole framework.
Something wrong on this page? Every page here describes behaviour that is checked in the repository. If a page and the package disagree, the package wins.
Report a documentation problem · Frequently asked questions · Troubleshooting