Skip to content

Commit f394e5a

Browse files
authored
New codemod: Sonar pythonsecurity:S2076 (#830)
New codemod for Sonar pythonsecurity:S2076
1 parent 42832e2 commit f394e5a

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

src/core_codemods/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
from .sonar.sonar_remove_assertion_in_pytest_raises import (
8888
SonarRemoveAssertionInPytestRaises,
8989
)
90+
from .sonar.sonar_sandbox_process_creation import SonarSandboxProcessCreation
9091
from .sonar.sonar_secure_random import SonarSecureRandom
9192
from .sonar.sonar_sql_parameterization import SonarSQLParameterization
9293
from .sonar.sonar_tempfile_mktemp import SonarTempfileMktemp
@@ -201,6 +202,7 @@
201202
SonarDisableGraphQLIntrospection,
202203
SonarInvertedBooleanCheck,
203204
SonarTimezoneAwareDatetime,
205+
SonarSandboxProcessCreation,
204206
],
205207
)
206208

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from core_codemods.process_creation_sandbox import ProcessSandbox
2+
from core_codemods.sonar.api import SonarCodemod
3+
4+
SonarSandboxProcessCreation = SonarCodemod.from_core_codemod(
5+
name="sandbox-process-creation",
6+
other=ProcessSandbox(),
7+
rule_id="pythonsecurity:S2076",
8+
rule_name="OS commands should not be vulnerable to command injection attacks",
9+
)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import json
2+
3+
import mock
4+
5+
from codemodder.codemods.test import BaseSASTCodemodTest
6+
from codemodder.dependency import Security
7+
from core_codemods.sonar.sonar_sandbox_process_creation import (
8+
SonarSandboxProcessCreation,
9+
)
10+
11+
12+
class TestSonarSandboxProcessCreation(BaseSASTCodemodTest):
13+
codemod = SonarSandboxProcessCreation
14+
tool = "sonar"
15+
16+
def test_name(self):
17+
assert self.codemod.name == "sandbox-process-creation"
18+
19+
@mock.patch("codemodder.codemods.api.FileContext.add_dependency")
20+
def test_simple(self, adds_dependency, tmpdir):
21+
input_code = """
22+
import os
23+
from flask import render_template, request
24+
25+
@app.route('/vuln', methods=['GET', 'POST'])
26+
def vuln():
27+
output = ""
28+
if request.method == 'POST':
29+
command = request.form.get('command')
30+
output = os.popen(command).read()
31+
return render_template('vuln.html', output=output)
32+
""".lstrip(
33+
"\n"
34+
)
35+
expected = """
36+
import os
37+
from flask import render_template, request
38+
from security import safe_command
39+
40+
@app.route('/vuln', methods=['GET', 'POST'])
41+
def vuln():
42+
output = ""
43+
if request.method == 'POST':
44+
command = request.form.get('command')
45+
output = safe_command.run(os.popen, command).read()
46+
return render_template('vuln.html', output=output)
47+
""".lstrip(
48+
"\n"
49+
)
50+
issues = {
51+
"issues": [
52+
{
53+
"rule": "pythonsecurity:S2076",
54+
"status": "OPEN",
55+
"component": "code.py",
56+
"textRange": {
57+
"startLine": 9,
58+
"endLine": 9,
59+
"startOffset": 17,
60+
"endOffset": 34,
61+
},
62+
}
63+
]
64+
}
65+
self.run_and_assert(tmpdir, input_code, expected, results=json.dumps(issues))
66+
adds_dependency.assert_called_once_with(Security)

0 commit comments

Comments
 (0)