CRITICAL: This document outlines security practices to protect sensitive data in cloud-based applications.
Your AWS Account (NEVER COMMIT):
- Account ID, Account Name, Region
- Free Tier status and credits
- Access keys and credentials
- ❌ AWS Access Keys / Secret Keys
- ❌ Database passwords
- ❌ API keys
- ❌ Session secrets / JWT secrets
- ❌ Private SSH keys
- ❌ TLS/SSL certificates
- ❌ Service account credentials
- ❌ Personal account information
- ❌ Production connection strings
- ❌ Any
.envfiles with real values
Always use environment variables for sensitive data.
# Good: Use .env files (which are gitignored)
DATABASE_URL=postgresql://user:pass@host/db
AWS_REGION=us-east-2
# Bad: Hardcoding in source code
const dbUrl = "postgresql://user:pass@host/db"; // ❌ NEVER DO THISSetup:
# Copy the example file
cp .env.example .env
# Edit with your actual values
nano .env # or your preferred editor
# Verify .env is gitignored
git status # .env should NOT appearRecommended Approaches (in order of preference):
Use IAM roles attached to EC2, ECS, Lambda, etc. No credentials needed!
// AWS SDK automatically uses IAM role
const s3 = new AWS.S3();aws configure
# Enter your credentials once
# Stored in ~/.aws/credentials (gitignored globally)# .env file (gitignored)
AWS_ACCESS_KEY_ID=your-access-key-here
AWS_SECRET_ACCESS_KEY=your-secret-key-here
AWS_REGION=us-east-2NEVER in Code:
// ❌ NEVER DO THIS
const credentials = {
accessKeyId: 'hardcoded-key-here',
secretAccessKey: 'hardcoded-secret-here'
};Before every commit:
# Check what you're about to commit
git status
git diff --staged
# Look for patterns that might be secrets
git diff --staged | grep -i "key\|secret\|password\|token\|credential"Use git-secrets (recommended):
# Install
brew install git-secrets # macOS
# or
sudo apt install git-secrets # Linux
# Setup for repo
git secrets --install
git secrets --register-aws
# Scan existing commits
git secrets --scan-history# Check for sensitive files
find . -type f \( -name "*.env" -o -name "*credentials*" -o -name "*.pem" -o -name "*.key" \)
# Verify .gitignore is working
git check-ignore .env .env.local .aws/credentials
# Should output the filenames (meaning they're ignored)Development:
# .env
DATABASE_URL=postgresql://localhost:5432/homeharbor_devProduction: Use AWS Secrets Manager or Parameter Store:
// Load from AWS Secrets Manager
const AWS = require('aws-sdk');
const secretsManager = new AWS.SecretsManager({ region: 'us-east-2' });
const secret = await secretsManager.getSecretValue({
SecretId: 'homeharbor/database/url'
}).promise();
const dbUrl = secret.SecretString;For third-party services:
# .env
OPENAI_API_KEY=sk-...
MAPBOX_API_KEY=pk....
STRIPE_SECRET_KEY=sk_test_...In code:
// ✅ Good
const apiKey = process.env.OPENAI_API_KEY;
// ❌ Bad
const apiKey = "sk-...";Next.js requires NEXT_PUBLIC_ prefix for client-side variables:
# .env
NEXT_PUBLIC_API_URL=http://localhost:4000
NEXT_PUBLIC_MAPBOX_TOKEN=pk.eyJ1... # Public token (safe)
# Never expose secrets on client
API_SECRET=secret123 # Only accessible server-sideTerraform state files can contain secrets!
# .gitignore already includes:
*.tfstate
*.tfstate.*
*.tfstate.backup
terraform.tfvarsUse remote state with encryption:
# terraform/backend.tf
terraform {
backend "s3" {
bucket = "homeharbor-terraform-state"
key = "state/terraform.tfstate"
region = "us-east-2"
encrypt = true
dynamodb_table = "terraform-state-lock"
}
}Act immediately:
# AWS: Deactivate the access key immediately
aws iam delete-access-key --access-key-id YOUR_KEY_ID --user-name your-user
# Generate new credentials
aws iam create-access-key --user-name your-user# Remove sensitive file from history
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch path/to/sensitive-file" \
--prune-empty --tag-name-filter cat -- --all
# Force push (if already pushed)
git push origin --force --all
# Notify GitHub to clear cache
# Contact GitHub support or use: gh api -X DELETE repos/{owner}/{repo}/git/refs/heads/main# Install BFG
brew install bfg # macOS
# Remove secrets
bfg --delete-files credentials.json
bfg --replace-text passwords.txt # List of secrets to remove
# Clean up
git reflog expire --expire=now --all
git gc --prune=now --aggressive
# Force push
git push --force- Document what was exposed
- Update security practices
- Review access logs
- Consider security audit
- ✅ Enable MFA on root account
- ✅ Create IAM users (don't use root)
- ✅ Use IAM roles for services
- ✅ Enable CloudTrail logging
- ✅ Set up billing alerts
- ✅ Enable GuardDuty (threat detection)
- ✅ Use AWS Organizations for account management
- Use Security Groups (restrictive by default)
- Enable VPC for network isolation
- Use AWS Secrets Manager for credentials
- Enable encryption at rest (S3, RDS, EBS)
- Enable encryption in transit (HTTPS, TLS)
- Regular security audits with AWS Security Hub
# Create deployment user (for CI/CD)
aws iam create-user --user-name homeharbor-deploy
# Attach minimal required policies
aws iam attach-user-policy \
--user-name homeharbor-deploy \
--policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess
# Create access key
aws iam create-access-key --user-name homeharbor-deploy
# Store in GitHub Secrets (for GitHub Actions)
gh secret set AWS_ACCESS_KEY_ID
gh secret set AWS_SECRET_ACCESS_KEYBefore Every Commit:
- Run
git statusand review files - Run
git diff --stagedand check for secrets - Verify .env files are NOT staged
- Check for hardcoded credentials in code
- Ensure API keys use environment variables
- Review terraform.tfvars is not committed
Before Deployment:
- All secrets in AWS Secrets Manager
- IAM roles configured for services
- Security groups properly configured
- Encryption enabled for data at rest
- HTTPS/TLS for data in transit
- Logging and monitoring enabled
- Backup strategy in place
Regular Reviews:
- Rotate credentials quarterly
- Review IAM permissions (principle of least privilege)
- Check CloudTrail logs for suspicious activity
- Update dependencies (security patches)
- Review AWS Trusted Advisor recommendations
- Scan for vulnerabilities (npm audit, snyk)
git secrets --install
git secrets --register-aws
git secrets --scandocker run --rm -v "$PWD:/pwd" trufflesecurity/trufflehog:latest filesystem /pwd# Check current credentials (obscured)
aws sts get-caller-identity
# Verify region
aws configure get region# Check if required vars are set
node -e "
const required = ['DATABASE_URL', 'AWS_REGION', 'SESSION_SECRET'];
const missing = required.filter(v => !process.env[v]);
if (missing.length) {
console.error('Missing:', missing.join(', '));
process.exit(1);
}
console.log('✓ All required variables set');
"- AWS Security Best Practices
- OWASP Top 10
- Git-Secrets Documentation
- GitHub Security Best Practices
- AWS IAM Best Practices
- Store in AWS Secrets Manager, not in code or .env.
- Rotate keys regularly; monitor usage for anomalies.
- Use least-privilege access; limit to necessary models.
- Validate AI outputs for security (e.g., no injection in property descriptions).
- Avoid exposing AI prompts with sensitive data.
- Implement rate limiting on AI endpoints to prevent abuse.
- Do not commit AI-generated code without review for vulnerabilities.
- Use AI feedback loops but validate suggestions against security guidelines.
- Ensure AI tools do not access sensitive repos or data.
Last Updated: January 30, 2026