From fc8c5e645a65c4bd95a849ff353fbf5e25ad9830 Mon Sep 17 00:00:00 2001
From: Assaf Attias <49212512+attiasas@users.noreply.github.com>
Date: Thu, 21 Sep 2023 19:22:56 +0300
Subject: [PATCH] Add Sast tests (#2180)
---
.github/workflows/xrayTests.yml | 2 -
testdata/xray/jas-test/requirements.txt | 3 +-
.../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 +-
7 files changed, 716 insertions(+), 7 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/.github/workflows/xrayTests.yml b/.github/workflows/xrayTests.yml
index a8f2df07d..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
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/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 8137e826f..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, 9, 7, 0, 1)
+ verifySimpleJsonJasResults(t, output, 3, 9, 7, 3, 1)
}
func TestXrayAuditPipJson(t *testing.T) {
@@ -750,13 +750,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, 3, 9, 7, 3, 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 {
@@ -776,10 +776,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