Skip to content

Commit 4feaecc

Browse files
guillaume-dequennesonartech
authored andcommitted
NO-JIRA Update rules metadata (#1054)
GitOrigin-RevId: 29bb749ca8ba868066f5ba113eb43307ee1547ff
1 parent 8111b33 commit 4feaecc

File tree

8 files changed

+113
-57
lines changed

8 files changed

+113
-57
lines changed

python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2092.html

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,29 @@
11
<p>When a cookie is protected with the <code>secure</code> attribute set to <em>true</em> it will not be send by the browser over an unencrypted HTTP
22
request and thus cannot be observed by an unauthorized person during a man-in-the-middle attack.</p>
3-
<h2>Ask Yourself Whether</h2>
4-
<ul>
5-
<li>the cookie is for instance a <em>session-cookie</em> not designed to be sent over non-HTTPS communication.</li>
6-
<li>it’s not sure that the website contains <a href="https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content">mixed content</a> or not
7-
(ie HTTPS everywhere or not)</li>
8-
</ul>
9-
<p>There is a risk if you answered yes to any of those questions.</p>
10-
<h2>Recommended Secure Coding Practices</h2>
11-
<ul>
12-
<li>It is recommended to use <code>HTTPs</code> everywhere so setting the <code>secure</code> flag to <em>true</em> should be the default behaviour
13-
when creating cookies.</li>
14-
<li>Set the <code>secure</code> flag to <em>true</em> for session-cookies.</li>
15-
</ul>
16-
<h2>Sensitive Code Example</h2>
17-
<p>Using Flask:</p>
18-
<pre data-diff-id="11" data-diff-type="noncompliant">
3+
<h2>Why is this an issue?</h2>
4+
<p>When a cookie is created without the <code>secure</code> attribute set to <code>true</code>, browsers will transmit it over unencrypted HTTP
5+
connections as well as HTTPS. An attacker who can observe or intercept network traffic—for example on a public Wi-Fi network—can read the cookie value
6+
in cleartext.</p>
7+
<h3>What is the potential impact?</h3>
8+
<h4>Session hijacking</h4>
9+
<p>If a session cookie is transmitted over an unencrypted HTTP connection, an attacker who can intercept the traffic can steal it. With a valid
10+
session cookie, the attacker can impersonate the victim and gain full access to their account without knowing their password. Even on sites that
11+
primarily use HTTPS, a single HTTP request containing the session cookie is enough to expose it.</p>
12+
<h2>How to fix it in Flask</h2>
13+
<p>Pass <code>secure=True</code> to <code>set_cookie</code> to prevent the cookie from being transmitted over unencrypted HTTP connections.</p>
14+
<h3>Code examples</h3>
15+
<h4>Noncompliant code example</h4>
16+
<pre data-diff-id="1" data-diff-type="noncompliant">
1917
from flask import Response
2018

2119
@app.route('/')
2220
def index():
2321
response = Response()
24-
response.set_cookie('key', 'value') # Sensitive
22+
response.set_cookie('key', 'value') # Noncompliant
2523
return response
2624
</pre>
27-
<p>Using FastAPI:</p>
28-
<pre data-diff-id="21" data-diff-type="noncompliant">
29-
from fastapi import FastAPI, Response
30-
31-
app = FastAPI()
32-
33-
@app.get('/')
34-
async def index(response: Response):
35-
response.set_cookie('key', 'value') # Sensitive
36-
return {"message": "Hello world!"}
37-
</pre>
38-
<h2>Compliant Solution</h2>
39-
<p>Using Flask:</p>
40-
<pre data-diff-id="11" data-diff-type="compliant">
25+
<h4>Compliant solution</h4>
26+
<pre data-diff-id="1" data-diff-type="compliant">
4127
from flask import Response
4228

4329
@app.route('/')
@@ -46,8 +32,22 @@ <h2>Compliant Solution</h2>
4632
response.set_cookie('key', 'value', secure=True)
4733
return response
4834
</pre>
49-
<p>Using FastAPI:</p>
50-
<pre data-diff-id="21" data-diff-type="compliant">
35+
<h2>How to fix it in FastAPI</h2>
36+
<p>Pass <code>secure=True</code> to <code>set_cookie</code> to prevent the cookie from being transmitted over unencrypted HTTP connections.</p>
37+
<h3>Code examples</h3>
38+
<h4>Noncompliant code example</h4>
39+
<pre data-diff-id="2" data-diff-type="noncompliant">
40+
from fastapi import FastAPI, Response
41+
42+
app = FastAPI()
43+
44+
@app.get('/')
45+
async def index(response: Response):
46+
response.set_cookie('key', 'value') # Noncompliant
47+
return {"message": "Hello world!"}
48+
</pre>
49+
<h4>Compliant solution</h4>
50+
<pre data-diff-id="2" data-diff-type="compliant">
5151
from fastapi import FastAPI, Response
5252

5353
app = FastAPI()
@@ -57,7 +57,8 @@ <h2>Compliant Solution</h2>
5757
response.set_cookie('key', 'value', secure=True)
5858
return {"message": "Hello world!"}
5959
</pre>
60-
<h2>See</h2>
60+
<h2>Resources</h2>
61+
<h3>Standards</h3>
6162
<ul>
6263
<li>OWASP - <a href="https://owasp.org/Top10/A04_2021-Insecure_Design/">Top 10 2021 Category A4 - Insecure Design</a></li>
6364
<li>OWASP - <a href="https://owasp.org/Top10/A05_2021-Security_Misconfiguration/">Top 10 2021 Category A5 - Security Misconfiguration</a></li>

python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2092.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
2-
"title": "Creating cookies without the \"secure\" flag is security-sensitive",
3-
"type": "SECURITY_HOTSPOT",
2+
"title": "Cookies should have the \"secure\" flag",
3+
"type": "VULNERABILITY",
4+
"quickfix": "unknown",
45
"code": {
56
"impacts": {
67
"SECURITY": "LOW"

python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S8494.html

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,33 @@
1-
<p>This rule raises an issue when code assigns a value to an attribute that is not listed in the class's <code>__slots__</code> declaration.</p>
1+
<p>This rule raises an issue when code assigns a value to an attribute that is not listed in the classs <code>__slots__</code> declaration.</p>
22
<h2>Why is this an issue?</h2>
3-
<p>In Python, the <code>__slots__</code> class attribute is used to explicitly declare which instance attributes a class can have. When a class defines
4-
<code>__slots__</code>, Python restricts instances to only those attributes, preventing the creation of new attributes dynamically.</p>
5-
<p>Assigning to an attribute that is not in <code>__slots__</code> causes Python to raise an <code>AttributeError</code> at runtime.</p>
3+
<p>In Python, the <code>__slots__</code> class attribute is used to explicitly declare which instance attributes a class can have. When a class
4+
defines <code>__slots__</code>, Python restricts instances to only those attributes, preventing the creation of new attributes dynamically.</p>
5+
<p>This restriction serves several purposes:</p>
6+
<ul>
7+
<li><strong>memory efficiency</strong>: instances use less memory because Python does not create a <code>__dict__</code> for each instance</li>
8+
<li><strong>faster attribute access</strong>: attribute lookups are faster with <code>__slots__</code></li>
9+
<li><strong>explicit interface</strong>: the class clearly declares which attributes it supports</li>
10+
</ul>
11+
<p>Assigning to an attribute that is not in <code>__slots__</code> causes Python to raise an <code>AttributeError</code> at runtime:</p>
12+
<pre>
13+
class Point:
14+
__slots__ = ['x', 'y']
15+
16+
p = Point()
17+
p.x = 10 # OK
18+
p.z = 20 # Raises AttributeError: 'Point' object has no attribute 'z'
19+
</pre>
20+
<h3>What is the potential impact?</h3>
21+
<p>When code attempts to assign to an attribute not in <code>__slots__</code>, the application will crash with an <code>AttributeError</code> at
22+
runtime. This can lead to:</p>
23+
<ul>
24+
<li><strong>application crashes</strong>: the error will terminate the current operation unless properly handled</li>
25+
<li><strong>data loss</strong>: if the assignment happens during a data processing operation, partial results may be lost</li>
26+
<li><strong>poor user experience</strong>: users may encounter unexpected errors during normal operations</li>
27+
<li><strong>difficult debugging</strong>: the error may only occur in specific scenarios, making it hard to reproduce and fix</li>
28+
</ul>
629
<h2>How to fix it</h2>
7-
<p>Add the missing attribute to the <code>__slots__</code> declaration.</p>
30+
<p>If the attribute should be part of the class’s interface, add it to the <code>__slots__</code> declaration.</p>
831
<h3>Code examples</h3>
932
<h4>Noncompliant code example</h4>
1033
<pre data-diff-id="1" data-diff-type="noncompliant">
@@ -31,3 +54,4 @@ <h3>Documentation</h3>
3154
<ul>
3255
<li>Python Documentation - <a href="https://docs.python.org/3/reference/datamodel.html#slots">__slots__</a></li>
3356
</ul>
57+
Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
{
22
"title": "Attributes should only be assigned if they are declared in \"__slots__\"",
33
"type": "BUG",
4-
"code": {
5-
"impacts": {
6-
"RELIABILITY": "BLOCKER"
7-
},
8-
"attribute": "LOGICAL"
9-
},
104
"status": "ready",
115
"remediation": {
126
"func": "Constant\/Issue",
13-
"constantCost": "5min"
7+
"constantCost": "5 min"
148
},
15-
"tags": [],
9+
"tags": [
10+
"pitfall",
11+
"slots"
12+
],
1613
"defaultSeverity": "Blocker",
1714
"ruleSpecification": "RSPEC-8494",
1815
"sqKey": "S8494",
1916
"scope": "All",
20-
"quickfix": "unknown"
17+
"quickfix": "unknown",
18+
"code": {
19+
"impacts": {
20+
"RELIABILITY": "BLOCKER"
21+
},
22+
"attribute": "LOGICAL"
23+
}
2124
}

python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S8495.html

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ <h2>Why is this an issue?</h2>
1010
else:
1111
return (value, value * 2) # Returns a 2-tuple
1212

13+
# Caller has no reliable way to unpack this
1314
result = process_data(10)
1415
x, y = result # ValueError if value &gt; 0!
1516
</pre>
@@ -20,8 +21,8 @@ <h3>What is the potential impact?</h3>
2021
<p>Runtime errors from tuple unpacking may not surface during initial testing if certain code paths are not fully exercised, leading to production
2122
failures. The need for defensive length-checking also increases the maintenance burden and makes the API harder to document for new team members.</p>
2223
<h2>How to fix it</h2>
23-
<p>Make all return statements return tuples of the same length. Add placeholder values (like <code>None</code> or <code>0</code>) to shorter tuples
24-
to maintain consistency.</p>
24+
<p>Make all return statements return tuples of the same length. Add placeholder values (like <code>None</code> or <code>0</code>) to shorter tuples to
25+
maintain consistency.</p>
2526
<h3>Code examples</h3>
2627
<h4>Noncompliant code example</h4>
2728
<pre data-diff-id="1" data-diff-type="noncompliant">
@@ -41,9 +42,28 @@ <h4>Compliant solution</h4>
4142
average = total / len(numbers)
4243
return (total, average)
4344
</pre>
45+
<h3>Going the extra mile</h3>
46+
<p>For complex return types, consider using <code>typing.NamedTuple</code> to make the return value self-documenting. Named tuples provide clear field
47+
names and enforce a consistent structure, making the API easier to use and understand.</p>
48+
<pre>
49+
from typing import NamedTuple
50+
51+
class Stats(NamedTuple):
52+
total: float
53+
average: float
54+
55+
def calculate_stats(numbers) -&gt; Stats:
56+
if not numbers:
57+
return Stats(total=0, average=0)
58+
total = sum(numbers)
59+
average = total / len(numbers)
60+
return Stats(total=total, average=average)
61+
</pre>
4462
<h2>Resources</h2>
4563
<h3>Documentation</h3>
4664
<ul>
47-
<li>Python Documentation - <a href="https://docs.python.org/3/tutorial/controlflow.html#more-on-defining-functions">More on Defining Functions</a></li>
65+
<li>Python Documentation - <a href="https://docs.python.org/3/tutorial/controlflow.html#more-on-defining-functions">More on Defining
66+
Functions</a></li>
4867
<li>Python Documentation - <a href="https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences">Tuples and Sequences</a></li>
4968
</ul>
69+

python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S8495.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,23 @@
44
"status": "ready",
55
"remediation": {
66
"func": "Constant\/Issue",
7-
"constantCost": "5min"
7+
"constantCost": "10 min"
88
},
9-
"tags": [],
9+
"tags": [
10+
"pitfall",
11+
"api-design",
12+
"type-system"
13+
],
1014
"defaultSeverity": "Major",
1115
"ruleSpecification": "RSPEC-8495",
1216
"sqKey": "S8495",
1317
"scope": "Main",
1418
"quickfix": "unknown",
1519
"code": {
1620
"impacts": {
21+
"RELIABILITY": "HIGH",
1722
"MAINTAINABILITY": "HIGH"
1823
},
19-
"attribute": "CONVENTIONAL"
24+
"attribute": "CLEAR"
2025
}
2126
}

python-checks/src/main/resources/org/sonar/l10n/py/rules/python/Sonar_way_profile.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,8 @@
328328
"S8413",
329329
"S8414",
330330
"S8415",
331+
"S8494",
332+
"S8495",
331333
"S8504",
332334
"S8517",
333335
"S8521"

sonarpedia.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"languages": [
44
"PY"
55
],
6-
"latest-update": "2026-04-08T07:34:47.747313Z",
6+
"latest-update": "2026-04-09T08:05:06.976620Z",
77
"options": {
88
"no-language-in-filenames": true,
99
"preserve-filenames": true

0 commit comments

Comments
 (0)