Feedback

Chat Icon

DevSecOps in Practice

A Hands-On Guide to Operationalizing DevSecOps at Scale

Code Quality and Security Linting
57%

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 Scale

Enroll 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!