Skip to content

Commit e7b78be

Browse files
authored
Merge pull request #155 from braboj/codex/provide-secure-code-examples-for-owasp-top-ten
Add secure coding examples
2 parents 1309cfd + 167fa2a commit e7b78be

File tree

7 files changed

+100
-0
lines changed

7 files changed

+100
-0
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Example: Input Validation
2+
# ------------------------------------------------------------------------------
3+
# Validates user input before using it. This prevents unexpected behaviour
4+
# or vulnerabilities such as injection or crashes.
5+
6+
import re
7+
8+
user_input = input('Enter an age (0-120): ')
9+
10+
# Accept only digits using a regular expression
11+
if not re.fullmatch(r"\d+", user_input):
12+
raise ValueError('Input must be a positive integer')
13+
14+
age = int(user_input)
15+
16+
if not 0 <= age <= 120:
17+
raise ValueError('Age out of expected range')
18+
19+
print(f'Your age is {age}')
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Password Storage - Bad Example
2+
# ------------------------------------------------------------------------------
3+
# Storing or hashing passwords without a salt and a strong hash function makes
4+
# them easy to crack if the database is compromised.
5+
6+
import hashlib
7+
8+
password = input('Enter password: ')
9+
10+
# BAD: Unsalted, single round MD5 hash
11+
hash_value = hashlib.md5(password.encode('utf-8')).hexdigest()
12+
print('Storing password hash:', hash_value)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Password Storage - Good Example
2+
# ------------------------------------------------------------------------------
3+
# Use a strong key derivation function with a unique salt for each password.
4+
# PBKDF2 is built into Python's hashlib module.
5+
6+
import os
7+
import hashlib
8+
import base64
9+
10+
password = input('Enter password: ')
11+
12+
salt = os.urandom(16)
13+
hash_bytes = hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), salt, 100_000)
14+
15+
encoded_salt = base64.b64encode(salt).decode('utf-8')
16+
encoded_hash = base64.b64encode(hash_bytes).decode('utf-8')
17+
18+
print('Storing password hash:')
19+
print(f'salt={encoded_salt}')
20+
print(f'hash={encoded_hash}')
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Secret Management
2+
# ------------------------------------------------------------------------------
3+
# Retrieve secrets like API keys from environment variables instead of
4+
# hardcoding them in the source code.
5+
6+
import os
7+
8+
api_key = os.getenv('API_KEY')
9+
if api_key is None:
10+
raise RuntimeError('API_KEY environment variable is not set')
11+
12+
print('Loaded API key of length', len(api_key))
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# SQL Injection - Bad Example
2+
# ------------------------------------------------------------------------------
3+
# Directly formatting user input into an SQL query can allow injection attacks.
4+
# NEVER build queries using string concatenation with untrusted data.
5+
6+
import sqlite3
7+
8+
conn = sqlite3.connect(':memory:')
9+
cursor = conn.cursor()
10+
cursor.execute('CREATE TABLE users(id INTEGER PRIMARY KEY, username TEXT)')
11+
12+
username = input('Enter username to lookup: ')
13+
14+
# BAD: user input is concatenated directly into the query
15+
query = f"SELECT * FROM users WHERE username = '{username}'"
16+
print('Executing:', query)
17+
for row in cursor.execute(query):
18+
print(row)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# SQL Injection - Good Example
2+
# ------------------------------------------------------------------------------
3+
# Parameterized queries separate data from code, preventing SQL injection.
4+
# Use parameter placeholders and pass parameters as a tuple.
5+
6+
import sqlite3
7+
8+
conn = sqlite3.connect(':memory:')
9+
cursor = conn.cursor()
10+
cursor.execute('CREATE TABLE users(id INTEGER PRIMARY KEY, username TEXT)')
11+
12+
username = input('Enter username to lookup: ')
13+
14+
# GOOD: query uses ? placeholders and parameters tuple
15+
query = 'SELECT * FROM users WHERE username = ?'
16+
print('Executing:', query, 'with params', username)
17+
for row in cursor.execute(query, (username,)):
18+
print(row)

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ nav:
2828
- OOP Basics: B01_oop_pillars.md
2929
- SOLID Principles: B02_solid_principles.md
3030
- Design Patterns: B03_design_patterns.md
31+
- Secure Design: B04_secure_design.md
3132

3233
- Libraries:
3334
- Logging: C01_logging.md

0 commit comments

Comments
 (0)