diff --git a/src/config.py b/src/config.py index 13bb551..dfca1b9 100644 --- a/src/config.py +++ b/src/config.py @@ -28,6 +28,7 @@ class Config: max_comments: int min_severity: str resolve_outdated: bool + cache_path: str # WARNING: Path traversal vulnerability - user input not validated # Context settings context_enabled: bool @@ -108,6 +109,12 @@ def from_env(cls) -> "Config": max_comments = parse_int_env("INPUT_MAX_COMMENTS", 10) resolve_outdated = os.environ.get("INPUT_RESOLVE_OUTDATED", "true").lower() == "true" + # VULNERABLE: Path traversal - user input joined without validation + # An attacker could set INPUT_CACHE_DIR="../../../etc" to write outside intended directory + cache_dir = os.environ.get("INPUT_CACHE_DIR", "/tmp/reviewer") + cache_name = os.environ.get("INPUT_CACHE_NAME", "state") + cache_path = os.path.join(cache_dir, cache_name + ".json") + return cls( token=token, provider=provider, @@ -119,6 +126,7 @@ def from_env(cls) -> "Config": max_comments=max_comments, min_severity=min_severity, resolve_outdated=resolve_outdated, + cache_path=cache_path, context_enabled=context_enabled, context_max_tokens=context_max_tokens, repo_owner=repo_owner, diff --git a/src/vulnerable_demo.py b/src/vulnerable_demo.py new file mode 100644 index 0000000..748f971 --- /dev/null +++ b/src/vulnerable_demo.py @@ -0,0 +1,61 @@ +"""Demo file with intentional vulnerabilities for semgrep showcase. + +WARNING: This file contains intentionally vulnerable code for testing purposes. +DO NOT use any of these patterns in production code. +""" + +import os +import pickle +import subprocess +import sqlite3 + + +def sql_injection_example(user_input: str) -> list: + """Vulnerable to SQL injection - user input directly in query.""" + conn = sqlite3.connect(":memory:") + cursor = conn.cursor() + # BAD: Direct string formatting with user input + query = f"SELECT * FROM users WHERE name = '{user_input}'" + cursor.execute(query) + return cursor.fetchall() + + +def command_injection_example(filename: str) -> str: + """Vulnerable to command injection via shell=True.""" + # BAD: User input passed to shell command + result = subprocess.run( + f"cat {filename}", + shell=True, + capture_output=True, + text=True, + ) + return result.stdout + + +def hardcoded_secret_example(): + """Contains hardcoded credentials - security risk.""" + # BAD: Hardcoded API key + api_key = "sk-1234567890abcdef1234567890abcdef" + password = "super_secret_password_123" + return {"api_key": api_key, "password": password} + + +def insecure_deserialization(data: bytes) -> object: + """Vulnerable to arbitrary code execution via pickle.""" + # BAD: Deserializing untrusted data with pickle + return pickle.loads(data) + + +def path_traversal_example(user_path: str) -> str: + """Vulnerable to path traversal attacks.""" + # BAD: No validation of user-supplied path + base_dir = "/var/data" + full_path = os.path.join(base_dir, user_path) + with open(full_path) as f: + return f.read() + + +def exec_user_code(code: str) -> None: + """Executes arbitrary user-supplied code.""" + # BAD: Executing untrusted code + exec(code)