ALM used
GitLab
CI system used
GitLab CI
Scanner command used when applicable (private details masked)
script:
- git fetch origin master --depth 10
- if [[ "$CREATE_RC" =~ 'TRUE' ]]; then
RELEASE_VERSION=$(date --date="$(echo $CI_PIPELINE_CREATED_AT | tr -d 'TZ')" "+%Y%m%d%H%M%S");
RELEASE_CANDIDATE_TAG="rc-$RELEASE_VERSION";
sonar-scanner
-Dsonar.projectVersion=$RELEASE_CANDIDATE_TAG
-Dsonar.organization=Hidden
-Dsonar.projectKey=$SONAR_PROJECT_KEY
-Dsonar.sources=$SONAR_SOURCE
-Dsonar.login=$SONAR_TOKEN
-Dsonar.python.coverage.reportPaths=coverage.xml
-Dsonar.python.xunit.reportPath=report.xml
-Dsonar.python.bandit.reportPaths=bandit.txt
-Dsonar.python.flake8.reportPaths=flake8.txt
-Dsonar.python.version=3
-Dsonar.javascript.lcov.reportPaths=coverage/lcov.info
-Dsonar.typescript.tsconfigPaths=tsconfig.json
-Dsonar.host.url=https://sonarcloud.io;
else
sonar-scanner
-Dsonar.organization=Hidden
-Dsonar.projectKey=$SONAR_PROJECT_KEY
-Dsonar.sources=$SONAR_SOURCE
-Dsonar.login=$SONAR_TOKEN
-Dsonar.host.url=https://sonarcloud.io
-Dsonar.python.coverage.reportPaths=coverage.xml
-Dsonar.python.xunit.reportPath=report.xml
-Dsonar.python.bandit.reportPaths=bandit.txt
-Dsonar.python.flake8.reportPaths=flake8.txt
-Dsonar.python.version=3
-Dsonar.javascript.lcov.reportPaths=coverage/lcov.info
-Dsonar.typescript.tsconfigPaths=tsconfig.json
-Dsonar.qualitygate.wait=true;
fi
Languages of the repository
Python
Only if the SonarCloud project is public, the URL
Private
And if you need help with pull request decoration, then the URL to the PR too
N/A
Error observed
We wanted to test that the vulnerability rules in our quality profile were triggered as expected when adding a vulnerable piece of code into the repo.
The error we have observed is vulnerabilities from the Security SonarAnalyzer repo are not being picked up by sonarcloud, whereas vulnerabilties from SonarQube Python repo are.
To prove this, we recreated the non-compliant code examples given in the SonarCloud rule definitions below.
SonarQube Python
- python:S2115 - A secure password should be used when connecting to a database
- python:S2053 - Hashes should include an unpredictable salt
- python:S4830 - Server certificates should be verified during SSL/TLS connections
- python:S5527 - Server hostnames should be verified during SSL/TLS connections
Security SonarAnalyzer
- pythonsecurity:S5147 - NoSQL operations should not be vulnerable to injection attacks
- pythonsecurity:S2076 - OS commands should not be vulnerable to command injection attacks
- pythonsecurity:S3649 - Database queries should not be vulnerable to injection attacks
- pythonsecurity:S5334 - Dynamic code execution should not be vulnerable to injection attacks
Steps to reproduce
- Create a sonarcloud project
- Create a python repository with the following code snippet
import os
from requests import request
from flask import Flask
from hashlib import pbkdf2_hmac
import ssl
import xml.etree.ElementTree as etree
import sqlite3
import boto3
# python:S4502 - FOUND
app = Flask(__name__)
def configure_app(app):
# python:S2115 - FOUND
app.config['SQLALCHEMY_DATABASE_URI'] = "postgresql://user:@domain.com"
def ping():
# pythonsecurity:S2076 - NOT FOUND
cmd = "ping -c 1 %s" % request.args.get("host", "www.google.com")
status = os.system(cmd)
return str(status == 0)
@app.route('/login')
def login():
# python:S2053 - FOUND
output_pbkdf2 = pbkdf2_hmac('sha256', '1232321312', b'D8VxSmTZt2E2YV454mkqAY5e', 100000)
# python:S4830/python:S5527 - FOUND
ctx = ssl._create_unverified_context()
ctx.check_hostname = False
parser = etree.XMLParser()
tree1 = etree.parse('ressources/xxe.xml', parser)
root1 = tree1.getroot()
# pythonsecurity:S5147 - NOT FOUND
dynamodb = boto3.client('dynamodb')
username = request.args["username"]
password = request.args["password"]
dynamodb.scan(
FilterExpression="username = " + username + " and password = " + password,
TableName="users",
ProjectionExpression="username"
)
# pythonsecurity:S3649 - NOT FOUND
user = request.args["user"]
sql = """SELECT user FROM users WHERE user = \'%s\'"""
conn = sqlite3.connect('example')
conn.cursor().execute(sql % (user))
# pythonsecurity:S5334 - NOT FOUND
operation = request.args.get("operation")
eval(f"product_{operation}()")
ping()
if __name__ == "__main__":
app.run(debug=True)
As you can see rules pythonsecurity:S5147, pythonsecurity:S2076, pythonsecurity:S3649 and pythonsecurity:S5334 were all included we should also note that it includes the vulnerabilities from the SonarQube repo e.g. ‘python:S2115’ as well.
Four vulnerabilities (and 1 hotspot which was related to 1 of the vulnerabilities) were discovered. All 4 of these vulnerabilities were from the SonarQube Python repo - none from the Security SonarAnalyzer repo were found.
Our first thought was we must have a configuration error, however after exploring all the configuration and settings for SonarCloud (including creating a freetrial of an enterprise account to see the settings available at the organisation-level) we couldn’t find anything pertaining to the enabling/disabling of certain vulnerability repositories.
Potential workaround
No known workarounds.
Do not share screenshots of logs – share the text itself (bonus points for being well-formatted)!