A shared default login in a tutorial becomes a known credential the moment the page is public. Readers who deploy the sample without changing it expose a login anyone can guess. Instead, generate a random password at first run, or force the reader to set one before the app starts.
How a demo credential becomes a live one
The pattern is simple. A tutorial says to sign in as admin with the password admin. The reader follows along on a laptop. A week later they copy the container or the compose file to a test server, then to a staging server visible from the internet. Nobody remembers the credential is still the tutorial's.
Attackers know the common defaults and try them first. A login page that accepts a documented password is not a hard target. The cause is the docs, but the incident belongs to the reader, which is why it is worth fixing at the source.
Options compared
| Approach | Reader effort | Residual risk |
|---|---|---|
| Fixed shared default password | None | High: known to everyone |
| Default password plus a "change it" note | Low | High: notes are skipped |
| Random password printed once at first start | Low | Low: unique per install |
| App refuses to start until a password is set | Medium | Lowest: no default exists |
| Passwordless local only mode bound to loopback | None | Low if truly local |
The third and fourth options cost the reader seconds and remove the known credential entirely.
Steps to change a tutorial
- Remove any shared account from the sample data and the docs text.
- Have the setup step generate a random password and show it once in the console, or read it from an environment variable the reader supplies.
- If the sample needs seeded users for a demo, create them with random passwords and print them locally. Do not commit them.
- Bind the sample to localhost by default so an unfinished setup is not reachable from other machines.
- Add a check that fails the sample's own tests if a known weak password is accepted.
- Document where the password lives and how to rotate it, so the reader can treat the sample as a template for real work.
# Generate a random password for a first run
openssl rand -base64 24
What to say in the docs
Say what the credential protects, in plain terms. "This account can read and change all data in the app" is more persuasive than "change the default password". Then link to the production checklist. See also the secure defaults checklist for a new git repository.
Related habits worth checking
Seeded API tokens in fixture files, database accounts with blank passwords in compose files, and admin consoles enabled on all interfaces all follow the same logic. A sample is a template, and templates spread their defaults.
If your product ships a sample that must have a fixed credential for a technical reason, label it loudly in the interface itself, not only in the docs, and make the first screen demand a change.
Try it yourself
A scan of the running sample web app can reveal exposed admin pages and weak settings.
Click through it at your own pace, or open it full screen.
Safeguard runs web application and API scanning, plus policy gates that can block risky changes in review. The free scan is at https://gold.safeguard.sh/scan.
Quick check
Is a password note in the README enough?
Notes get skipped. A random per-install password or a required setup step is more reliable.
Is a fixed password fine if the sample only runs locally?
Only if it is bound to the loopback address. Samples are often copied to shared servers.
Last reviewed: 19 October 2026.