This document outlines the security features and best practices for Bucketlist CMS.
Isolation & Sandboxing:
- ✅
contextIsolation: true- Renderer process is isolated from Node.js - ✅
nodeIntegration: false- No direct Node.js access in renderer - ✅
sandbox: true- Additional OS-level sandboxing - ✅
webSecurity: true- Web security features enabled - ✅
contextBridge- Controlled IPC communication only
What This Means:
- Renderer process cannot access AWS credentials directly
- All AWS operations happen in the secure main process
- XSS vulnerabilities cannot access Node.js APIs
- IPC surface is minimal and well-defined
Active CSP Rules:
default-src 'self' # Only load from app
script-src 'self' # No remote scripts
style-src 'self' 'unsafe-inline' # Allow inline styles (Tailwind)
img-src 'self' data: https://*.s3.amazonaws.com # S3 images allowed
connect-src 'self' https://*.s3.amazonaws.com # S3 API calls allowed
font-src 'self' # Local fonts only
frame-ancestors 'none' # Prevent clickjacking
object-src 'none' # No plugins
upgrade-insecure-requests # Force HTTPS
What This Prevents:
- Remote code execution from external scripts
- Cross-site scripting (XSS) attacks
- Clickjacking attacks
- Malicious plugin injection
Option 1: AWS Profile (Recommended)
Use AWS CLI profiles from ~/.aws/credentials:
aws configure --profile bucketlist-cmsOption 2: Dedicated IAM User Create a dedicated IAM user with minimal permissions.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3ReadWrite",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*"
},
{
"Sid": "AllowListBucket",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME"
}
]
}Replace YOUR-BUCKET-NAME with your actual bucket name.
For extra security, limit access to specific prefixes:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
"Resource": [
"arn:aws:s3:::YOUR-BUCKET/collections/*",
"arn:aws:s3:::YOUR-BUCKET/entries/*",
"arn:aws:s3:::YOUR-BUCKET/assets/*",
"arn:aws:s3:::YOUR-BUCKET/schemas/*",
"arn:aws:s3:::YOUR-BUCKET/api/*"
]
},
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::YOUR-BUCKET",
"Condition": {
"StringLike": {
"s3:prefix": [
"collections/*",
"entries/*",
"assets/*",
"schemas/*",
"api/*"
]
}
}
}
]
}1. Enable Versioning Protects against accidental deletions and overwrites:
aws s3api put-bucket-versioning \
--bucket YOUR-BUCKET \
--versioning-configuration Status=Enabled2. Block Public Access Unless you need public API access, keep Block Public Access enabled:
aws s3api put-public-access-block \
--bucket YOUR-BUCKET \
--public-access-block-configuration \
"BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"3. Enable Default Encryption Encrypt data at rest:
aws s3api put-bucket-encryption \
--bucket YOUR-BUCKET \
--server-side-encryption-configuration \
'{"Rules": [{"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}]}'4. Configure CORS (for public API access) If you need public API access:
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "HEAD"],
"AllowedOrigins": ["*"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3000
}
]Electron Store (Encrypted)
- Credentials are stored in OS-specific secure locations
- macOS:
~/Library/Application Support/Bucketlist/ - Windows:
%APPDATA%\Bucketlist\ - Linux:
~/.config/Bucketlist/
What's Stored:
- AWS region
- Access Key ID (if using keys)
- Secret Access Key (if using keys, encrypted by Electron)
- AWS Profile name (if using profile)
- Default bucket name
Security:
- Files are only readable by your user account
- Credentials never leave your machine
- Not exposed to renderer process
- Cleared when you click "Clear Stored"
✅ XSS Attacks - CSP prevents remote script execution
✅ Credential Exposure to Renderer - Main process isolation
✅ Unauthorized IPC Calls - Typed, validated IPC surface
✅ Remote Code Execution - Sandbox + contextIsolation
✅ Clickjacking - frame-ancestors 'none'
Long-lived Credentials:
- If using IAM access keys (not profiles), they don't expire
- Mitigation: Rotate keys regularly, use IAM Identity Center (SSO) when possible
No Multi-factor Authentication:
- App doesn't enforce MFA
- Mitigation: Enable MFA on your AWS account
No Audit Trail in App:
- App doesn't track who made what changes
- Mitigation: Enable CloudTrail on your bucket for AWS-level auditing
Before using Bucketlist CMS in production:
- Create dedicated IAM user with minimal permissions
- Enable S3 Versioning on your bucket
- Enable S3 default encryption
- Configure CORS if using public API
- Enable CloudTrail for audit logs (optional)
- Set up MFA on your AWS account
- Regularly rotate access keys (if not using SSO)
- Keep Bucketlist updated to latest version
If you discover a security vulnerability in Bucketlist CMS, please report it responsibly:
- Do not open a public GitHub issue
- Email the maintainer directly with details
- Allow time for a patch before public disclosure
- AWS IAM Best Practices
- AWS IAM Identity Center (SSO)
- S3 Security Best Practices
- Electron Security Guidelines
Remember: Security is a shared responsibility. Bucketlist provides a secure foundation, but you must configure AWS correctly and follow best practices.
🔒 Stay Secure!