What are best practices for handling sensitive data?

Security

The short answer

Never store sensitive data in client-side code (JavaScript, localStorage, or HTML). Use HTTPS for all communication. Store secrets in environment variables on the server. Use httpOnly cookies for auth tokens. Mask sensitive fields in the UI. Follow the principle of least exposure — only send data the client actually needs.

Never expose secrets in frontend code

// Bad — API key is visible to anyone who opens DevTools
const API_KEY = 'sk_live_abc123';
fetch(`/api?key=${API_KEY}`);
// Good — proxy through your backend
fetch('/api/data'); // your server adds the API key

Anything in your JavaScript bundle is public. Environment variables prefixed with NEXT_PUBLIC_ or VITE_ are embedded in the client bundle — never put secrets there.

Use HTTPS everywhere

Without HTTPS, data travels in plain text over the network. Anyone on the same WiFi can read passwords, tokens, and personal data.

  • Enable HTTPS on your server
  • Use HSTS headers to force HTTPS
  • Never send forms over HTTP

Store auth tokens securely

// Good — httpOnly cookie (JavaScript cannot access it)
// Server sets: Set-Cookie: token=abc123; HttpOnly; Secure; SameSite=Strict
// Bad — localStorage (any script can read it)
localStorage.setItem('token', 'abc123');

httpOnly cookies are invisible to JavaScript, which protects them from XSS attacks.

Environment variables

Store secrets in server-side environment variables, not in code:

# .env file (never commit to git)
DATABASE_URL=postgres://user:pass@host/db
API_SECRET=sk_live_abc123

Add .env to your .gitignore. Use your hosting provider's environment variable settings for production.

Minimize data exposure

// Bad — sends all user data to the frontend
app.get('/api/user', async (req, res) => {
const user = await db.getUser(req.userId);
res.json(user); // includes password hash, SSN, etc.
});
// Good — only send what the frontend needs
app.get('/api/user', async (req, res) => {
const user = await db.getUser(req.userId);
res.json({
name: user.name,
email: user.email,
avatar: user.avatar,
});
});

Mask sensitive data in the UI

function CreditCard({ number }) {
const masked = `**** **** **** ${number.slice(-4)}`;
return <p>{masked}</p>;
}

Only show the last 4 digits. Never display full card numbers, SSNs, or passwords.

Interview Tip

Cover: no secrets in frontend code, HTTPS, httpOnly cookies for auth, environment variables for server secrets, and minimal data exposure. These are the five most important points. Give a quick code example for each.

Why interviewers ask this

Data breaches are expensive and damaging. Interviewers want to see if you handle sensitive data responsibly and know the common mistakes (like putting API keys in frontend code or storing tokens in localStorage).