Security Emergency Procedures#
This guide outlines the strategies and actions to take in case of a security incident or credential exposure.
Forced Password Reset Strategy#
In the event of a credential exposure or as a proactive security measure, you can force a password reset for specific users or all active users.
How to use strategy#
Run migration: Ensure the database schema supports the password reset flag.
Trigger reset: A security admin calls
POST /api/v1/login/force-password-resetwith either:affected_emails: A list of specific user emails.include_all_active_users: true: To force a reset for all users.
User experience: Flagged users will see a warning in their settings and will be guided to change their password upon their next login or interaction.
Automatic clearing: A successful password change will clear the forced reset flag automatically.
Security Emergency Actions#
If specific credentials are known to be exposed, follow these steps immediately. The deployment stores its secrets in AWS Systems Manager Parameter Store — see Environment Variables and Deploying on AWS.
1. Rotate exposed credentials immediately#
Generate fresh values first: Use
rotate_exposed_secrets.pyto generate replacements in one pass (for example--target local-db --target secret-key, or--target all).Update local env values: Put generated values into
.env(POSTGRES_PASSWORD,FIRST_SUPERUSER_PASSWORD,SECRET_KEY) and rotateVITE_STRAPI_API_KEYas needed. Local.envfiles are for local development only.Update Parameter Store: Overwrite the deployed values so the instance picks them up on the next deploy.
aws ssm put-parameter --name /blocks/secret-key --type SecureString \ --overwrite --value "$(openssl rand -hex 32)" aws ssm put-parameter --name /blocks/postgres-password --type SecureString \ --overwrite --value "$(openssl rand -hex 24)"
2. Apply the rotation to the running deployment#
Re-run the deploy script:
./deploy.shon the instance rewrites.envfrom Parameter Store and recreates the containers, so both the backend and PostgreSQL come up on the new values.Change the database password itself: rotating the parameter changes what the backend sends. The PostgreSQL role has to be changed to match, or the two drift apart:
docker compose exec db psql -U blocks -c "ALTER ROLE blocks WITH PASSWORD 'new-value';"
Do this before recreating the backend, then run
./deploy.sh.
3. Recycle access paths#
Revoke IAM credentials: The instance authenticates with its instance profile, so there should be no long-lived access keys to rotate. If any exist, deactivate them with
aws iam update-access-key --status Inactiveand delete them after cutover rather than leaving them in place.Re-key SSH: There is no SSH access to revoke — the instance is reached through SSM Session Manager and port 22 is closed. If a key pair was added at some point, remove it from
~/.ssh/authorized_keysand close the rule.Force user password resets: Use the procedure at the top of this page if application accounts are implicated.
4. Verify compromise closure#
Confirm access denial: Verify that the old database password no longer works.
Confirm functionality: Confirm that app/admin login and database connectivity work correctly with the new credentials.
Audit logs: Review CloudTrail for
ssm:GetParameter,s3:GetObjectand IAM activity during the exposure window, anddocker compose logs backendfor unexpected authenticated requests.
5. Prevent repeat incidents#
Secret hygiene: Never commit real secrets to the repository or include them in examples.
Environment separation: Continue using
.envfiles only for local development; deployed configuration must be sourced from Parameter Store. The.envthatdeploy.shwrites on the instance is generated, mode600, and never committed.Automated scanning: Add secret scanning to pre-commit hooks and CI pipelines (e.g.,
gitleaksortrufflehog) and block pushes if secrets are found.