Skip to content

Commit d5c7d1b

Browse files
ZiadMareysonartech
authored andcommitted
SONARPY-4757 S5332: Do not raise on a bare clear-text scheme literal ("http://", "ftp://")
GitOrigin-RevId: a6d2cf1060a447f63b807e100f6ba170bd96701d
1 parent 1007e82 commit d5c7d1b

2 files changed

Lines changed: 11 additions & 8 deletions

File tree

‎python-checks/src/main/java/org/sonar/python/checks/hotspots/ClearTextProtocolsCheck.java‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public void initialize(Context originalContext) {
8080
context.registerSyntaxNodeConsumer(Tree.Kind.STRING_ELEMENT, ctx -> {
8181
Tree node = ctx.syntaxNode();
8282
String value = Expressions.unescape((StringElement) node);
83-
unsafeProtocol(value)
83+
unsafeProtocol(value, node)
8484
.filter(protocol -> !isProtocolIdentificationArgument(node, ctx))
8585
// cleanup slashes
8686
.map(protocol -> protocol.substring(0, protocol.length() - 3))
@@ -273,14 +273,17 @@ private static void handleAssignmentStatement(AssignmentStatement assignmentStat
273273
}
274274
}
275275

276-
private static Optional<String> unsafeProtocol(String literalValue) {
276+
private static Optional<String> unsafeProtocol(String literalValue, Tree stringElement) {
277277
return CLEARTEXT_PROTOCOLS.stream()
278278
.filter(literalValue::startsWith)
279279
.filter(p -> {
280280
String rest = literalValue.substring(p.length());
281281
if (rest.isEmpty()) {
282-
// Bare scheme string (e.g. "http://") — always flag
283-
return true;
282+
// Keep direct replace arguments reportable; the identification filter exempts the old value.
283+
return stringElement.parent().parent() instanceof RegularArgument argument
284+
&& TreeUtils.firstAncestorOfKind(argument, Tree.Kind.CALL_EXPR) instanceof CallExpression call
285+
&& call.callee() instanceof QualifiedExpression callee
286+
&& "replace".equals(callee.name().name());
284287
}
285288
char first = rest.charAt(0);
286289
if (first == '/' || first == '?' || first == '#') {

‎python-checks/src/test/resources/checks/hotspots/clearTextProtocols.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
import urllib.request
88

99
def clear_text_protocol():
10-
url = "http://" # Noncompliant {{Using HTTP protocol is insecure. Use HTTPS instead.}}
11-
# ^^^^^^^^^
10+
url = "http://" # Compliant
1211
url = "http://exemple.com" # Noncompliant
1312
url = "http://0001::1" # Noncompliant
1413
url = "http://dead:beef::1" # Noncompliant
@@ -18,9 +17,9 @@ def clear_text_protocol():
1817
url = "http://subdomain.exemple.com" # Noncompliant
1918
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2019

21-
url = "ftp://" # Noncompliant {{Using FTP protocol is insecure. Use SFTP, SCP or FTPS instead.}}
20+
url = "ftp://" # Compliant
2221
url = "ftp://anonymous@exemple.com" # Noncompliant
23-
url = "telnet://" # Noncompliant
22+
url = "telnet://" # Compliant
2423
url = "telnet://anonymous@exemple.com" # Noncompliant {{Using Telnet protocol is insecure. Use SSH instead.}}
2524

2625
# Argument default value
@@ -178,6 +177,7 @@ def clear_text_protocol_used_as_prefix_grouped(url: str):
178177

179178
def clear_text_protocol_used_outside_startswith_prefix(url: str):
180179
check_protocol("http://insecure.com") # Noncompliant
180+
check_protocol("http://") # Compliant
181181
url.endswith("http://insecure.com") # Noncompliant
182182
url.startswith(prefix="http://insecure.com") # Noncompliant
183183
str.startswith("http://insecure.com") # Noncompliant

0 commit comments

Comments
 (0)