Skip to content

Security: sblrm/travo_mate

Security

SECURITY.md

πŸ”’ Security Quick Reference

🎯 At a Glance

Fixed Vulnerabilities

  • βœ… Information Disclosure (HIGH) - Sanitized errors, removed stack traces
  • βœ… Sensitive Data Exposure (HIGH) - Masked emails/phones automatically
  • βœ… CORS Misconfiguration (MEDIUM) - Restricted to trusted origins
  • βœ… Missing Security Headers (LOW) - Added CSP, X-Frame-Options, etc.

πŸ›‘οΈ Security Features

1. Data Masking (Auto-applied)

// Emails: john.doe@example.com β†’ j***e@e***e.com
// Phones: +6281234567890 β†’ +62812****7890
// Tokens: secrettoken123 β†’ s***3

2. Error Sanitization

// Production: "Terjadi kesalahan. Silakan coba lagi."
// Development: Full error details for debugging
// NEVER: Stack traces, API keys, database structure

3. CORS Protection

// βœ… Allowed: https://travo-mate.vercel.app
// βœ… Allowed: http://localhost:8080 (dev only)
// ❌ Blocked: All other origins

4. Security Headers

X-Frame-Options: DENY
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Security-Policy: (strict)

πŸ”§ Common Usage

Display Masked Data

import { maskEmail, maskPhoneNumber } from '@/utils/dataMasking';

<p>Email: {maskEmail(user.email)}</p>
<p>Phone: {maskPhoneNumber(booking.phone)}</p>

Handle Errors Safely

import { getUserFriendlyError, logError } from '@/utils/errorSanitization';

try {
  await operation();
} catch (error) {
  toast.error(getUserFriendlyError(error));  // Indonesian message
  logError('Context', error);  // Dev only
}

Fetch Masked Data

import { getUserBookingsWithMasking } from '@/utils/supabaseHelpers';

// Auto-masks for non-admin users
const bookings = await getUserBookingsWithMasking(userId, !isAdmin);

βš™οΈ Configuration

Environment Variables

# Vercel Environment Variables
APP_URL=https://travo-mate.vercel.app  # For CORS
NODE_ENV=production                    # Enables security

CORS Allowed Origins

Edit api/midtrans.ts and api/gemini.ts:

const allowedOrigins = [
  'https://travo-mate.vercel.app',
  'https://your-custom-domain.com',  // Add your domain here
];

πŸ§ͺ Testing

Check Security Headers

curl -I https://travo-mate.vercel.app

Test Data Masking

// Browser console
import { maskEmail } from '@/utils/dataMasking';
maskEmail('test@example.com');  // β†’ t***t@e***e.com

Test CORS

# Should FAIL
curl -H "Origin: https://evil.com" https://travo-mate.vercel.app/api/midtrans

# Should SUCCEED  
curl -H "Origin: https://travo-mate.vercel.app" https://travo-mate.vercel.app/api/midtrans

πŸ“‹ Pre-Deployment Checklist

  • All secrets use correct env var naming (no VITE_ for server keys)
  • CORS allowedOrigins includes production domain
  • Security headers configured in vercel.json
  • Data masking applied to user-facing components
  • Error messages use getUserFriendlyError()
  • Console.log wrapped with logError() or NODE_ENV check
  • Test locally: bun run dev
  • Build succeeds: bun run build
  • Deploy to Vercel
  • Run security scan to verify

πŸ†˜ Troubleshooting

Issue Solution
CORS errors Check APP_URL in Vercel env vars
Data not masked Verify isAdmin() function works
Errors still show stack traces Check NODE_ENV=production
CSP violations Add domain to vercel.json CSP

πŸ“š Full Documentation

  • Complete Guide: docs/SECURITY_FIXES_2025-11-03.md
  • Code Examples: docs/SECURITY_USAGE_EXAMPLES.md
  • AI Instructions: .github/copilot-instructions.md

Last Updated: November 3, 2025
Status: Production Ready βœ…

There aren’t any published security advisories