From 4c3f96b26621b97e6aa7011bcfb3d221ae311a93 Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 3 Sep 2023 15:54:13 +0300 Subject: [PATCH 1/5] change go mod to core dev --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ec2780edd..e6c91815c 100644 --- a/go.mod +++ b/go.mod @@ -125,7 +125,7 @@ require ( // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20230828134416-f0db33dd9344 -replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230831153853-3ddf531482e7 +replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230903121243-b9d14a8b247f // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.2.6-0.20230418122323-2bf299dd6d27 diff --git a/go.sum b/go.sum index 4f38367f0..66ec45bab 100644 --- a/go.sum +++ b/go.sum @@ -239,8 +239,8 @@ github.com/jfrog/build-info-go v1.8.9-0.20230831151231-e5e7bd035ddc h1:pqu82clhP github.com/jfrog/build-info-go v1.8.9-0.20230831151231-e5e7bd035ddc/go.mod h1:QEskae5fQpjeY2PBzsjWtUQVskYSNDF2sSmw/Gx44dQ= github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk= github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230831153853-3ddf531482e7 h1:G60mVnOYqtVJ0UQpkYS2kmbqYZ59q1g8XivZt9W0tUg= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230831153853-3ddf531482e7/go.mod h1:eQJU+jDTcPVqOeHNheURqkMEMXDVNQFKKjcyVEa0058= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230903121243-b9d14a8b247f h1:Zv+YLNN6oLwCuRo7bG87FjygXCdBnXEgw0t6uOJJZCc= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230903121243-b9d14a8b247f/go.mod h1:eQJU+jDTcPVqOeHNheURqkMEMXDVNQFKKjcyVEa0058= github.com/jfrog/jfrog-client-go v1.28.1-0.20230831152946-6ed2ae1aa57f h1:S6l0o2sKFLRJ+QYVB5U/PJhrnwFSmKFFY7eHpRPRH8A= github.com/jfrog/jfrog-client-go v1.28.1-0.20230831152946-6ed2ae1aa57f/go.mod h1:uUnMrqHX7Xi+OCaZEE4b3BtsmGeOSCB7XqaEWVXEH/E= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= From f579380303806c001c95645bdaa50fcb66744d6c Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 3 Sep 2023 15:58:41 +0300 Subject: [PATCH 2/5] implement tests --- .../jas-test/sast/flask_webgoat/__init__.py | 51 ++ .../xray/jas-test/sast/flask_webgoat/ui.py | 25 + testdata/xray/jas-test/sast/result.sarif | 618 ++++++++++++++++++ testdata/xray/jas-test/sast/run.py | 15 + xray_test.go | 9 +- 5 files changed, 714 insertions(+), 4 deletions(-) create mode 100644 testdata/xray/jas-test/sast/flask_webgoat/__init__.py create mode 100644 testdata/xray/jas-test/sast/flask_webgoat/ui.py create mode 100644 testdata/xray/jas-test/sast/result.sarif create mode 100644 testdata/xray/jas-test/sast/run.py diff --git a/testdata/xray/jas-test/sast/flask_webgoat/__init__.py b/testdata/xray/jas-test/sast/flask_webgoat/__init__.py new file mode 100644 index 000000000..9e2f505a6 --- /dev/null +++ b/testdata/xray/jas-test/sast/flask_webgoat/__init__.py @@ -0,0 +1,51 @@ +import os +import sqlite3 +from pathlib import Path + +from flask import Flask, g + +DB_FILENAME = "database.db" + + +def query_db(query, args=(), one=False, commit=False): + with sqlite3.connect(DB_FILENAME) as conn: + # vulnerability: Sensitive Data Exposure + conn.set_trace_callback(print) + cur = conn.cursor().execute(query, args) + if commit: + conn.commit() + return cur.fetchone() if one else cur.fetchall() + + +def create_app(): + app = Flask(__name__) + app.secret_key = "aeZ1iwoh2ree2mo0Eereireong4baitixaixu5Ee" + + db_path = Path(DB_FILENAME) + if db_path.exists(): + db_path.unlink() + + conn = sqlite3.connect(DB_FILENAME) + create_table_query = """CREATE TABLE IF NOT EXISTS user + (id INTEGER PRIMARY KEY, username TEXT, password TEXT, access_level INTEGER)""" + conn.execute(create_table_query) + + insert_admin_query = """INSERT INTO user (id, username, password, access_level) + VALUES (1, 'admin', 'admin', 0)""" + conn.execute(insert_admin_query) + conn.commit() + conn.close() + + with app.app_context(): + from . import actions + from . import auth + from . import status + from . import ui + from . import users + + app.register_blueprint(actions.bp) + app.register_blueprint(auth.bp) + app.register_blueprint(status.bp) + app.register_blueprint(ui.bp) + app.register_blueprint(users.bp) + return app diff --git a/testdata/xray/jas-test/sast/flask_webgoat/ui.py b/testdata/xray/jas-test/sast/flask_webgoat/ui.py new file mode 100644 index 000000000..2b0bd0608 --- /dev/null +++ b/testdata/xray/jas-test/sast/flask_webgoat/ui.py @@ -0,0 +1,25 @@ +import sqlite3 + +from flask import Blueprint, request, render_template +from . import query_db + +bp = Blueprint("ui", __name__) + + +@bp.route("/search") +def search(): + query_param = request.args.get("query") + if query_param is None: + message = "please provide the query parameter" + return render_template("error.html", message=message) + + try: + query = "SELECT username, access_level FROM user WHERE username LIKE ?;" + results = query_db(query, (query_param,)) + # vulnerability: XSS + return render_template( + "search.html", results=results, num_results=len(results), query=query_param + ) + except sqlite3.Error as err: + message = "Error while executing query " + query_param + ": " + err + return render_template("error.html", message=message) diff --git a/testdata/xray/jas-test/sast/result.sarif b/testdata/xray/jas-test/sast/result.sarif new file mode 100644 index 000000000..839f34816 --- /dev/null +++ b/testdata/xray/jas-test/sast/result.sarif @@ -0,0 +1,618 @@ +{ + "runs": [ + { + "tool": { + "driver": { + "name": "USAF", + "rules": [ + { + "id": "python-flask-debug", + "defaultConfiguration": { + "parameters": { + "properties": { + "CWE": "1295" + } + } + }, + "fullDescription": { + "text": "\n### Overview\nDebug mode in a Flask app is a feature that allows the developer to see detailed\nerror messages and tracebacks when an error occurs. This can be useful for debugging\nand troubleshooting, but it can also create a security vulnerability if the app is\ndeployed in debug mode. In debug mode, Flask will display detailed error messages and\ntracebacks to the user, even if the error is caused by malicious input.\nThis can provide attackers with valuable information about the app's internal workings\nand vulnerabilities, making it easier for them to exploit those vulnerabilities.\n\n### Query operation\nIn this query we look Flask applications that set the `debug` argument to `True`\n\n### Vulnerable example\n```python\nfrom flask import Flask\n\napp = Flask(__name__)\n\n@app.route('/')\ndef hello():\n return 'Hello, World!'\n\nif __name__ == '__main__':\n app.run(debug=True)\n```\nIn this example, the Flask application is set to run in debug mode by passing\n`debug=True` as an argument to the `app.run()` function. This will make the application\nemit potentially sensitive information to the users.\n\n### Remediation\nWhen using `app.run`, omit the `debug` flag or set it to `False` -\n```diff\nif __name__ == '__main__':\n- app.run(debug=True)\n+ app.run()\n```\n", + "markdown": "\n### Overview\nDebug mode in a Flask app is a feature that allows the developer to see detailed\nerror messages and tracebacks when an error occurs. This can be useful for debugging\nand troubleshooting, but it can also create a security vulnerability if the app is\ndeployed in debug mode. In debug mode, Flask will display detailed error messages and\ntracebacks to the user, even if the error is caused by malicious input.\nThis can provide attackers with valuable information about the app's internal workings\nand vulnerabilities, making it easier for them to exploit those vulnerabilities.\n\n### Query operation\nIn this query we look Flask applications that set the `debug` argument to `True`\n\n### Vulnerable example\n```python\nfrom flask import Flask\n\napp = Flask(__name__)\n\n@app.route('/')\ndef hello():\n return 'Hello, World!'\n\nif __name__ == '__main__':\n app.run(debug=True)\n```\nIn this example, the Flask application is set to run in debug mode by passing\n`debug=True` as an argument to the `app.run()` function. This will make the application\nemit potentially sensitive information to the users.\n\n### Remediation\nWhen using `app.run`, omit the `debug` flag or set it to `False` -\n```diff\nif __name__ == '__main__':\n- app.run(debug=True)\n+ app.run()\n```\n" + }, + "shortDescription": { + "text": "Flask Running in Debug" + } + }, + { + "id": "python-stack-trace-exposure", + "defaultConfiguration": { + "parameters": { + "properties": { + "CWE": "209" + } + } + }, + "fullDescription": { + "text": "\n### Overview\nStack trace exposure is a type of security vulnerability that occurs when a program reveals\nsensitive information, such as the names and locations of internal files and variables,\nin error messages or other diagnostic output. This can happen when a program crashes or\nencounters an error, and the stack trace (a record of the program's call stack at the time\nof the error) is included in the output. Stack trace exposure can provide attackers with\nvaluable information about a program's internal workings and vulnerabilities, making it\neasier for them to exploit those vulnerabilities and gain unauthorized access\nto the system.\n\n### Query operation\nIn this query we look for any stack trace information flowing into the output.\n\n### Vulnerable example\n```python\nimport traceback\n\ndef my_function():\n try:\n # Some code that may raise an exception\n raise ValueError('Something went wrong')\n except ValueError as e:\n traceback.print_tb(e.__traceback__)\n\nmy_function()\n```\nIn this example, the `my_function()` function intentionally raises\na `ValueError` exception.\nThe `traceback.print_tb()` function is then used to print the stack trace\nwhen the exception is caught. The vulnerability lies in using `traceback.print_tb()`\nto output the stack trace directly to the console or any other output stream.\nIf this code were part of a web application or exposed through an API,\nthe stack trace would be exposed in the server logs or potentially returned\nas part of an error response to the client.\n\n### Remediation\nLog the exception to a logging framework or file, instead of outputting directly to the\nconsole-\n\n```python\ndef log_exception(exception):\n logging.exception('An exception occurred', exc_info=exception)\n```\n\n```diff\ndef my_function():\n try:\n # Some code that may raise an exception\n raise ValueError('Something went wrong')\n except ValueError as e:\n- traceback.print_tb(e.__traceback__)\n+ log_exception(e)\n```\n", + "markdown": "\n### Overview\nStack trace exposure is a type of security vulnerability that occurs when a program reveals\nsensitive information, such as the names and locations of internal files and variables,\nin error messages or other diagnostic output. This can happen when a program crashes or\nencounters an error, and the stack trace (a record of the program's call stack at the time\nof the error) is included in the output. Stack trace exposure can provide attackers with\nvaluable information about a program's internal workings and vulnerabilities, making it\neasier for them to exploit those vulnerabilities and gain unauthorized access\nto the system.\n\n### Query operation\nIn this query we look for any stack trace information flowing into the output.\n\n### Vulnerable example\n```python\nimport traceback\n\ndef my_function():\n try:\n # Some code that may raise an exception\n raise ValueError('Something went wrong')\n except ValueError as e:\n traceback.print_tb(e.__traceback__)\n\nmy_function()\n```\nIn this example, the `my_function()` function intentionally raises\na `ValueError` exception.\nThe `traceback.print_tb()` function is then used to print the stack trace\nwhen the exception is caught. The vulnerability lies in using `traceback.print_tb()`\nto output the stack trace directly to the console or any other output stream.\nIf this code were part of a web application or exposed through an API,\nthe stack trace would be exposed in the server logs or potentially returned\nas part of an error response to the client.\n\n### Remediation\nLog the exception to a logging framework or file, instead of outputting directly to the\nconsole-\n\n```python\ndef log_exception(exception):\n logging.exception('An exception occurred', exc_info=exception)\n```\n\n```diff\ndef my_function():\n try:\n # Some code that may raise an exception\n raise ValueError('Something went wrong')\n except ValueError as e:\n- traceback.print_tb(e.__traceback__)\n+ log_exception(e)\n```\n" + }, + "shortDescription": { + "text": "Stack Trace Exposure" + } + }, + { + "id": "python-xss", + "defaultConfiguration": { + "parameters": { + "properties": { + "CWE": "79" + } + } + }, + "fullDescription": { + "text": "\n### Overview\nXSS, or Cross-Site Scripting, is a type of vulnerability that allows an attacker to\ninject malicious code into a website or web application.\nThis can allow the attacker to steal sensitive information from users, such as their\ncookies or login credentials, or to perform unauthorized actions on their behalf.\n\n### Query operation\nIn the query we look for any user input that flows into\na potential output of the application.\n\n### Vulnerable example\nIn the following example, the Flask application takes a user-supplied parameter (`name`)\nfrom the query string and renders it directly into an HTML template using the\n`render_template_string` function. The issue is that\nthe user input is not properly sanitized or escaped, making it vulnerable to XSS attacks.\n```python\nfrom flask import Flask, request, render_template_string\n\napp = Flask(__name__)\n\n@app.route('/')\ndef index():\n name = request.args.get('name', 'Guest')\n message = f'Hello, {name}!'\n return render_template_string('

{}

'.format(message))\n\nif __name__ == '__main__':\napp.run()\n```\nAn attacker can exploit this vulnerability by injecting malicious JavaScript code into the\n`name` parameter. For instance, they could modify the URL to include the following payload:\n`http://localhost:5000/?name=`\n\n### Remediation\nWhen rendering templates, use parametrized variable assignments (which are automatically\nescaped) instead of direct string manipulation -\n```diff\n@app.route('/')\ndef index():\n name = request.args.get('name', 'Guest')\n message = f'Hello, {name}!'\n- return render_template_string('

{}

'.format(message))\n+ return render_template_string('

{{ message }}

', message=message)\n```\n", + "markdown": "\n### Overview\nXSS, or Cross-Site Scripting, is a type of vulnerability that allows an attacker to\ninject malicious code into a website or web application.\nThis can allow the attacker to steal sensitive information from users, such as their\ncookies or login credentials, or to perform unauthorized actions on their behalf.\n\n### Query operation\nIn the query we look for any user input that flows into\na potential output of the application.\n\n### Vulnerable example\nIn the following example, the Flask application takes a user-supplied parameter (`name`)\nfrom the query string and renders it directly into an HTML template using the\n`render_template_string` function. The issue is that\nthe user input is not properly sanitized or escaped, making it vulnerable to XSS attacks.\n```python\nfrom flask import Flask, request, render_template_string\n\napp = Flask(__name__)\n\n@app.route('/')\ndef index():\n name = request.args.get('name', 'Guest')\n message = f'Hello, {name}!'\n return render_template_string('

{}

'.format(message))\n\nif __name__ == '__main__':\napp.run()\n```\nAn attacker can exploit this vulnerability by injecting malicious JavaScript code into the\n`name` parameter. For instance, they could modify the URL to include the following payload:\n`http://localhost:5000/?name=`\n\n### Remediation\nWhen rendering templates, use parametrized variable assignments (which are automatically\nescaped) instead of direct string manipulation -\n```diff\n@app.route('/')\ndef index():\n name = request.args.get('name', 'Guest')\n message = f'Hello, {name}!'\n- return render_template_string('

{}

'.format(message))\n+ return render_template_string('

{{ message }}

', message=message)\n```\n" + }, + "shortDescription": { + "text": "XSS Vulnerability" + } + } + ] + } + }, + "invocations": [ + { + "executionSuccessful": true, + "arguments": [ + "/Users/assafa/.jfrog/dependencies/analyzerManager/zd_scanner/scanner", + "scan", + "/var/folders/xv/th4cksxn7jv9wjrdnn1h4tj00000gq/T/jfrog.cli.temp.-1693492973-1963413933/results.sarif" + ], + "workingDirectory": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast" + } + } + ], + "results": [ + { + "message": { + "text": "Stack Trace Exposure" + }, + "level": "note", + "locations": [ + { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.__init__.query_db" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/__init__.py" + }, + "region": { + "endColumn": 39, + "endLine": 13, + "snippet": { + "text": "conn.set_trace_callback(print)" + }, + "startColumn": 9, + "startLine": 13 + } + } + } + ], + "ruleId": "python-stack-trace-exposure" + }, + { + "message": { + "text": "Stack Trace Exposure" + }, + "level": "note", + "locations": [ + { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.__init__.query_db" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/__init__.py" + }, + "region": { + "endColumn": 39, + "endLine": 13, + "snippet": { + "text": "conn.set_trace_callback(print)" + }, + "startColumn": 9, + "startLine": 13 + } + } + } + ], + "ruleId": "python-stack-trace-exposure" + }, + { + "message": { + "text": "XSS Vulnerability" + }, + "codeFlows": [ + { + "threadFlows": [ + { + "locations": [ + { + "location": { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 31, + "endLine": 11, + "snippet": { + "text": "request.args" + }, + "startColumn": 19, + "startLine": 11 + } + } + } + }, + { + "location": { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 35, + "endLine": 11, + "snippet": { + "text": "request.args.get" + }, + "startColumn": 19, + "startLine": 11 + } + } + } + }, + { + "location": { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 44, + "endLine": 11, + "snippet": { + "text": "request.args.get(\"query\")" + }, + "startColumn": 19, + "startLine": 11 + } + } + } + }, + { + "location": { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 16, + "endLine": 11, + "snippet": { + "text": "query_param" + }, + "startColumn": 5, + "startLine": 11 + } + } + } + }, + { + "location": { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 10, + "endLine": 22, + "snippet": { + "text": "render_template(\n \"search.html\", results=results, num_results=len(results), query=query_param\n )" + }, + "startColumn": 16, + "startLine": 20 + } + } + } + }, + { + "location": { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 10, + "endLine": 22, + "snippet": { + "text": "return render_template(\n \"search.html\", results=results, num_results=len(results), query=query_param\n )" + }, + "startColumn": 9, + "startLine": 20 + } + } + } + } + ] + } + ] + } + ], + "level": "error", + "locations": [ + { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 10, + "endLine": 22, + "snippet": { + "text": "return render_template(\n \"search.html\", results=results, num_results=len(results), query=query_param\n )" + }, + "startColumn": 9, + "startLine": 20 + } + } + } + ], + "ruleId": "python-xss" + }, + { + "message": { + "text": "XSS Vulnerability" + }, + "codeFlows": [ + { + "threadFlows": [ + { + "locations": [ + { + "location": { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 31, + "endLine": 11, + "snippet": { + "text": "request.args" + }, + "startColumn": 19, + "startLine": 11 + } + } + } + }, + { + "location": { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 35, + "endLine": 11, + "snippet": { + "text": "request.args.get" + }, + "startColumn": 19, + "startLine": 11 + } + } + } + }, + { + "location": { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 44, + "endLine": 11, + "snippet": { + "text": "request.args.get(\"query\")" + }, + "startColumn": 19, + "startLine": 11 + } + } + } + }, + { + "location": { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 16, + "endLine": 11, + "snippet": { + "text": "query_param" + }, + "startColumn": 5, + "startLine": 11 + } + } + } + }, + { + "location": { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 63, + "endLine": 24, + "snippet": { + "text": "\"Error while executing query \" + query_param" + }, + "startColumn": 19, + "startLine": 24 + } + } + } + }, + { + "location": { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 70, + "endLine": 24, + "snippet": { + "text": "\"Error while executing query \" + query_param + \": \"" + }, + "startColumn": 19, + "startLine": 24 + } + } + } + }, + { + "location": { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 76, + "endLine": 24, + "snippet": { + "text": "\"Error while executing query \" + query_param + \": \" + err" + }, + "startColumn": 19, + "startLine": 24 + } + } + } + }, + { + "location": { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 16, + "endLine": 24, + "snippet": { + "text": "message" + }, + "startColumn": 9, + "startLine": 24 + } + } + } + }, + { + "location": { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 62, + "endLine": 25, + "snippet": { + "text": "render_template(\"error.html\", message=message)" + }, + "startColumn": 16, + "startLine": 25 + } + } + } + }, + { + "location": { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 62, + "endLine": 25, + "snippet": { + "text": "return render_template(\"error.html\", message=message)" + }, + "startColumn": 9, + "startLine": 25 + } + } + } + } + ] + } + ] + } + ], + "level": "error", + "locations": [ + { + "logicalLocations": [ + { + "fullyQualifiedName": "flask_webgoat.ui.search" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/flask_webgoat/ui.py" + }, + "region": { + "endColumn": 62, + "endLine": 25, + "snippet": { + "text": "return render_template(\"error.html\", message=message)" + }, + "startColumn": 9, + "startLine": 25 + } + } + } + ], + "ruleId": "python-xss" + }, + { + "message": { + "text": "Flask Running in Debug" + }, + "locations": [ + { + "logicalLocations": [ + { + "fullyQualifiedName": "run" + } + ], + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/assafa/Documents/code/cli-projects/jfrog-cli/testdata/xray/jas/sast/run.py" + }, + "region": { + "endColumn": 24, + "endLine": 15, + "snippet": { + "text": "app.run(debug=True)" + }, + "startColumn": 5, + "startLine": 15 + } + } + } + ], + "ruleId": "python-flask-debug" + } + ] + } + ], + "version": "2.1.0", + "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json" +} \ No newline at end of file diff --git a/testdata/xray/jas-test/sast/run.py b/testdata/xray/jas-test/sast/run.py new file mode 100644 index 000000000..8cacc71d4 --- /dev/null +++ b/testdata/xray/jas-test/sast/run.py @@ -0,0 +1,15 @@ +from flask_webgoat import create_app + +app = create_app() + +@app.after_request +def add_csp_headers(response): + # vulnerability: Broken Access Control + response.headers['Access-Control-Allow-Origin'] = '*' + # vulnerability: Security Misconfiguration + response.headers['Content-Security-Policy'] = "script-src 'self' 'unsafe-inline'" + return response + +if __name__ == '__main__': + # vulnerability: Security Misconfiguration + app.run(debug=True) diff --git a/xray_test.go b/xray_test.go index fd3ff3150..d691c5673 100644 --- a/xray_test.go +++ b/xray_test.go @@ -335,7 +335,7 @@ func TestXrayAuditMultiProjects(t *testing.T) { defer cleanTestsHomeEnv() output := xrayCli.WithoutCredentials().RunCliCmdWithOutput(t, "audit", "--format="+string(utils.SimpleJson), workingDirsFlag) verifySimpleJsonScanResults(t, output, 35, 0) - verifySimpleJsonJasResults(t, output, 9, 7, 0, 1) + verifySimpleJsonJasResults(t, output, 4, 9, 7, 0, 1) } func TestXrayAuditPipJson(t *testing.T) { @@ -669,13 +669,13 @@ func TestXrayOfflineDBSyncV3(t *testing.T) { func TestXrayAuditJasSimpleJson(t *testing.T) { output := testXrayAuditJas(t, string(utils.SimpleJson), "jas-test") - verifySimpleJsonJasResults(t, output, 9, 7, 2, 1) + verifySimpleJsonJasResults(t, output, 4, 9, 7, 2, 1) } func TestXrayAuditJasNoViolationsSimpleJson(t *testing.T) { output := testXrayAuditJas(t, string(utils.SimpleJson), "npm") verifySimpleJsonScanResults(t, output, 2, 0) - verifySimpleJsonJasResults(t, output, 0, 0, 0, 1) + verifySimpleJsonJasResults(t, output, 0, 0, 0, 0, 1) } func testXrayAuditJas(t *testing.T, format string, project string) string { @@ -695,10 +695,11 @@ func testXrayAuditJas(t *testing.T, format string, project string) string { return xrayCli.WithoutCredentials().RunCliCmdWithOutput(t, "audit", "--format="+format) } -func verifySimpleJsonJasResults(t *testing.T, content string, minIacViolations, minSecrets, minApplicable, minNotApplicable int) { +func verifySimpleJsonJasResults(t *testing.T, content string, minSastViolations, minIacViolations, minSecrets, minApplicable, minNotApplicable int) { var results formats.SimpleJsonResults err := json.Unmarshal([]byte(content), &results) if assert.NoError(t, err) { + assert.GreaterOrEqual(t, len(results.Sast), minSastViolations, "Found less sast then expected") assert.GreaterOrEqual(t, len(results.Secrets), minSecrets, "Found less secrets then expected") assert.GreaterOrEqual(t, len(results.Iacs), minIacViolations, "Found less IaC then expected") var applicableResults, notApplicableResults int From d6e999ca370edc0fe80450ade768302134a7c215 Mon Sep 17 00:00:00 2001 From: attiasas Date: Wed, 20 Sep 2023 10:42:57 +0300 Subject: [PATCH 3/5] fix tests --- testdata/xray/jas-test/requirements.txt | 3 ++- xray_test.go | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/testdata/xray/jas-test/requirements.txt b/testdata/xray/jas-test/requirements.txt index ddff94966..79bfd143b 100644 --- a/testdata/xray/jas-test/requirements.txt +++ b/testdata/xray/jas-test/requirements.txt @@ -1 +1,2 @@ -PyYAML==5.2 \ No newline at end of file +PyYAML==5.2 +Werkzeug==1.0.1 \ No newline at end of file diff --git a/xray_test.go b/xray_test.go index eeb73c742..97fa88068 100644 --- a/xray_test.go +++ b/xray_test.go @@ -416,7 +416,7 @@ func TestXrayAuditMultiProjects(t *testing.T) { defer cleanTestsHomeEnv() output := xrayCli.WithoutCredentials().RunCliCmdWithOutput(t, "audit", "--format="+string(utils.SimpleJson), workingDirsFlag) verifySimpleJsonScanResults(t, output, 35, 0) - verifySimpleJsonJasResults(t, output, 4, 9, 7, 0, 1) + verifySimpleJsonJasResults(t, output, 3, 9, 7, 3, 1) } func TestXrayAuditPipJson(t *testing.T) { @@ -750,7 +750,7 @@ func TestXrayOfflineDBSyncV3(t *testing.T) { func TestXrayAuditJasSimpleJson(t *testing.T) { output := testXrayAuditJas(t, string(utils.SimpleJson), "jas-test") - verifySimpleJsonJasResults(t, output, 4, 9, 7, 2, 1) + verifySimpleJsonJasResults(t, output, 3, 9, 7, 3, 1) } func TestXrayAuditJasNoViolationsSimpleJson(t *testing.T) { From 3879cb7cd98ba4655e0ae070b5326c93da715c34 Mon Sep 17 00:00:00 2001 From: attiasas Date: Wed, 20 Sep 2023 16:34:29 +0300 Subject: [PATCH 4/5] action not on release --- .github/workflows/xrayTests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/xrayTests.yml b/.github/workflows/xrayTests.yml index a8f2df07d..c5bd099a6 100644 --- a/.github/workflows/xrayTests.yml +++ b/.github/workflows/xrayTests.yml @@ -24,7 +24,7 @@ jobs: env: GRADLE_OPTS: -Dorg.gradle.daemon=false # Run Xray tests with latest Analyzer - JFROG_CLI_ANALYZER_MANAGER_VERSION: "[RELEASE]" + # JFROG_CLI_ANALYZER_MANAGER_VERSION: "[RELEASE]" steps: - name: Install Go uses: actions/setup-go@v3 From 923f1f3ea0983883db7992b31e97edf784b38e4f Mon Sep 17 00:00:00 2001 From: attiasas Date: Thu, 21 Sep 2023 19:13:48 +0300 Subject: [PATCH 5/5] review changes --- .github/workflows/xrayTests.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/xrayTests.yml b/.github/workflows/xrayTests.yml index c5bd099a6..afb659a97 100644 --- a/.github/workflows/xrayTests.yml +++ b/.github/workflows/xrayTests.yml @@ -23,8 +23,6 @@ jobs: runs-on: ${{ matrix.os }}-latest env: GRADLE_OPTS: -Dorg.gradle.daemon=false - # Run Xray tests with latest Analyzer - # JFROG_CLI_ANALYZER_MANAGER_VERSION: "[RELEASE]" steps: - name: Install Go uses: actions/setup-go@v3