Code Quality and Security Linting
Common Code Security Pitfalls
It's hard to list all the potential security pitfalls when writing code, and even creating a list of the most common ones is challenging. There are many factors to consider, such as the programming language, the type of application, the environment, the industry, and the specific requirements of the project. However, some security pitfalls are probably more prevalent and can be found across different scenarios. The goal in this section is to highlight some of them without pretending to be exhaustive. The code snippets provided are intentionally simplified to illustrate the issues clearly. They are written in Python, but the concepts are applicable to other languages as well.
Hardcoded Secrets and Credentials
Embedding sensitive credentials directly in source code can lead to leaks and unauthorized access if the code is exposed.
Insecure Code
# Hardcoded API key
API_KEY = "my-super-secret-api-key"
# Hardcoded database password
DB_PASSWORD = "password123"
Secure Alternative
import os
# Fetch from environment variables
API_KEY = os.getenv("API_KEY")
# Fetch from a secure vault
DB_PASSWORD = os.getenv("DB_PASSWORD")
Reading variables from environment variables is not only more secure but also allows for easier configuration management across different environments. With the availability of tools like orchestration platforms, configuration management tools, and secrets management services, the job of managing secrets and configurations has become more manageable.
SQL Injection Vulnerabilities
Constructing SQL queries using string concatenation can expose the application to SQL injection attacks.
Insecure Code
import sqlite3
def get_user(username):
conn = sqlite3.connect("users.db")
cursor = conn.cursor()
query = f"SELECT * FROM users WHERE username = '{username}'"
# Dangerous: vulnerable to SQL injection
cursor.execute(query)
return cursor.fetchall()
In the above code, if the username parameter is not sanitized, an attacker could inject malicious SQL code like '; DROP TABLE users; -- to delete the users table.
Secure Alternative:
import sqlite3
def get_user(username):
conn = sqlite3.connect("users.db")
cursor = conn.cursor()
query = "SELECT * FROM users WHERE username = ?"
# Parameterized query prevents SQL injection
cursor.execute(query, (username,))
return cursor.fetchall()
Insufficient Input Validation
Failing to validate user inputs can lead to security risks like command injection and cross-site scripting (XSS).
Insecure Code
import os
def execute_command(user_input):
# Dangerous: could allow arbitrary command execution
os.system("echo " + user_input)
If the user_input is "; rm -rf some_folder;", it would execute the rm -rf some_folder command, leading to data loss.
Secure Alternative:
import shlex, subprocess
def execute_command(user_input):
# Sanitize input
safe_input = shlex.quote(user_input)
subprocess.run(["echo", safe_input], check=True)
The final command executed would be:
echo '; rm -rf some_folder;'
Improper Error Handling and Information Disclosure
Exposing stack traces or debug logs in production can leak sensitive system details.
Insecure Code
try:
result = 1 / 0
except Exception as e:
# Reveals system information
print("Error:", e)
DevSecOps in Practice
A Hands-On Guide to Operationalizing DevSecOps at ScaleEnroll now to unlock current content and receive all future updates for free. Your purchase supports the author and fuels the creation of more exciting content. Act fast, as the price will rise as the course nears completion!
