-
Notifications
You must be signed in to change notification settings - Fork 230
Trigger pr comments #77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,214 @@ | ||||||
| from fastapi import FastAPI, HTTPException, Header, Request | ||||||
| from typing import Optional | ||||||
| from models import VideoGame, User | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ℹ️ Codacy found a minor CodeStyle issue: 'models.User' imported but unused (F401) The issue reported by the Prospector linter indicates that the To fix this issue, you can remove the unused import. Since the
Suggested change
This comment was generated by an experimental AI tool. |
||||||
| from database import video_games, users | ||||||
| import sqlite3 | ||||||
| import os | ||||||
| import requests | ||||||
| from fastapi.responses import RedirectResponse | ||||||
|
|
||||||
| app = FastAPI( | ||||||
| title="Intentionally Insecure Video Game API", | ||||||
| description="An API designed for security education, demonstrating common vulnerabilities.", | ||||||
| version="1.0.0", | ||||||
| contact={ | ||||||
| "name": "Your Name", | ||||||
| "email": "[email protected]", | ||||||
| }, | ||||||
| ) | ||||||
|
|
||||||
| # Initialize the SQLite database | ||||||
| def init_db(): | ||||||
| if not os.path.exists('videogames.db'): | ||||||
| conn = sqlite3.connect('videogames.db') | ||||||
| cursor = conn.cursor() | ||||||
| # Create table | ||||||
| cursor.execute(''' | ||||||
| CREATE TABLE video_games ( | ||||||
| id INTEGER PRIMARY KEY, | ||||||
| title TEXT NOT NULL, | ||||||
| developer TEXT NOT NULL, | ||||||
| publisher TEXT NOT NULL, | ||||||
| year_published INTEGER NOT NULL, | ||||||
| sales INTEGER NOT NULL | ||||||
| ) | ||||||
| ''') | ||||||
| # Insert data | ||||||
| for game in video_games: | ||||||
| cursor.execute(''' | ||||||
| INSERT INTO video_games (id, title, developer, publisher, year_published, sales) | ||||||
| VALUES (?, ?, ?, ?, ?, ?) | ||||||
| ''', (game.id, game.title, game.developer, game.publisher, game.year_published, game.sales)) | ||||||
| conn.commit() | ||||||
| conn.close() | ||||||
|
|
||||||
| # Call the init_db function when the app starts | ||||||
| @app.on_event("startup") | ||||||
| def startup_event(): | ||||||
| init_db() | ||||||
|
|
||||||
| # Public endpoint to get basic video game info | ||||||
| @app.get("/games") | ||||||
| def get_games(): | ||||||
| return video_games | ||||||
|
|
||||||
| # Vulnerable endpoint: No authentication required to get sensitive sales data | ||||||
| @app.get("/games/{game_id}/sales") | ||||||
| def get_game_sales(game_id: int): | ||||||
| # Vulnerability: No authentication or authorization checks (API1:2019 - Broken Object Level Authorization) | ||||||
| for game in video_games: | ||||||
| if game.id == game_id: | ||||||
| return {"title": game.title, "sales": game.sales} | ||||||
| raise HTTPException(status_code=404, detail="Game not found") | ||||||
|
|
||||||
| # Vulnerable endpoint: Weak authentication and improper authorization | ||||||
| @app.post("/games") | ||||||
| def add_game(game: VideoGame, Authorization: Optional[str] = Header(None)): | ||||||
| # Vulnerability: Token sent in Authorization header without proper validation (API2:2019 - Broken Authentication) | ||||||
| if not Authorization: | ||||||
| raise HTTPException(status_code=401, detail="Authorization header required") | ||||||
|
|
||||||
| # Extract Bearer token | ||||||
| if not Authorization.startswith("Bearer "): | ||||||
| raise HTTPException(status_code=401, detail="Invalid Authorization header format") | ||||||
| token = Authorization.split(" ")[1] | ||||||
|
|
||||||
| # Vulnerability: Insecure token handling and authorization (API5:2019 - Broken Function Level Authorization) | ||||||
| for user in users: | ||||||
| if user.token == token: | ||||||
| if user.is_admin: | ||||||
| video_games.append(game) | ||||||
| return {"message": "Game added"} | ||||||
| else: | ||||||
| raise HTTPException(status_code=403, detail="Not authorized") | ||||||
| raise HTTPException(status_code=401, detail="Invalid token") | ||||||
|
|
||||||
| # Vulnerable endpoint: Exposes sensitive user data | ||||||
| @app.get("/users") | ||||||
| def get_users(): | ||||||
| # Vulnerability: Exposes tokens and admin status (API3:2019 - Excessive Data Exposure) | ||||||
| return users | ||||||
|
|
||||||
| # Additional vulnerable endpoint: No rate limiting implemented | ||||||
| @app.post("/login") | ||||||
| def login(username: str): | ||||||
| # Vulnerability: No rate limiting allows brute-force attacks (API4:2019 - Lack of Resources & Rate Limiting) | ||||||
| for user in users: | ||||||
| if user.username == username: | ||||||
| return {"token": user.token} | ||||||
| raise HTTPException(status_code=404, detail="User not found") | ||||||
|
|
||||||
| # Additional vulnerable endpoint: Mass assignment | ||||||
| @app.put("/games/{game_id}") | ||||||
| def update_game(game_id: int, updated_game: VideoGame): | ||||||
| # Vulnerability: Mass assignment allows overwriting of unintended fields (API6:2019 - Mass Assignment) | ||||||
| for i, game in enumerate(video_games): | ||||||
| if game.id == game_id: | ||||||
| video_games[i] = updated_game | ||||||
| return {"message": "Game updated"} | ||||||
| raise HTTPException(status_code=404, detail="Game not found") | ||||||
|
|
||||||
| # Additional vulnerable endpoint: SQL Injection | ||||||
| @app.get("/search") | ||||||
| def search_games(query: str): | ||||||
| # Vulnerability: User input is not sanitized (API8:2019 - Injection) | ||||||
| conn = sqlite3.connect('videogames.db') | ||||||
| cursor = conn.cursor() | ||||||
| try: | ||||||
| sql_query = f"SELECT * FROM video_games WHERE title = '{query}'" | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue identified by the Bandit linter is a potential SQL injection vulnerability. This occurs because the user input ( To fix this issue, we should use parameterized queries, which safely handle user input and prevent SQL injection attacks. Here's the single line change to implement this:
Suggested change
This comment was generated by an experimental AI tool. |
||||||
| cursor.execute(sql_query) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Security control: Static Code Analysis Python Semgrep Sqlalchemy Raw Sql Query Concatenation Risks Sql Injection Avoiding SQL string concatenation: untrusted input concatenated with raw SQL query can result in SQL Injection. In order to execute raw query safely, prepared statement should be used. SQLAlchemy provides TextualSQL to easily used prepared statement with named parameters. For complex SQL composition, use SQL Expression Language or Schema Definition Language. In most cases, SQLAlchemy ORM will be a better option. Severity: HIGH Jit Bot commands and options (e.g., ignore issue)You can trigger Jit actions by commenting on this PR review:
|
||||||
| rows = cursor.fetchall() | ||||||
| except Exception as e: | ||||||
| # Return the exception message for educational purposes (not recommended in production) | ||||||
| return {"error": str(e)} | ||||||
| finally: | ||||||
| conn.close() | ||||||
| # Convert rows to list of dictionaries | ||||||
| results = [] | ||||||
| for row in rows: | ||||||
| results.append({ | ||||||
| "id": row[0], | ||||||
| "title": row[1], | ||||||
| "developer": row[2], | ||||||
| "publisher": row[3], | ||||||
| "year_published": row[4], | ||||||
| "sales": row[5], | ||||||
| }) | ||||||
| return results | ||||||
|
|
||||||
| # Additional vulnerable endpoint: Improper assets management | ||||||
| @app.get("/.env") | ||||||
| def get_env(): | ||||||
| # Vulnerability: Sensitive files are exposed (API9:2019 - Improper Assets Management) | ||||||
| return {"SECRET_KEY": "supersecretkey"} | ||||||
|
|
||||||
| # Additional vulnerable endpoint: Insufficient logging and monitoring | ||||||
| @app.post("/admin/delete_game") | ||||||
| def delete_game(game_id: int, Authorization: Optional[str] = Header(None)): | ||||||
| # Vulnerability: Actions are not logged (API10:2019 - Insufficient Logging & Monitoring) | ||||||
| if not Authorization: | ||||||
| raise HTTPException(status_code=401, detail="Authorization header required") | ||||||
|
|
||||||
| # Extract Bearer token | ||||||
| if not Authorization.startswith("Bearer "): | ||||||
| raise HTTPException(status_code=401, detail="Invalid Authorization header format") | ||||||
| token = Authorization.split(" ")[1] | ||||||
|
|
||||||
| for user in users: | ||||||
| if user.token == token and user.is_admin: | ||||||
| for i, game in enumerate(video_games): | ||||||
| if game.id == game_id: | ||||||
| deleted_game = video_games.pop(i) | ||||||
| # No logging of the deletion action | ||||||
| return {"message": f"Game '{deleted_game.title}' deleted"} | ||||||
| raise HTTPException(status_code=404, detail="Game not found") | ||||||
| raise HTTPException(status_code=403, detail="Not authorized") | ||||||
|
|
||||||
| @app.post("/feedback") | ||||||
| def submit_feedback(feedback: str): | ||||||
| # Vulnerability: User input is not sanitized before rendering (API7:2019 - Security Misconfiguration) | ||||||
| response = HTMLResponse(content=f"<html><body><h1>Feedback Received</h1><p>{feedback}</p></body></html>") | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ℹ️ Codacy found a minor CodeStyle issue: undefined name 'HTMLResponse' (F821) The issue identified by the Prospector linter is that the name Here’s the suggested code change to fix the issue by adding the necessary import statement:
Suggested change
This comment was generated by an experimental AI tool. |
||||||
| return response | ||||||
|
|
||||||
| # Additional vulnerable endpoint: Insecure Direct Object References (IDOR) | ||||||
| @app.get("/user_profile") | ||||||
| def get_user_profile(user_id: int): | ||||||
| # Vulnerability: No authorization checks (API1:2019 - Broken Object Level Authorization) | ||||||
| for user in users: | ||||||
| if user.username == f"user{user_id}": | ||||||
| return user | ||||||
| raise HTTPException(status_code=404, detail="User not found") | ||||||
|
|
||||||
| # Additional vulnerable endpoint: Cross-Site Request Forgery (CSRF) | ||||||
| @app.post("/update_profile") | ||||||
| def update_profile(username: str, email: str, Authorization: Optional[str] = Header(None)): | ||||||
| # Vulnerability: No CSRF protection (API5:2019 - Broken Function Level Authorization) | ||||||
| if not Authorization: | ||||||
| raise HTTPException(status_code=401, detail="Authorization header required") | ||||||
| # Extract Bearer token | ||||||
| if not Authorization.startswith("Bearer "): | ||||||
| raise HTTPException(status_code=401, detail="Invalid Authorization header format") | ||||||
| token = Authorization.split(" ")[1] | ||||||
| # Simulate updating user profile | ||||||
| for user in users: | ||||||
| if user.token == token: | ||||||
| user.username = username | ||||||
| user.email = email # Assuming 'email' field exists in User model | ||||||
| return {"message": "Profile updated"} | ||||||
| raise HTTPException(status_code=401, detail="Invalid token") | ||||||
|
|
||||||
| # Additional vulnerable endpoint: Server-Side Request Forgery (SSRF) | ||||||
| @app.get("/fetch_url") | ||||||
| def fetch_url_content(url: str): | ||||||
| # Vulnerability: No validation of the URL (API10:2019 - Unsafe Consumption of APIs) | ||||||
| try: | ||||||
| response = requests.get(url) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Security control: Static Code Analysis Python Semgrep Potential Ssrf With Request Data In Server-Side Requests Data from request object is passed to a new server-side request. This could lead to a server-side request forgery (SSRF). To mitigate, ensure that schemes and hosts are validated against an allowlist, do not forward the response to the user, and ensure proper authentication and transport-layer security in the proxied request. Severity: HIGH Jit Bot commands and options (e.g., ignore issue)You can trigger Jit actions by commenting on this PR review:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue identified by the Bandit linter is that the To fix this issue, you can specify a timeout in the
Suggested change
This comment was generated by an experimental AI tool. |
||||||
| return {"content": response.text} | ||||||
| except Exception as e: | ||||||
| return {"error": str(e)} | ||||||
|
|
||||||
| # Additional vulnerable endpoint: Unvalidated Redirects and Forwards | ||||||
| @app.get("/redirect") | ||||||
| def unsafe_redirect(next: str): | ||||||
| # Vulnerability: Unvalidated redirect (API10:2019 - Unsafe Consumption of APIs) | ||||||
| return RedirectResponse(url=next) | ||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,168 @@ | ||||||||||
| from flask import Flask, request, render_template_string, jsonify | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ℹ️ Codacy found a minor CodeStyle issue: 'flask.jsonify' imported but unused (F401) The issue reported by the Prospector linter indicates that the To fix the issue, you can simply remove the unused import statement for
Suggested change
This comment was generated by an experimental AI tool. |
||||||||||
| import subprocess | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue with importing the If the
Suggested change
This comment was generated by an experimental AI tool. |
||||||||||
| import os | ||||||||||
| import sqlite3 | ||||||||||
| import requests | ||||||||||
| from lxml import etree | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Security control: Static Code Analysis Python Semgrep Potential Xxe Vulnerability With Native Python Xml Libraries Found use of the native Python XML libraries, which is vulnerable to XML external entity (XXE) Severity: HIGH Jit Bot commands and options (e.g., ignore issue)You can trigger Jit actions by commenting on this PR review:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue identified by the Bandit linter pertains to the use of To mitigate this risk, it is recommended to use the To fix the issue, you can replace the import statement for
Suggested change
This comment was generated by an experimental AI tool. |
||||||||||
|
|
||||||||||
| # Example hardcoded AWS credentials (sensitive data leakage) | ||||||||||
| aws_access_key_id = 'AKIA2JAPX77RGLB664VE' | ||||||||||
| aws_secret = 'v5xpjkWYoy45fGKFSMajSn+sqs22WI2niacX9yO5' | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue identified by the Bandit linter is that the AWS secret key is hardcoded directly in the Python code. Hardcoding sensitive information such as AWS credentials in your source code can lead to security vulnerabilities, as anyone with access to the code can see these credentials. This practice can lead to unauthorized access to your AWS resources, data breaches, and other security risks. To fix this issue, it's recommended to use environment variables to securely store sensitive information. This way, the credentials are not exposed in the source code. Here's the suggested change to implement this fix:
Suggested change
Make sure to set the This comment was generated by an experimental AI tool. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❌ Codacy found a critical Security issue: Amazon Web Services secret key (aws_secret_key) The issue identified by the Prospector linter is that hardcoding sensitive information, such as AWS credentials, directly in the source code can lead to security vulnerabilities. If the code is shared or deployed, these credentials can be exposed, allowing unauthorized access to AWS resources. It is crucial to manage sensitive data securely, typically by using environment variables or secure vaults. To fix this issue, you should remove the hardcoded AWS secret and instead retrieve it from an environment variable. Here’s the suggested change:
Suggested change
This comment was generated by an experimental AI tool. |
||||||||||
|
|
||||||||||
| app = Flask(__name__) | ||||||||||
|
|
||||||||||
| @app.route('/', methods=['GET', 'POST']) | ||||||||||
| def index(): | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ℹ️ Codacy found a minor CodeStyle issue: index is too complex (22) (MC0001) The issue described by the Prospector linter indicates that the To simplify the
Suggested change
This change suggests that we create a new function called This comment was generated by an experimental AI tool. |
||||||||||
| output = '' | ||||||||||
| # 1 - SQL Injection | ||||||||||
| db = sqlite3.connect("tutorial.db") | ||||||||||
| cursor = db.cursor() | ||||||||||
| username = '' | ||||||||||
| password = '' | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue highlighted by the Bandit linter is that the variable To fix this issue, you can modify the code to retrieve the password from a more secure source. Here's a suggestion to replace the hardcoded password:
Suggested change
This change retrieves the password from an environment variable named This comment was generated by an experimental AI tool. |
||||||||||
| try: | ||||||||||
| cursor.execute("SELECT * FROM users WHERE username = '%s' AND password = '%s'" % (username, password)) | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue identified by the Bandit linter is a potential SQL injection vulnerability due to the use of string interpolation to construct the SQL query. By directly inserting user input into the SQL query string, an attacker could manipulate the input to execute arbitrary SQL commands, potentially compromising the database. To fix this issue, we should use parameterized queries, which safely handle user input by separating the data from the query structure. This prevents any user input from being treated as executable SQL code. Here's the single line change to fix the issue:
Suggested change
This comment was generated by an experimental AI tool. |
||||||||||
| except: | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue with the line To fix this, we should at least log the exception or handle it in a way that provides feedback. A common approach is to catch specific exceptions or log the error. Here's a single line code suggestion to improve the error handling by logging the exception:
Suggested change
This comment was generated by an experimental AI tool. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ℹ️ Codacy found a minor CodeStyle issue: do not use bare 'except' (E722) The issue with using a bare To fix the issue, you can change the bare Here’s the suggested code change:
Suggested change
This comment was generated by an experimental AI tool. |
||||||||||
| pass | ||||||||||
|
|
||||||||||
| if request.method == 'POST': | ||||||||||
| # 2 - Command Injection | ||||||||||
| if 'command' in request.form: | ||||||||||
| cmd = request.form['command'] | ||||||||||
| process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Security control: Static Code Analysis Python Semgrep User Input In Unsafe Subprocess Call In Flask Detected user input entering a Severity: HIGH Jit Bot commands and options (e.g., ignore issue)You can trigger Jit actions by commenting on this PR review:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Security control: Static Code Analysis Python Semgrep User Data In Subprocess Function Risks Command Injection Vulnerability Detected subprocess function 'Popen' with user controlled data. A malicious actor could leverage this to perform command injection. You may consider using 'shlex.escape()'. Severity: HIGH Jit Bot commands and options (e.g., ignore issue)You can trigger Jit actions by commenting on this PR review:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❌ Codacy found a critical Security issue: subprocess call with shell=True identified, security issue. The issue identified by Bandit is related to the use of To mitigate this risk, it's recommended to avoid using Here’s the suggested code change:
Suggested change
This change ensures that This comment was generated by an experimental AI tool. |
||||||||||
| stdout, stderr = process.communicate() | ||||||||||
| if process.returncode == 0: | ||||||||||
| output = stdout.decode('utf-8') | ||||||||||
| else: | ||||||||||
| output = f"Error (Exit Code: {process.returncode}):\n{stderr.decode('utf-8')}" | ||||||||||
|
|
||||||||||
| # 3 - File Upload with no restrictions, and path traversal | ||||||||||
| elif 'file' in request.files: | ||||||||||
| uploaded_file = request.files['file'] | ||||||||||
| uploaded_file.save(os.path.join('/uploads', uploaded_file.filename)) | ||||||||||
| output = f"File {uploaded_file.filename} uploaded successfully!" | ||||||||||
|
|
||||||||||
| # 4 - SQL Injection via input | ||||||||||
| elif 'sql' in request.form: | ||||||||||
| sql = request.form['sql'] | ||||||||||
| try: | ||||||||||
| # Execute the user's SQL query | ||||||||||
| cursor.execute(sql) | ||||||||||
| # Fetch all rows from the query result | ||||||||||
| rows = cursor.fetchall() | ||||||||||
| # Format the results for display | ||||||||||
| if rows: | ||||||||||
| output = "Results:\n" + "\n".join(str(row) for row in rows) | ||||||||||
| else: | ||||||||||
| output = "Query executed successfully, but no results found." | ||||||||||
| except Exception as e: | ||||||||||
| output = f"SQL Error: {e}" | ||||||||||
|
|
||||||||||
| # 5 - Cross-Site Scripting (XSS) | ||||||||||
| elif 'xss' in request.form: | ||||||||||
| xss_input = request.form['xss'] | ||||||||||
| output = f"Reflected XSS result: {xss_input}" | ||||||||||
|
|
||||||||||
| # 6 - XML External Entity (XXE) Injection | ||||||||||
| elif 'xml' in request.form: | ||||||||||
| xml_data = request.form['xml'] | ||||||||||
| try: | ||||||||||
| # Use lxml to parse the XML data | ||||||||||
| parser = etree.XMLParser(load_dtd=True, resolve_entities=True) | ||||||||||
| tree = etree.fromstring(xml_data.encode(), parser) | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Security control: Static Code Analysis Python Semgrep Potential Xxe Vulnerability With Native Python Xml Libraries Found use of the native Python XML libraries, which is vulnerable to XML external entity (XXE) Severity: HIGH Jit Bot commands and options (e.g., ignore issue)You can trigger Jit actions by commenting on this PR review:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue identified by the Bandit linter is that using To fix the issue, you should replace the
Suggested change
This comment was generated by an experimental AI tool. |
||||||||||
| output = f"Parsed XML: {etree.tostring(tree, encoding='unicode')}" | ||||||||||
| except Exception as e: | ||||||||||
| output = f"XML Parsing Error: {e}" | ||||||||||
|
|
||||||||||
| # 7 - Server-Side Request Forgery (SSRF) | ||||||||||
| elif 'url' in request.form: | ||||||||||
| url = request.form['url'] | ||||||||||
| try: | ||||||||||
| response = requests.get(url) | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Security control: Static Code Analysis Python Semgrep Server-Side Request Forgery (Ssrf) Risk With User Data In Requests In Django Data from request object is passed to a new server-side request. This could lead to a server-side request forgery (SSRF). To mitigate, ensure that schemes and hosts are validated against an allowlist, do not forward the response to the user, and ensure proper authentication and transport-layer security in the proxied request. See https://owasp.org/www-community/attacks/Server_Side_Request_Forgery to learn more about SSRF vulnerabilities. Severity: HIGH Fix suggestion: This fix suggestion was generated by Jit. Please note that the suggestion might not always fit every use case. It is highly recommended that you check and review it before merging. Suggestion guidelines This remediation will modify the vulnerable request call in your code to validate the target URL before making a request. This helps prevent server-side request forgery (SSRF) attacks by ensuring that only allowed URLs are used.
Suggested change
Jit Bot commands and options (e.g., ignore issue)You can trigger Jit actions by commenting on this PR review:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue identified by the Bandit linter is that the To fix this issue, you can specify a timeout value in the
Suggested change
In this suggestion, a timeout of 10 seconds is set, which means that if the server does not respond within that time frame, a This comment was generated by an experimental AI tool. |
||||||||||
| output = f"SSRF Response: {response.text[:200]}" | ||||||||||
| except Exception as e: | ||||||||||
| output = f"SSRF Error: {e}" | ||||||||||
|
|
||||||||||
| # 8 - SQL injection with parameter instead of whole query | ||||||||||
| if 'username' in request.form: | ||||||||||
| username = request.form['username'] | ||||||||||
| try: | ||||||||||
| # Vulnerable SQL query using string interpolation | ||||||||||
| query = "SELECT password FROM users WHERE username = '{}'".format(username) | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue identified by the Bandit linter is that the SQL query is constructed using string interpolation, which makes it vulnerable to SQL injection attacks. An attacker could manipulate the To fix this issue, you should use parameterized queries, which safely handle user inputs by separating SQL logic from data. This prevents the possibility of SQL injection. Here's the suggested single line change: query = "SELECT password FROM users WHERE username = %s"
cursor.execute(query, (username,))This comment was generated by an experimental AI tool. |
||||||||||
| cursor.execute(query) | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Security control: Static Code Analysis Python Semgrep Sqlalchemy Raw Sql Query Concatenation Risks Sql Injection Avoiding SQL string concatenation: untrusted input concatenated with raw SQL query can result in SQL Injection. In order to execute raw query safely, prepared statement should be used. SQLAlchemy provides TextualSQL to easily used prepared statement with named parameters. For complex SQL composition, use SQL Expression Language or Schema Definition Language. In most cases, SQLAlchemy ORM will be a better option. Severity: HIGH Jit Bot commands and options (e.g., ignore issue)You can trigger Jit actions by commenting on this PR review:
|
||||||||||
| result = cursor.fetchone() | ||||||||||
| if result: | ||||||||||
| output = f"Password for {username}: {result[0]}" | ||||||||||
| else: | ||||||||||
| output = "User not found." | ||||||||||
| except Exception as e: | ||||||||||
| output = f"SQL Error: {e}" | ||||||||||
|
|
||||||||||
| return render_template_string(""" | ||||||||||
| <h1>Intentionally Insecure App</h1> | ||||||||||
| <hr> | ||||||||||
|
|
||||||||||
| <!-- Command Injection --> | ||||||||||
| <form action="/" method="post"> | ||||||||||
| <h2>Command Injection</h2> | ||||||||||
| <input type="text" name="command" value="ls -la"> | ||||||||||
| <input type="submit" value="Run"> | ||||||||||
| </form> | ||||||||||
| <br> | ||||||||||
|
|
||||||||||
| <!-- File Upload --> | ||||||||||
| <form action="/" method="post" enctype="multipart/form-data"> | ||||||||||
| <h2>Path Traversal via File Upload</h2> | ||||||||||
| <input type="file" name="file"> | ||||||||||
| <input type="submit" value="Upload"> | ||||||||||
| </form> | ||||||||||
| <p>Try uploading a file named: <code>../../../../etc/passwd</code></p> | ||||||||||
| <br> | ||||||||||
|
|
||||||||||
| <!-- SQL Injection --> | ||||||||||
| <form action="/" method="post"> | ||||||||||
| <h2>SQL Injection</h2> | ||||||||||
| <input type="text" name="sql" value="SELECT * FROM users WHERE username = 'admin' OR '1'='1'"> | ||||||||||
| <input type="submit" value="Run"> | ||||||||||
| </form> | ||||||||||
| <br> | ||||||||||
|
|
||||||||||
| <!-- Cross-Site Scripting (XSS) --> | ||||||||||
| <form action="/" method="post"> | ||||||||||
| Enter XSS payload: <input type="text" name="xss" value="<script>alert('XSS');</script>"> | ||||||||||
| <input type="submit" value="Run"> | ||||||||||
| </form> | ||||||||||
| <br> | ||||||||||
|
|
||||||||||
| <!-- XML External Entity (XXE) Injection --> | ||||||||||
| <form action="/" method="post"> | ||||||||||
| <h2>XML External Entity (XXE) Injection</h2> | ||||||||||
| <textarea name="xml" rows="5" cols="50"> | ||||||||||
| <?xml version="1.0"?> | ||||||||||
| <!DOCTYPE root [ | ||||||||||
| <!ENTITY xxe SYSTEM "file:///etc/passwd"> | ||||||||||
| ]> | ||||||||||
| <root>&xxe;</root> | ||||||||||
| </textarea> | ||||||||||
| <input type="submit" value="Parse XML"> | ||||||||||
| </form> | ||||||||||
| <br> | ||||||||||
|
|
||||||||||
| <!-- Server-Side Request Forgery (SSRF) --> | ||||||||||
| <form action="/" method="post"> | ||||||||||
| <h2>Server-Side Request Forgery (SSRF)</h2> | ||||||||||
| <input type="text" name="url" value="http://localhost:8080/"> | ||||||||||
| <input type="submit" value="Request"> | ||||||||||
| </form> | ||||||||||
| <br> | ||||||||||
| <!-- SQL Injection 2 --> | ||||||||||
| <h2>SQL Injection 2</h2> | ||||||||||
| <form action="/" method="post"> | ||||||||||
| Enter Username: <input type="text" name="username" value="' UNION SELECT username || ' : ' || password FROM users --"> | ||||||||||
| <input type="submit" value="Lookup"> | ||||||||||
| </form> | ||||||||||
| <hr> | ||||||||||
| <pre>{{ output|safe }}</pre> | ||||||||||
| """, output=output) | ||||||||||
|
|
||||||||||
| if __name__ == '__main__': | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ℹ️ Codacy found a minor CodeStyle issue: expected 2 blank lines after class or function definition, found 1 (E305) The issue identified by the Prospector linter is related to PEP 8, which is the style guide for Python code. According to PEP 8, there should be two blank lines before the definition of a class or function, including the To fix this issue, you need to add an additional blank line before the Here’s the code suggestion to address the issue: <code suggestion>
<code suggestion>
if __name__ == '__main__':This comment was generated by an experimental AI tool. |
||||||||||
| app.run(host='0.0.0.0', port=8080, debug=True) | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❌ Codacy found a critical Security issue: A Flask app appears to be run with debug=True, which exposes the Werkzeug debugger and allows the execution of arbitrary code. The issue identified by the Bandit linter is that running a Flask application with To fix this issue, you should set Here is the code suggestion to address the issue:
Suggested change
This comment was generated by an experimental AI tool. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue identified by the Bandit linter is that binding the application to To fix this issue, you can change the host parameter in the
Suggested change
This comment was generated by an experimental AI tool. |
||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| requests == 2.19.1 | ||
|
Check warning on line 1 in insecure-app/requirements.txt
|
||
| cryptography==3.3.2 | ||
| #cryptography==3.3.2 | ||
| flask==3.0.2 | ||
| #cryptograpy==3.3.2 | ||
| cryptograpy==3.3.2 | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ℹ️ Codacy found a minor CodeStyle issue: 'fastapi.Request' imported but unused (F401)
The issue reported by the Prospector linter indicates that the
Requestclass from the FastAPI module has been imported but is not being used anywhere in the provided code fragment. This can lead to unnecessary imports, making the code less clean and potentially confusing for other developers.To fix this issue, you can remove the unused import of
Request. Here’s the single line change:This comment was generated by an experimental AI tool.