Code is at the heart of today’s digital world, and as such is a prime target for hackers. With so many attacks exploiting so many vulnerabilities in software, code security is essential for building strong and resilient systems.
In this 101-level piece, we’ll dive into what code security really means, why it’s so important, and walk through some real-world examples of both secure and vulnerable code.
Code security is the practice of writing, testing, and maintaining code in a way that protects it from attacks or exploitation. This happens by identifying and addressing vulnerabilities in code to prevent attackers from exploiting weaknesses to compromise systems, steal data, or disrupt services.
Vulnerabilities in code are one of the biggest entry points for cyber criminals. Like we've seen time and time again, a single vulnerability can expose sensitive data or even bring down an entire system. Preventing breaches starts with secure coding from the ground up.
Then there’s reputation - once a company suffers a breach, customer trust takes a serious hit. Restoring that trust isn’t easy, and the financial and legal fallout can be just as damaging.
From a cost perspective, fixing security issues while developers are drafting code is far more cost-effective than scrambling to patch a system after deployment (or worse, after an attack). The longer a vulnerability goes unnoticed, the more expensive it becomes to fix.
Another reason code security is important is for compliance. For many industries, compliance isn’t optional; Finance, healthcare, and tech companies must follow strict regulations like SOC 2, GDPR, and HIPAA. Secure coding ensures these requirements are met without last-minute panic.
Finally, scalability depends on security. If an application is built on shaky foundations, expanding it only increases the risk. A secure-by-design approach ensures that growth doesn’t come at the cost of security.
In short, investing in secure coding isn’t just about avoiding threats—it’s about building a resilient, scalable, and trustworthy business.
An example of insecure code in python:
In this example, the application is vulnerable to SQL injection because an attacker could input malicious SQL, such ' OR '1'='1' --, which always returns true and retrieves all users.
import sqlite3
def get_user_info(username):
conn = sqlite3.connect("users.db")
cursor = conn.cursor()
query = f"SELECT * FROM users WHERE username = '{username}'" # 🚨 INSECURE
cursor.execute(query) # Attacker can input: ' OR '1'='1' --
result = cursor.fetchall()
conn.close()
return result
Securing this code
Using parameterized queries ensures user input is treated as data, not code, so the database never executes user input directly.
import sqlite3
def get_user_info_secure(username):
conn = sqlite3.connect("users.db")
cursor = conn.cursor()
query = "SELECT * FROM users WHERE username = ?"
cursor.execute(query, (username,)) # ✅ SAFE: Prevents SQL Injection
result = cursor.fetchall()
conn.close()
return result
Insecure Code
In this example, credentials are stored in the source code, making them easy to steal.
import pymysql
# 🚨 INSECURE: Hardcoded credentials
DB_HOST = "localhost"
DB_USER = "admin"
DB_PASSWORD = "supersecret123"
DB_NAME = "sensitive_db"
def connect_db():
conn = pymysql.connect(
host=DB_HOST,
user=DB_USER,
password=DB_PASSWORD,
database=DB_NAME
)
return conn
def get_users():
conn = connect_db()
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
result = cursor.fetchall()
conn.close()
return result
Secure Code
In the secure code, credentials are stored with environment variables to keep secrets out of the codebase, reducing the risk of exposure.
import os
import pymysql
from dotenv import load_dotenv
# Load environment variables from .env file (if used)
load_dotenv()
def connect_db():
conn = pymysql.connect(
host=os.getenv("DB_HOST"),
user=os.getenv("DB_USER"),
password=os.getenv("DB_PASSWORD"),
database=os.getenv("DB_NAME")
)
return conn
def get_users():
conn = connect_db()
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
result = cursor.fetchall()
conn.close()
return result
Insecure code
The example below shows a function running with a role check that doesn't verify whether or not the user is an admin, which, in this case, gives all users the ability to delete accounts.
def delete_user(user_id, current_user_role):
"""Deletes a user account"""
if current_user_role: # 🚨 No role check! Any user can delete accounts.
print(f"User {user_id} deleted.")
else:
print("Access denied.")
# Test cases
delete_user(5, "regular_user") # 🚨 A normal user can delete accounts!
delete_user(3, "admin") # ✅ Admin should have access
Secure Code
This secure example solves that issue by verifying that a user has admin permissions before granting the user that privilege.
def delete_user(user_id, current_user_role):
"""Securely deletes a user account"""
if current_user_role != "admin": # ✅ Only admins can delete users
print("Access denied: Insufficient privileges.")
return
print(f"User {user_id} deleted.")
# Test cases
delete_user(5, "regular_user") # ❌ Access denied
delete_user(3, "admin") # ✅ Admin can delete accounts
Insecure code
The error messages in this code example give too much information to attackers, who can use them to find valid usernames, guess passwords, and identify errors.
def login(username, password):
try:
# Simulate database connection
if username != "admin":
raise ValueError("User not found in database") # 🚨 Reveals too much info
if password != "securepassword":
raise ValueError("Incorrect password") # 🚨 Helps attackers guess passwords
return "Login successful!"
except Exception as e:
return f"Error: {e}" # 🚨 Exposes internal error details
# Test the function
print(login("testuser", "password"))
Secure Code
These generic messages do not expose system details, so attackers can't see whether the username or password was wrong or what type of error is returned.
import logging
# Configure logging
logging.basicConfig(filename="errors.log", level=logging.ERROR)
def login(username, password):
try:
# Simulate database connection
if username != "admin" or password != "securepassword":
return "Invalid login credentials." # ✅ Generic message
return "Login successful!"
except Exception as e:
logging.error(f"Unexpected error: {e}") # ✅ Logs detailed error securely
return "Something went wrong. Please try again later." # ✅ Generic response
# Test the function
print(login("testuser", "password"))
We’ve written the definitive guide for secure coding practices that you can read here, but for now:
Code security is not just a technical requirement; it’s a fundamental practice to ensure trust, resilience, and reliability in modern software. By prioritizing secure coding practices, developers safeguard not just their applications but also the users and businesses that rely on them daily.
Whether you’re a seasoned developer or just starting your journey, embracing secure coding is a skill that will pay dividends in both security and professional growth. To find out how Symbiotic Security's AI can help, check out our solutions page here.