15 Principle for Secure Programming
Your go-to guide for building secure web apps + FREE access to my video course
Hello there 👋
I’m Rakia, a freelance senior software engineer, Google Developer Expert (GDE), speaker, and content creator.
In today’s roundup, I dive into how to keep your web apps safe and sound. I’ll share some practical tips, laid out in a way that’s easy to follow. Let’s get right into it!
Security might sound scary, but it’s really just about being smart and staying one step ahead of the bad guys.
1. Validate Input Like a Skeptic
Never trust what users enter into your app. It could be innocent — or it could be a grenade. Always validate and sanitize input. For example, if someone’s typing a username, make sure they’re not sneaking in <script>alert(XSS)</script>
.
Use htmlspecialchars()
in PHP to sanitize user input:
echo htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
In Java, use a library like OWASP Java Encoder:
// Use a library like OWASP Java Encoder
String safeOutput = Encode.forHtml(userInput);
2. Keep Your Secrets… Secret
Passwords, API keys, and database credentials don’t belong in your codebase:
Sensitive stuff like passwords should never be cached.
Use environment variables to store them securely.
And for the love of everything, don’t push secrets to GitHub — bots will grab them faster than you can delete the commit.
3. Parameterized Queries Are Your Best Friend
SQL injection is like leaving your front door wide open. Use parameterized queries or ORM tools to lock that door tight. You're practically inviting trouble if you’re concatenating user input into SQL queries.
Here’s how it looks in some common languages:
Python (with SQLite or any DB API-compliant library):
import sqlite3
# Connect to your database
conn = sqlite3.connect('example.db')
cursor = conn.cursor()
# BAD: Vulnerable to SQL injection
user_input = "1 OR 1=1" # Hacker input
query = f"SELECT * FROM users WHERE id={user_input}" # Dangerous concatenation
cursor.execute(query)
# GOOD: Using parameterized queries
user_id = 1 # Safe input
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
results = cursor.fetchall()
conn.close()
Java (with JDBC):
import java.sql.*;
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/example", "user", "password");
// BAD: Vulnerable to SQL injection
String userInput = "1 OR 1=1"; // Hacker input
Statement stmt = conn.createStatement();
String query = "SELECT * FROM users WHERE id = " + userInput; // Dangerous concatenation
ResultSet rs = stmt.executeQuery(query);
// GOOD: Using parameterized queries
String safeQuery = "SELECT * FROM users WHERE id = ?";
PreparedStatement pstmt = conn.prepareStatement(safeQuery);
pstmt.setInt(1, 1); // Safe input
ResultSet safeRs = pstmt.executeQuery();
4. Escape Output to Defuse Attacks
Whenever you show user-provided content on your web app, escape it properly. This stops Cross-Site Scripting (XSS) attacks in their tracks. Use the escaping features of your framework or libraries — it’s easier than doing it by hand.
Here is an example of how you can treat user input as plain text, not executable code:
JavaScript (Using DOM API with Escaping):
// BAD: Directly inserting user input into HTML
const userInput = "<script>alert('XSS')</script>"; // Malicious input
document.getElementById('output').innerHTML = userInput; // Executes script
// GOOD: Using textContent to escape
const safeInput = "<script>alert('XSS')</script>"; // Still potentially malicious
document.getElementById('output').textContent = safeInput; // Displays as text, not code
Python (with Flask):
from flask import Flask, render_template_string, request
app = Flask(__name__)
# BAD: Rendering user input directly in HTML
@app.route("/unsafe")
def unsafe():
user_input = request.args.get("name", "")
return f"<h1>Hello {user_input}</h1>" # Vulnerable to XSS
# GOOD: Escaping output using Flask's built-in escaping
@app.route("/safe")
def safe():
user_input = request.args.get("name", "")
return render_template_string("<h1>Hello {{ name }}</h1>", name=user_input) # Escaped
5. Always Hash Passwords
If you’re storing passwords in plain text, stop reading and fix that immediately. Use a strong hashing algorithm like bcrypt or scrypt. Don’t try to build your own crypto solution — it’s harder than it looks, and nobody likes reinvented wheels that break.
6. Keep Dependencies Fresh
Outdated libraries are a hacker’s playground. Keep your dependencies updated, and use tools like npm audit
or pip-audit
to catch vulnerabilities. Old packages might seem harmless, but they could carry known exploits.
7. Use HTTPS Everywhere
If your app doesn’t use HTTPS, you’re basically shouting sensitive data across a crowded room. It’s free with services like Let’s Encrypt, so there’s no excuse not to.
Node.js with Express (Redirect to HTTPS):
const express = require('express');
const https = require('https');
const fs = require('fs');
const app = express();
// Redirect HTTP to HTTPS
app.use((req, res, next) => {
if (!req.secure) {
return res.redirect(`https://${req.headers.host}${req.url}`);
}
next();
});
// HTTPS Server setup
const options = {
key: fs.readFileSync('path/to/private-key.pem'),
cert: fs.readFileSync('path/to/certificate.pem')
};
https.createServer(options, app).listen(443, () => {
console.log('HTTPS server running on port 443');
});
8. Implement Proper Access Control
Don’t let users access things they shouldn’t. Use role-based access control (RBAC) to keep sensitive data locked away from prying eyes. Don’t trust user input to decide what they can or can’t see.

9. Log Smart, Not Sensitive
Logging is great for debugging, but don’t log passwords, credit card numbers, or personal information. Keep your logs clean and helpful, and secure them so only the right people can see them.
Python with Logging:
import logging
# Set up logging
logging.basicConfig(level=logging.INFO, filename="app.log",
format="%(asctime)s - %(levelname)s - %(message)s")
# BAD: Logging sensitive data
password = "secret123"
logging.info(f"User logged in with password: {password}") # DO NOT DO THIS!
# GOOD: Logging safely
user_id = 42
logging.info(f"User ID {user_id} logged in.") # Useful, non-sensitive information
JavaScript Example (Winston Logger):
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'app.log' })
],
});
// BAD: Logging sensitive information
const creditCard = "1234-5678-9012-3456";
logger.info(`User entered credit card: ${creditCard}`); // Don't do this!
// GOOD: Log general actions instead
logger.info('User completed a transaction.');
10. Test Like a Hacker
Think like a troublemaker when testing your app. Try to break it. Use tools like OWASP ZAP (Zed Attack Proxy) or Burp Suite to scan for vulnerabilities. The more you practice breaking it, the harder it’ll be for others to succeed.
11. Set Secure Cookies
Cookies are powerful but dangerous if left unsecured. Always set the HttpOnly
and Secure
flags. This keeps cookies safe from JavaScript-based attacks and ensures they only travel over HTTPS.
Node.js with Express:
const express = require('express');
const app = express();
// Set a secure cookie
app.use((req, res, next) => {
res.cookie('session', 'secure_value', {
httpOnly: true, // Prevents JavaScript access
secure: true, // Ensures it only travels over HTTPS
sameSite: 'Strict' // Stops cross-site attacks
});
next();
});
app.listen(443, () => {
console.log('Secure app running on HTTPS');
});
PHP Example:
<?php
// Set a secure cookie
setcookie("session", "secure_value", [
"httponly" => true,
"secure" => true,
"samesite" => "Strict"
]);
?>
Some Inspiring Pieces
🎁 Special Gift for You
I have a couple of great offers to help you go even deeper. Free & Discount access to my video courses - available for a limited time, so don’t wait too long!
⚡ Master Web Performance: From Novice to Expert
Use FREE coupon 17175ACA722524F3901A🔥 Modern Software Engineering: Architecture, Cloud & Security
Use Discount coupon B23FA85253A6E0CD0FB0
Until next time—stay curious and keep learning!
Best,
Rakia
💡 🧠 I share content about engineering, technology, and leadership for a community of smart, curious people. For more insights and tech updates, join my newsletter and subscribe to my YouTube channel.