fix(sonarqube): mdDesc fallback#14770
Conversation
|
This pull request introduces code that generates and returns HTML from markdown (via markdown.markdown(..., extensions=["extra"])) without sanitization, and returns htmlDesc verbatim from get_rule_details, creating a high-severity potential Cross-Site Scripting (XSS) risk if user-controlled content reaches a rendering sink. The finding recommends sanitizing or escaping rendered HTML before use to prevent XSS.
🟠 Potential Cross-Site Scripting in
|
| Vulnerability | Potential Cross-Site Scripting |
|---|---|
| Description | The code calls markdown.markdown(md_desc, extensions=["extra"]) and also returns htmlDesc verbatim from get_rule_details; these can produce/contain raw HTML that is later parsed and used without any sanitization or escaping. If user-controlled markdown/html reaches a rendering sink, this can enable XSS. |
django-DefectDojo/dojo/tools/api_sonarqube/importer.py
Lines 371 to 374 in 981a86b
Comment to provide feedback on these findings.
Report false positive: @dryrunsecurity fp [FINDING ID] [FEEDBACK]
Report low-impact: @dryrunsecurity nit [FINDING ID] [FEEDBACK]
Example: @dryrunsecurity fp drs_90eda195 This code is not user-facing
All finding details can be found in the DryRun Security Dashboard.
Description
This PR fixes SonarQube API imports when a rule no longer returns
htmlDescbut does returnmdDesc, which is the behavior reported in issue#12565.Before this change, the regular SonarQube importer only populated
description,cwe, and rule references whenhtmlDescwas present. WhenhtmlDescwas missing, the importer fell back to an empty description andNonefor CWE, even when SonarQube had provided a Markdown rule description inmdDesc.I fixed this by making the importer resolve rule content from either
htmlDescormdDesc, converting Markdown to HTML when needed, and then reusing the existing description/CWE/reference extraction flow.The importer change is:
The new helper logic and the small hardening around description/reference parsing are:
I also added a regression fixture that represents a rule with only
mdDesc:{ "key": "typescript:S1854", "repo": "typescript", "name": "Dead stores should be removed", "createdAt": "2018-01-17T10:11:21-0500", "mdDesc": "A dead store happens when a local variable is assigned a value that is not read by any subsequent instruction. Calculating or retrieving a value only to then overwrite it or throw it away, could indicate a serious error in the code. Even if it's not an error, it is at best a waste of resources. Therefore all calculated values should be used.\n\n## Noncompliant Code Example\n\ni = a + b; // Noncompliant; calculation result not used before value is overwritten\ni = compute();\n\n## Compliant Solution\n\ni = a + b;\ni += compute();\n\n## Exceptions\n\nThis rule ignores initializations to -1, 0, 1, `null`, `true`, `false`, `\"\"`, `[]` and `{}`.\n\n## See\n\n- [MITRE, CWE-563](http://cwe.mitre.org/data/definitions/563.html) - Assignment to Variable without Use ('Unused Variable')\n- [CERT, MSC13-C.](https://www.securecoding.cert.org/confluence/x/QYA5) - Detect and remove unused values\n- [CERT, MSC56-J.](https://www.securecoding.cert.org/confluence/x/uQCSBg) - Detect and remove superfluous code and values\n", "severity": "MAJOR", "status": "READY", "isTemplate": false, "tags": [], "sysTags": [ "cert", "cwe", "unused" ], "lang": "ts", "langName": "TypeScript", "params": [], "defaultDebtRemFnType": "CONSTANT_ISSUE", "defaultDebtRemFnOffset": "15min", "debtOverloaded": false, "debtRemFnType": "CONSTANT_ISSUE", "debtRemFnOffset": "15min", "defaultRemFnType": "CONSTANT_ISSUE", "defaultRemFnBaseEffort": "15min", "remFnType": "CONSTANT_ISSUE", "remFnBaseEffort": "15min", "remFnOverloaded": false, "scope": "MAIN", "isExternal": false, "type": "CODE_SMELL" }The regression test I added is:
Test results
I tested this change with the SonarQube importer unit tests in the project’s Docker/Postgres-backed test setup.
Focused regression test:
docker compose -f docker-compose.yml -f docker-compose.override.unit_tests.yml run --rm --no-deps --entrypoint bash uwsgi -lc "export HOME=/tmp PYTHONUSERBASE=/tmp/pyuser PATH=/tmp/pyuser/bin:/usr/local/bin:/usr/bin:/bin; python3 -m pip install --user -r requirements-dev.txt && python3 manage.py test unittests.tools.test_api_sonarqube_importer.TestSonarqubeImporterMarkdownRuleDescription -v2 --keepdb"Full SonarQube importer test file:
docker compose -f docker-compose.yml -f docker-compose.override.unit_tests.yml run --rm --no-deps --entrypoint bash uwsgi -lc "export HOME=/tmp PYTHONUSERBASE=/tmp/pyuser PATH=/tmp/pyuser/bin:/usr/local/bin:/usr/bin:/bin; python3 -m pip install --user -r requirements-dev.txt >/tmp/requirements-dev-install.log && python3 manage.py test unittests.tools.test_api_sonarqube_importer -v1 --keepdb"Results:
unittests.tools.test_api_sonarqube_importersuite passed with 17 tests.Checklist
This checklist is for your information.
dev.dev.bugfixbranch.