diff --git a/.github/workflows/cycode-sast-pr-scan.yml b/.github/workflows/cycode-sast-pr-scan.yml index 4803c26..2255ac7 100644 --- a/.github/workflows/cycode-sast-pr-scan.yml +++ b/.github/workflows/cycode-sast-pr-scan.yml @@ -12,12 +12,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.12" diff --git a/.github/workflows/cycode-sast-scan.yml b/.github/workflows/cycode-sast-scan.yml index d52e9aa..0e28b7c 100644 --- a/.github/workflows/cycode-sast-scan.yml +++ b/.github/workflows/cycode-sast-scan.yml @@ -11,10 +11,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.12" diff --git a/vulnerable_apps/login_handler.py b/vulnerable_apps/login_handler.py new file mode 100644 index 0000000..b3c8bba --- /dev/null +++ b/vulnerable_apps/login_handler.py @@ -0,0 +1,68 @@ +""" +Login Handler — Web endpoint for user authentication +Exposes the authentication module over HTTP +""" +from flask import Flask, request, jsonify +import sqlite3 +import hashlib + +app = Flask(__name__) + + +@app.route('/login', methods=['POST']) +def login(): + """Handle login form submission""" + username = request.form.get('username') + password = request.form.get('password') + + conn = sqlite3.connect('app.db') + cursor = conn.cursor() + + # Vulnerable: user-controlled input flows directly into SQL query + query = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'" + cursor.execute(query) + + user = cursor.fetchone() + conn.close() + + if user: + return jsonify({'status': 'success', 'user': user[0]}) + return jsonify({'status': 'unauthorized'}), 401 + + +@app.route('/search', methods=['GET']) +def search_users(): + """Search users by name""" + name = request.args.get('name', '') + + conn = sqlite3.connect('app.db') + cursor = conn.cursor() + + # Vulnerable: query parameter unsanitized in SQL + cursor.execute("SELECT username, email FROM users WHERE username LIKE '%" + name + "%'") + + results = cursor.fetchall() + conn.close() + return jsonify({'results': results}) + + +@app.route('/register', methods=['POST']) +def register(): + """Register a new user""" + username = request.form.get('username') + password = request.form.get('password') + + # Vulnerable: MD5 is cryptographically broken for password storage + password_hash = hashlib.md5(password.encode()).hexdigest() + + conn = sqlite3.connect('app.db') + cursor = conn.cursor() + cursor.execute("INSERT INTO users (username, password) VALUES (?, ?)", (username, password_hash)) + conn.commit() + conn.close() + + return jsonify({'status': 'created'}), 201 + + +if __name__ == '__main__': + app.run(debug=True)