From c223d407d00c38248e08aa38da0a25f443108f1a Mon Sep 17 00:00:00 2001 From: Guillaume Dequenne Date: Wed, 21 Jun 2023 10:00:20 +0200 Subject: [PATCH] Update rules metadata (#1497) --- .../l10n/py/rules/python/LineLength.html | 2 +- .../py/rules/python/OneStatementPerLine.html | 7 +- .../org/sonar/l10n/py/rules/python/S100.html | 11 +- .../org/sonar/l10n/py/rules/python/S101.html | 21 +- .../org/sonar/l10n/py/rules/python/S104.html | 7 +- .../org/sonar/l10n/py/rules/python/S108.html | 10 +- .../org/sonar/l10n/py/rules/python/S1134.html | 4 +- .../org/sonar/l10n/py/rules/python/S1134.json | 2 +- .../org/sonar/l10n/py/rules/python/S2190.json | 2 +- .../org/sonar/l10n/py/rules/python/S2757.html | 25 +- .../org/sonar/l10n/py/rules/python/S2757.json | 2 +- .../org/sonar/l10n/py/rules/python/S2761.html | 23 +- .../org/sonar/l10n/py/rules/python/S3358.html | 11 +- .../org/sonar/l10n/py/rules/python/S3776.html | 5 +- .../org/sonar/l10n/py/rules/python/S3923.html | 8 +- .../org/sonar/l10n/py/rules/python/S3981.html | 21 +- .../org/sonar/l10n/py/rules/python/S4143.html | 8 +- .../org/sonar/l10n/py/rules/python/S4144.html | 21 +- .../org/sonar/l10n/py/rules/python/S4426.html | 171 +++++++-- .../org/sonar/l10n/py/rules/python/S4487.html | 16 +- .../org/sonar/l10n/py/rules/python/S4830.html | 146 +++++--- .../org/sonar/l10n/py/rules/python/S5542.html | 332 +++++++++++++----- .../org/sonar/l10n/py/rules/python/S5547.html | 191 +++++----- .../org/sonar/l10n/py/rules/python/S6321.html | 42 ++- .../org/sonar/l10n/py/rules/python/S6326.json | 2 +- .../org/sonar/l10n/py/rules/python/S6397.json | 2 +- sonarpedia.json | 2 +- 27 files changed, 712 insertions(+), 382 deletions(-) diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/LineLength.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/LineLength.html index 10a9058c20..013131f871 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/LineLength.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/LineLength.html @@ -1,3 +1,3 @@

Why is this an issue?

-

Having to scroll horizontally makes it harder to get a quick overview and understanding of any piece of code.

+

Scrolling horizontally to see a full line of code lowers the code readability.

diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/OneStatementPerLine.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/OneStatementPerLine.html index 30b471d18b..06657ec9e8 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/OneStatementPerLine.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/OneStatementPerLine.html @@ -1,10 +1,9 @@

Why is this an issue?

-

For better readability, do not put more than one statement on a single line.

-

Noncompliant code example

+

Putting multiple statements on a single line lowers the code readability and makes debugging the code more complex.

-if (True): print("hello")
+if (True): print("hello") # Noncompliant
 
-

Compliant solution

+

Write one statement per line to improve readability.

 if (True):
     print("hello")
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S100.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S100.html
index fff9d02753..d0cb9a4990 100644
--- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S100.html
+++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S100.html
@@ -1,14 +1,13 @@
 

Why is this an issue?

-

Sharing some naming conventions is a key point to make it possible for a team to efficiently collaborate. This rule allows to check that all method -names match a provided regular expression.

-

Noncompliant code example

-

With default provided regular expression: ^[a-z_][a-z0-9_]*$

+

Shared naming conventions allow teams to collaborate efficiently.

+

This rule raises an issue when a method name does not match a provided regular expression.

+

For example, with the default provided regular expression ^[a-z_][a-z0-9_]*$, the method:

 class MyClass:
-    def MyMethod(a,b):
+    def MyMethod(a,b): # Noncompliant
         ...
 
-

Compliant solution

+

should be renamed to

 class MyClass:
     def my_method(a,b):
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S101.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S101.html
index 04294da33f..b1bcf74b0d 100644
--- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S101.html
+++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S101.html
@@ -1,11 +1,10 @@
 

Why is this an issue?

-

Shared coding conventions allow teams to collaborate effectively. This rule allows to check that all class names match a provided regular -expression.

-

The default regular expression is based on PEP-8 standard. It allows "CapWords" convention and "snake_case" in lowercase. The "snake_case" -convention is accepted by PEP-8 when the class is primarily used as a callable (ex: decorator, context manager, etc…​). However the "CapWords" -convention is recommended in every case.

-

Noncompliant code example

-

With default provided regular expression ^_?([A-Z_][a-zA-Z0-9]*|[a-z_][a-z0-9_]*)$:

+

Shared naming conventions allow teams to collaborate efficiently.

+

This rule raises an issue when a class name does not match a provided regular expression.

+

The default regular expression allows the "CapWords" convention and the "snake_case" in lowercase. The style guide PEP-8 recommends using the +"CapWords" convention in every case but also accepts the "snake_case" convention when the class is primarily used as a callable (ex: decorator, +context manager, etc…​).

+

For example, with the default provided regular expression ^_?([A-Z_][a-zA-Z0-9]*|[a-z_][a-z0-9_]*)$, the classes:

 class myClass:  # Noncompliant
    ...
@@ -16,7 +15,7 @@ 

Noncompliant code example

def __exit__(self, type, value, traceback): pass
-

Compliant solution

+

should be renamed to

 class MyClass:
    ...
@@ -27,4 +26,10 @@ 

Compliant solution

def __exit__(self, type, value, traceback): pass
+

Resources

+

Documentation

+ diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S104.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S104.html index f6c0dbaa44..cc8ee8fa38 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S104.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S104.html @@ -1,5 +1,6 @@

Why is this an issue?

-

A source file that grows too much tends to aggregate too many responsibilities and inevitably becomes harder to understand and therefore to -maintain. Above a specific threshold, it is strongly advised to refactor it into smaller pieces of code which focus on well defined tasks. Those -smaller files will not only be easier to understand but also probably easier to test.

+

A source file that grows too much tends to aggregate too many responsibilities and inevitably becomes harder to understand and, therefore, to +maintain.

+

Above a specific threshold, refactor the file into smaller files whose code focuses on well-defined tasks. Those smaller files will be easier to +understand and easier to test.

diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S108.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S108.html index 5b9107e9c9..6462f51117 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S108.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S108.html @@ -1,10 +1,12 @@

Why is this an issue?

-

Most of the time a block of code is empty when a piece of code is really missing. So such empty block must be either filled or removed.

-

Noncompliant code example

+

An empty code block is confusing. It will require some effort from maintainers to determine if it is intentional or indicates the implementation is +incomplete.

+# Noncompliant: is the block empty on purpose, or is code missing?
 for i in range(3):
     pass
 
-

Exceptions

-

When a block contains a comment, this block is not considered to be empty.

+

Removing or filling the empty code blocks takes away ambiguity and generally results in a more straightforward and less surprising code. === +Exceptions

+

The rule ignores code blocks that contain comments.

diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1134.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1134.html index 8259c2e451..0d92ba6fb3 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1134.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1134.html @@ -2,13 +2,13 @@

Why is this an issue?

FIXME tags are commonly used to mark places where a bug is suspected, but which the developer wants to deal with later.

Sometimes the developer will not have the time or will simply forget to get back to that tag.

This rule is meant to track those tags and to ensure that they do not go unnoticed.

-

Noncompliant code example

 def divide(numerator, denominator):
   return numerator / denominator              # FIXME denominator value might be 0
 

Resources

+

Documentation

diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1134.json b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1134.json index 00aef3d01f..2fb339349a 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1134.json +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1134.json @@ -18,5 +18,5 @@ 546 ] }, - "quickfix": "unknown" + "quickfix": "infeasible" } diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2190.json b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2190.json index c3ffb41fb3..2b664a001d 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2190.json +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2190.json @@ -13,5 +13,5 @@ "ruleSpecification": "RSPEC-2190", "sqKey": "S2190", "scope": "All", - "quickfix": "unknown" + "quickfix": "infeasible" } diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2757.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2757.html index 9b4f26fe89..35dba57071 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2757.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2757.html @@ -1,22 +1,27 @@

Why is this an issue?

-

The use of operators pairs ( =+ or =-) where the reversed, single operator was meant (+= or -=) -will run fine, but not produce the expected results.

-

This rule raises an issue when =+ or =- is used without any spacing between the two operators and when there is at least -one whitespace character after.

-

Noncompliant code example

+

Using operator pairs (=+ or =-) that look like reversed single operators (+= or -=) is +confusing. They compile and run but do not produce the same result as their mirrored counterpart.

 target = -5
 num = 3
 
-target =- num  # Noncompliant; target = -3. Is that really what's meant?
-target =+ num # Noncompliant; target = 3
+target =- num  # Noncompliant: target = -3. Is that really what's meant?
+target =+ num # Noncompliant: target = 3
 
-

Compliant solution

+

This rule raises an issue when =+ or =- are used without any space between the operators and when there is at least one +whitespace after.

+

Replace the operators with a single one if that is the intention

 target = -5
 num = 3
 
-target = -num  # Compliant; intent to assign inverse value of num is clear
-target += num
+target -= num  # target = -8
+
+

Or fix the spacing to avoid confusion

+
+target = -5
+num = 3
+
+target = -num  #  target = -3
 
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2757.json b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2757.json index bdf3a05503..acd83d9f50 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2757.json +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2757.json @@ -1,5 +1,5 @@ { - "title": "\"\u003d+\" should not be used instead of \"+\u003d\"", + "title": "Non-existent operators like \"\u003d+\" should not be used", "type": "BUG", "status": "ready", "remediation": { diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2761.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2761.html index 1e8b62fc35..24c5c0fd50 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2761.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2761.html @@ -1,25 +1,16 @@

Why is this an issue?

-

Calling the not or ~ prefix operator twice might be redundant: the second invocation undoes the first. Such mistakes are -typically caused by accidentally double-tapping the key in question without noticing. Either this is a bug, if the operator was actually meant to be -called once, or misleading if done on purpose. Calling not twice is commonly done instead of using the dedicated "bool()" builtin -function. However, the latter one increases the code readability and should be used.

-

Noncompliant code example

+

The repetition of a prefix operator (not or ~) is usually a typo. The second operator invalidates the first one:

-a = 0
-b = False
-
-c = not not a # Noncompliant
-d = ~~b # Noncompliant
+a = False
+b = ~~a # Noncompliant: equivalent to "a"
 
-

Compliant solution

+

While calling not twice is equivalent to calling the bool() built-in function, the latter increases the code readability, +so it should be preferred.

 a = 0
-b = False
 
-c = bool(a)
-d = ~b
+b = not not a # Noncompliant: use bool()
 

Exceptions

-

If the ~ function has been overloaded in a customised class and has been called twice, no warning is raised as it is assumed to be an -expected usage.

+

The rule does not raise an issue if the ~ function is overloaded in a customized class, as it is assumed to be the expected usage.

diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3358.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3358.html index 3728f1f3a9..a1dcc51e11 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3358.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3358.html @@ -1,16 +1,12 @@

Why is this an issue?

-

Just because you can do something, doesn’t mean you should, and that’s the case with nested conditional expressions. Nesting conditional -expressions results in the kind of code that may seem clear as day when you write it, but six months later will leave maintainers (or worse - future -you) scratching their heads and cursing.

-

Instead, err on the side of clarity, and use another line to express the nested operation as a separate statement.

-

Noncompliant code example

+

Nested conditionals are hard to read and can make the order of operations complex to understand.

 class Job:
     @property
     def readable_status(self):
         return "Running" if job.is_running else "Failed" if job.errors else "Succeeded"  # Noncompliant
 
-

Compliant solution

+

Instead, use another line to express the nested operation in a separate statement.

 class Job:
     @property
@@ -21,4 +17,7 @@ 

Compliant solution

Exceptions

No issue is raised on conditional expressions in comprehensions.

+
+job_statuses = ["Running" if job.is_running else "Failed" if job.errors else "Succeeded" for job in jobs]  # Compliant by exception
+
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3776.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3776.html index bce85c33f3..be9d04d0c5 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3776.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3776.html @@ -1,7 +1,8 @@

Why is this an issue?

-

Cognitive Complexity is a measure of how hard the control flow of a function is to understand. Functions with high Cognitive Complexity will be -difficult to maintain.

+

Cognitive Complexity is a measure of how hard the control flow of a function +is to understand. Functions with high Cognitive Complexity will be difficult to maintain.

Resources

+

Documentation

diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3923.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3923.html index f407f1f9c1..f4ab948424 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3923.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3923.html @@ -1,7 +1,6 @@

Why is this an issue?

-

Having the same implementation in every branch of an if chain is an error. Either a copy-paste error was made and something different -should be executed, or there shouldn’t be an if chain at all.

-

Noncompliant code example

+

Having all branches of an if chain with the same implementation indicates a problem.

+

In the following code:

 if b == 0:  # Noncompliant
     doOneMoreThing()
@@ -12,8 +11,9 @@ 

Noncompliant code example

b = 4 if a > 12 else 4 # Noncompliant
+

Either there is a copy-paste error that needs fixing or the unnecessary if chain needs removing.

Exceptions

-

This rule does not apply to if chains without else-s.

+

This rule does not apply to if chains without else.

 if b == 0:  # no issue, this could have been done on purpose to make the code more readable
     doOneMoreThing()
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3981.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3981.html
index fcb5ba30be..8e7b3df4c1 100644
--- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3981.html
+++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3981.html
@@ -1,23 +1,16 @@
 

Why is this an issue?

-

The length of a collection is always greater than or equal to zero. So testing that a length is greater than or equal to zero doesn’t make sense, -since the result is always true. Similarly testing that it is less than zero will always return false. Perhaps the intent -was to check the non-emptiness of the collection instead.

-

Noncompliant code example

+

The length of a collection is always greater than or equal to zero. Testing it doesn’t make sense, since the result is always +true.

 mylist = []
-if len(myList) >= 0:  # Noncompliant
-    pass
-
-if len(myList) < 0:  # Noncompliant
+if len(myList) >= 0:  # Noncompliant: always true
     pass
 
-

Compliant solution

+

Similarly testing that it is less than zero will always return false.

-mylist = []
-if len(myList) >= 42:
-    pass
-
-if len(myList) == 0:
+if len(myList) < 0:  # Noncompliant: always false
     pass
+----
 
+

Fix the code to properly check for emptiness if it was the intent, or remove the redundant code to keep the current behavior.

diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4143.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4143.html index 7d647608b2..b66463adf3 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4143.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4143.html @@ -1,9 +1,6 @@

Why is this an issue?

-

It is highly suspicious when a value is saved in a collection for a given key or index and then unconditionally overwritten. Such replacements are -likely errors.

-

This rule raises an issue when the __setitem__ -method of the same object is called multiple times with the same index, slice or key without any other action done between the calls.

-

Noncompliant code example

+

Storing a value inside a collection at a given key or index and then unconditionally overwriting it without reading the initial value is a case of +"dead store".

 def swap(mylist, index1, index2):
     tmp = mylist[index2]
@@ -18,4 +15,5 @@ 

Noncompliant code example

mymap['a']['b'] = 42 mymap['a']['b'] = 42 # Noncompliant
+

At best it is redundant and will confuse the reader, most often it is an error and not what the developer intended to do.

diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4144.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4144.html index da1f635331..a80f799272 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4144.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4144.html @@ -1,33 +1,32 @@

Why is this an issue?

-

When two functions or methods have the same implementation, either it was a mistake - something else was intended - or the duplication was -intentional, but may be confusing to maintainers. In the latter case, one implementation should invoke the other. Numerical and string literals are -not taken into account.

-

Noncompliant code example

-
+

Two functions having the same implementation are suspicious. It might be that something else was intended. Or the duplication is intentional, which +becomes a maintenance burden.

+
 class MyClass:
-    code = "bounteous"
+    code = "secret"
 
     def calculate_code(self):
         self.do_the_thing()
         return self.__class__.code
 
-    def get_name(self):  # Noncompliant
+    def get_name(self):  # Noncompliant: duplicates calculate_code
         self.do_the_thing()
         return self.__class__.code
 
     def do_the_thing(self):
         pass  # on purpose
 
-

Compliant solution

-
+

If the identical logic is intentional, the code should be refactored to avoid duplication. For example, by having both functions call the same +function or by having one implementation invoke the other.

+
 class MyClass:
-    code = "bounteous"
+    code = "secret"
 
     def calculate_code(self):
         self.do_the_thing()
         return self.__class__.code
 
-    def get_name(self):
+    def get_name(self):  # Intent is clear
         return self.calculate_code()
 
     def do_the_thing(self):
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4426.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4426.html
index 144d9a5781..40b0b6c8d8 100644
--- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4426.html
+++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4426.html
@@ -1,43 +1,164 @@
+

This vulnerability exposes encrypted data to attacks whose goal is to recover the plaintext.

Why is this an issue?

-

When generating cryptographic keys (or key pairs), it is important to use strong parameters. Key length, for instance, should provide enough -entropy against brute-force attacks.

+

Encryption algorithms are essential for protecting sensitive information and ensuring secure communications in a variety of domains. They are used +for several important reasons:

    -
  • For RSA and DSA algorithms key size should be at least 2048 bits long
  • -
  • For ECC (elliptic curve cryptography) algorithms key size should be at least 224 bits long
  • -
  • For RSA public key exponent should be at least 65537.
  • +
  • Confidentiality, privacy, and intellectual property protection
  • +
  • Security during transmission or on storage devices
  • +
  • Data integrity, general trust, and authentication
-

This rule raises an issue when a RSA, DSA or ECC key-pair generator is initialized using weak -parameters.

-

It supports the following libraries:

+

When selecting encryption algorithms, tools, or combinations, you should also consider two things:

+
    +
  1. No encryption is unbreakable.
  2. +
  3. The strength of an encryption algorithm is usually measured by the effort required to crack it within a reasonable time frame.
  4. +
+

In today’s cryptography, the length of the key directly affects the security level of cryptographic algorithms.

+

Note that depending on the algorithm, the term key refers to a different mathematical property. For example:

    -
  • cryptography
  • -
  • PyCrypto
  • -
  • Cryptodome
  • +
  • For RSA, the key is the product of two large prime numbers, also called the modulus.
  • +
  • For AES and Elliptic Curve Cryptography (ECC), the key is only a sequence of randomly generated bytes. +
      +
    • In some cases, AES keys are derived from a master key or a passphrase using a Key Derivation Function (KDF) like PBKDF2 (Password-Based Key + Derivation Function 2)
    • +
-

Noncompliant code example

-
-from cryptography.hazmat.primitives.asymmetric import rsa, ec, dsa
+

If an application uses a key that is considered short and insecure, the encrypted data is exposed to attacks aimed at getting at +the plaintext.

+

In general, it is best practice to expect a breach: that a user or organization with malicious intent will perform cryptographic attacks on this +data after obtaining it by other means.

+

What is the potential impact?

+

After retrieving encrypted data and performing cryptographic attacks on it on a given timeframe, attackers can recover the plaintext that +encryption was supposed to protect.

+

Depending on the recovered data, the impact may vary.

+

Below are some real-world scenarios that illustrate the potential impact of an attacker exploiting the vulnerability.

+

Additional attack surface

+

By modifying the plaintext of the encrypted message, an attacker may be able to trigger additional vulnerabilities in the code. An attacker can +further exploit a system to obtain more information.
Encrypted values are often considered trustworthy because it would not be possible for a +third party to modify them under normal circumstances.

+

Breach of confidentiality and privacy

+

When encrypted data contains personal or sensitive information, its retrieval by an attacker can lead to privacy violations, identity theft, +financial loss, reputational damage, or unauthorized access to confidential systems.

+

In this scenario, the company, its employees, users, and partners could be seriously affected.

+

The impact is twofold, as data breaches and exposure of encrypted data can undermine trust in the organization, as customers, clients and +stakeholders may lose confidence in the organization’s ability to protect their sensitive data.

+

Legal and compliance issues

+

In many industries and locations, there are legal and compliance requirements to protect sensitive data. If encrypted data is compromised and the +plaintext can be recovered, companies face legal consequences, penalties, or violations of privacy laws.

+

How to fix it in pyca

+

Code examples

+

The following code examples either explicitly or implicitly generate keys. Note that there are differences in the size of the keys depending on the +algorithm.

+

Due to the mathematical properties of the algorithms, the security requirements for the key size vary depending on the algorithm.
For example, +a 256-bit ECC key provides about the same level of security as a 3072-bit RSA key and a 128-bit symmetric key.

+

Noncompliant code example

+

Here is an example of a private key generation with RSA:

+
+from cryptography.hazmat.primitives.asymmetric import rsa
+from cryptography.hazmat.backends import default_backend
 
-dsa.generate_private_key(key_size=1024, backend=backend) # Noncompliant
-rsa.generate_private_key(public_exponent=999, key_size=2048, backend=backend) # Noncompliant
-ec.generate_private_key(curve=ec.SECT163R2, backend=backend)  # Noncompliant
+backend = default_backend()
+
+private_key = rsa.generate_private_key(key_size = 1024, backend = backend) # Noncompliant
+public_key  = private_key.public_key()
+
+

Here is an example of a key generation with the Digital Signature Algorithm (DSA):

+
+from cryptography.hazmat.primitives.asymmetric import dsa
+from cryptography.hazmat.backends import default_backend
+
+backend = default_backend()
+
+private_key = dsa.generate_private_key(key_size = 1024, backend = backend) # Noncompliant
+public_key  = private_key.public_key()
+
+

Here is an example of an Elliptic Curve (EC) initialization. It implicitly generates a private key whose size is indicated in the algorithm +name:

+
+from cryptography.hazmat.primitives.asymmetric import ec
+from cryptography.hazmat.backends import default_backend
+
+backend = default_backend()
+
+private_key = ec.generate_private_key(curve=ec.SECT163R2, backend=backend)  # Noncompliant
+public_key  = private_key.public_key()
+
+

Compliant solution

+
+from cryptography.hazmat.primitives.asymmetric import rsa
+from cryptography.hazmat.backends import default_backend
+
+backend = default_backend()
+
+private_key = rsa.generate_private_key(key_size = 2048, backend = backend)
+public_key  = private_key.public_key()
+
+
+from cryptography.hazmat.primitives.asymmetric import dsa
+from cryptography.hazmat.backends import default_backend
+
+backend = default_backend()
+
+private_key = dsa.generate_private_key(key_size = 2048, backend = backend)
+public_key  = private_key.public_key()
 
-

Compliant solution

-
-from cryptography.hazmat.primitives.asymmetric import rsa, ec, dsa
+
+from cryptography.hazmat.primitives.asymmetric import ec
+from cryptography.hazmat.backends import default_backend
+
+backend = default_backend()
 
-dsa.generate_private_key(key_size=2048, backend=backend) # Compliant
-rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=backend) # Compliant
-ec.generate_private_key(curve=ec.SECT409R1, backend=backend) # Compliant
+private_key = ec.generate_private_key(curve=ec.SECT409R1, backend=backend)
+public_key  = private_key.public_key()
 
+

How does this work?

+

As a rule of thumb, use the cryptographic algorithms and mechanisms that are considered strong by the cryptographic community.

+

The appropriate choices are the following.

+

RSA (Rivest-Shamir-Adleman) and DSA (Digital Signature Algorithm)

+

The security of these algorithms depends on the difficulty of attacks attempting to solve their underlying mathematical problem.

+

In general, a minimum key size of 2048 bits is recommended for both.

+

AES (Advanced Encryption Standard)

+

AES supports three key sizes: 128 bits, 192 bits and 256 bits. The security of the AES algorithm is based on the computational complexity of trying +all possible keys.
A larger key size increases the number of possible keys and makes exhaustive search attacks computationally infeasible. +Therefore, a 256-bit key provides a higher level of security than a 128-bit or 192-bit key.

+

Currently, a minimum key size of 128 bits is recommended for AES.

+

Elliptic Curve Cryptography (ECC)

+

Elliptic curve cryptography is also used in various algorithms, such as ECDSA, ECDH, or ECMQV. The length of keys generated with elliptic curve +algorithms are mentioned directly in their names. For example, secp256k1 generates a 256-bits long private key.

+

Currently, a minimum key size of 224 bits is recommended for EC algorithms.

+

Going the extra mile

+

Pre-Quantum Cryptography

+

Encrypted data and communications recorded today could be decrypted in the future by an attack from a quantum computer.
It is important to keep +in mind that NIST-approved digital signature schemes, key agreement, and key transport may need to be replaced with secure quantum-resistant (or +"post-quantum") counterpart.

+

Thus, if data is to remain secure beyond 2030, proactive measures should be taken now to ensure its safety.

+

Learn more here.

Resources

+

Articles & blog posts

+ +

Standards

diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4487.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4487.html index cf746d19c6..d4dd0971a9 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4487.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4487.html @@ -1,21 +1,24 @@ +

Private attributes which are written but never read are a case of "dead store". Changing their value is useless and most probably indicates an +error in the code.

Why is this an issue?

-

Private attributes which are written but never read are a clear case of dead store. Changing their value is useless and most probably indicates a -serious error in the code.

Python has no real private attribute. Every attribute is accessible. There are however two conventions indicating that an attribute is not meant to be "public":

  • attributes with a name starting with a single underscore (ex: _myattribute) should be seen as non-public and might change without prior notice. They should not be used by third-party libraries or software. It is ok to use those methods inside the library defining them but it should be done with caution.
  • -
  • "class-private" attributes have a name which starts with at least two underscores and ends with at most one underscore. These attribute’s names +
  • "class-private" attributes have a name starting with at least two underscores and ending with at most one underscore. These attributes' names will be automatically mangled to avoid collision with subclasses' attributes. For example __myattribute will be renamed as _classname__myattribute, where classname is the attribute’s class name without its leading underscore(s). They shouldn’t be used outside of the class defining the attribute.

This rule raises an issue when a class-private attribute (two leading underscores, max one underscore at the end) is never read inside the class. -It optionally raises an issue on unread attributes prefixed with a single underscore. Both class attribute and instance attributes will raise an +It optionally raises an issue on unread attributes prefixed with a single underscore. Both class attributes and instance attributes will raise an issue.

-

Noncompliant code example

+

How to fix it

+

Remove the attribute or fix the code to read it.

+

Code examples

+

Noncompliant code example

 class Noncompliant:
     _class_attr = 0  # Noncompliant if enable_single_underscore_issues is enabled
@@ -28,7 +31,7 @@ 

Noncompliant code example

def compute(self, x): return x * x
-

Compliant solution

+

Compliant solution

 class Compliant:
     _class_attr = 0
@@ -42,6 +45,7 @@ 

Compliant solution

return x * Compliant._class_attr * Compliant.__mangled_class_attr * self._attr * self.__mangled_attr

Resources

+

Documentation

  • Python documentation – Private Variables
  • PEP 8 – Style Guide for Python Code
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4830.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4830.html index 434b0ec249..de1a99505a 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4830.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4830.html @@ -1,68 +1,120 @@ +

    This vulnerability makes it possible that an encrypted communication is intercepted.

    Why is this an issue?

    -

    Validation of X.509 certificates is essential to create secure SSL/TLS sessions not vulnerable to man-in-the-middle attacks.

    -

    The certificate chain validation includes these steps:

    -
      -
    • The certificate is issued by its parent Certificate Authority or the root CA trusted by the system.
    • -
    • Each CA is allowed to issue certificates.
    • -
    • Each certificate in the chain is not expired.
    • -
    -

    It’s not recommended to reinvent the wheel by implementing custom certificate chain validation.

    -

    TLS libraries provide built-in certificate validation functions that should be used.

    -

    Noncompliant code example

    -

    psf/requests library:

    -
    -import requests
    -
    -requests.request('GET', 'https://example.domain', verify=False) # Noncompliant
    -requests.get('https://example.domain', verify=False) # Noncompliant
    -
    -

    Python ssl standard library:

    -
    +

    Transport Layer Security (TLS) provides secure communication between systems over the internet by encrypting the data sent between them. The role +of certificate validation in this process is to ensure that a system is indeed the one it claims to be, adding an extra layer of trust and +security.

    +

    When certificate validation is disabled, the client skips this critical check. This creates an opportunity for attackers to pose as a trusted +entity and intercept, manipulate, or steal the data being transmitted.

    +

    What is the potential impact?

    +

    Establishing trust in a secure way is a non-trivial task. When you disable certificate validation, you are removing a key mechanism designed to +build this trust in internet communication, opening your system up to a number of potential threats.

    +

    Identity spoofing

    +

    If a system does not validate certificates, it cannot confirm the identity of the other party involved in the communication. An attacker can +exploit this by creating a fake server and masquerading it as a legitimate one. For example, they might set up a server that looks like your bank’s +server, tricking your system into thinking it is communicating with the bank. This scenario, called identity spoofing, allows the attacker to collect +any data your system sends to them, potentially leading to significant data breaches.

    +

    Loss of data integrity

    +

    When TLS certificate validation is disabled, the integrity of the data you send and receive cannot be guaranteed. An attacker could modify the data +in transit, and you would have no way of knowing. This could range from subtle manipulations of the data you receive to the injection of malicious +code or malware into your system. The consequences of such breaches of data integrity can be severe, depending on the nature of the data and the +system.

    +

    How to fix it in Python Standard Library

    +

    Code examples

    +

    The following code contains examples of disabled certificate validation.

    +

    Certificate validation is not enabled by default when _create_unverified_context is used. It is recommended to use +_create_default_https_context instead to create a secure context that validates certificates.

    +

    Noncompliant code example

    +
     import ssl
     
    -ctx1 = ssl._create_unverified_context() # Noncompliant: by default certificate validation is not done
    -ctx2 = ssl._create_stdlib_context() # Noncompliant: by default certificate validation is not done
    +ctx1 = ssl._create_unverified_context() # Noncompliant
    +ctx2 = ssl._create_stdlib_context() # Noncompliant
     
     ctx3 = ssl.create_default_context()
     ctx3.verify_mode = ssl.CERT_NONE # Noncompliant
     
    -

    pyca/pyopenssl library:

    -
    +

    Compliant solution

    +
    +import ssl
    +
    +ctx = ssl.create_default_context()
    +ctx.verify_mode = ssl.CERT_REQUIRED
    +
    +# By default, certificate validation is enabled
    +ctx = ssl._create_default_https_context()
    +
    +

    How does this work?

    +

    Addressing the vulnerability of disabled TLS certificate validation primarily involves re-enabling the default validation.

    +

    To avoid running into problems with invalid certificates, consider the following sections.

    +

    Using trusted certificates

    +

    If possible, always use a certificate issued by a well-known, trusted CA for your server. Most programming environments come with a predefined list +of trusted root CAs, and certificates issued by these authorities are validated automatically. This is the best practice, and it requires no +additional code or configuration.

    +

    Working with self-signed certificates or non-standard CAs

    +

    In some cases, you might need to work with a server using a self-signed certificate, or a certificate issued by a CA not included in your trusted +roots. Rather than disabling certificate validation in your code, you can add the necessary certificates to your trust store.

    +

    How to fix it in OpenSSL

    +

    Code examples

    +

    The following code contains examples of disabled certificate validation.

    +

    Certificate validation is not enabled by default and has to be explicitly enabled through set_verify.

    +

    Noncompliant code example

    +
     from OpenSSL import SSL
     
    -ctx1 = SSL.Context(SSL.TLSv1_2_METHOD) # Noncompliant: by default certificate validation is not done
    +ctx1 = SSL.Context(SSL.TLSv1_2_METHOD) # Noncompliant
     
     ctx2 = SSL.Context(SSL.TLSv1_2_METHOD)
     ctx2.set_verify(SSL.VERIFY_NONE, verify_callback) # Noncompliant
     
    -

    Compliant solution

    -

    psf/requests library:

    -
    -import requests
    +

    Compliant solution

    +
    +from OpenSSL import SSL
     
    -requests.request('GET', 'https://example.domain', verify=True)
    -requests.request('GET', 'https://example.domain', verify='/path/to/CAbundle')
    -requests.get(url='https://example.domain') # by default certificate validation is enabled
    +ctx = SSL.Context(SSL.TLSv1_2_METHOD)
    +ctx.set_verify(SSL.VERIFY_PEER, verify_callback)
    +ctx.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback)
    +ctx.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT | SSL.VERIFY_CLIENT_ONCE, verify_callback)
     
    -

    Python ssl standard library:

    -
    -import ssl
    -
    -ctx = ssl.create_default_context()
    -ctx.verify_mode = ssl.CERT_REQUIRED
    +

    How does this work?

    +

    Addressing the vulnerability of disabled TLS certificate validation primarily involves re-enabling the default validation.

    +

    To avoid running into problems with invalid certificates, consider the following sections.

    +

    Using trusted certificates

    +

    If possible, always use a certificate issued by a well-known, trusted CA for your server. Most programming environments come with a predefined list +of trusted root CAs, and certificates issued by these authorities are validated automatically. This is the best practice, and it requires no +additional code or configuration.

    +

    Working with self-signed certificates or non-standard CAs

    +

    In some cases, you might need to work with a server using a self-signed certificate, or a certificate issued by a CA not included in your trusted +roots. Rather than disabling certificate validation in your code, you can add the necessary certificates to your trust store.

    +

    How to fix it in Requests

    +

    Code examples

    +

    The following code contains examples of disabled certificate validation.

    +

    The certificate validation gets disabled by setting verify to False. To enable validation set the value to +True or do not set verify at all to use the secure default value.

    +

    Noncompliant code example

    +
    +import requests
     
    -ctx = ssl._create_default_https_context() # by default certificate validation is enabled
    +requests.request('GET', 'https://example.com', verify=False) # Noncompliant
     
    -

    pyca/pyopenssl library:

    -
    -from OpenSSL import SSL
    +

    Compliant solution

    +
    +import requests
     
    -ctx = SSL.Context(SSL.TLSv1_2_METHOD)
    -ctx.set_verify(SSL.VERIFY_PEER, verify_callback) # Compliant
    -ctx.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback) # Compliant
    -ctx.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT | SSL.VERIFY_CLIENT_ONCE, verify_callback) # Compliant
    +# By default, certificate validation is enabled
    +requests.request('GET', 'https://example.com')
     
    +

    How does this work?

    +

    Addressing the vulnerability of disabled TLS certificate validation primarily involves re-enabling the default validation.

    +

    To avoid running into problems with invalid certificates, consider the following sections.

    +

    Using trusted certificates

    +

    If possible, always use a certificate issued by a well-known, trusted CA for your server. Most programming environments come with a predefined list +of trusted root CAs, and certificates issued by these authorities are validated automatically. This is the best practice, and it requires no +additional code or configuration.

    +

    Working with self-signed certificates or non-standard CAs

    +

    In some cases, you might need to work with a server using a self-signed certificate, or a certificate issued by a CA not included in your trusted +roots. Rather than disabling certificate validation in your code, you can add the necessary certificates to your trust store.

    Resources

    +

    Standards

    diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5542.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5542.html index 16e48d573f..dc103083e2 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5542.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5542.html @@ -1,123 +1,271 @@ +

    This vulnerability exposes encrypted data to a number of attacks whose goal is to recover the plaintext.

    Why is this an issue?

    -

    Encryption algorithms should use secure modes and padding schemes where appropriate to guarantee data confidentiality and integrity.

    +

    Encryption algorithms are essential for protecting sensitive information and ensuring secure communications in a variety of domains. They are used +for several important reasons:

      -
    • For block cipher encryption algorithms (like AES): -
        -
      • The ECB (Electronic Codebook) cipher mode doesn’t provide serious message confidentiality: under a given key any given plaintext block - always gets encrypted to the same ciphertext block. This mode should never be used.
      • -
      • The CBC (Cipher Block Chaining) mode by itself provides only data confidentiality. This cipher mode is also vulnerable to padding oracle attacks when used with padding. Using CBC along with Message - Authentication Code can provide data integrity and should prevent such attacks. In practice the implementation has many pitfalls and it’s - recommended to avoid CBC with padding completely.
      • -
      • The GCM (Galois Counter Mode) mode which works - internally with zero/no padding scheme, is recommended, as it is designed to provide both data authenticity (integrity) and confidentiality. - Other similar modes are CCM, CWC, EAX, IAPM and OCB.
      • -
    • -
    • For RSA encryption algorithm, the recommended padding scheme is OAEP.
    • +
    • Confidentiality, privacy, and intellectual property protection
    • +
    • Security during transmission or on storage devices
    • +
    • Data integrity, general trust, and authentication
    -

    Noncompliant code example

    -

    pycryptodomex library:

    -
    -from Cryptodome.Cipher import AES, PKCS1_OAEP,  PKCS1_v1_5
    -from Cryptodome.Random import get_random_bytes
    -from Cryptodome.PublicKey import RSA
    -
    -# Example for a symmetric cipher: AES
    -AES.new(key, AES.MODE_ECB)  # Noncompliant
    -AES.new(key, AES.MODE_CBC)  # Noncompliant
    +

    When selecting encryption algorithms, tools, or combinations, you should also consider two things:

    +
      +
    1. No encryption is unbreakable.
    2. +
    3. The strength of an encryption algorithm is usually measured by the effort required to crack it within a reasonable time frame.
    4. +
    +

    For these reasons, as soon as cryptography is included in a project, it is important to choose encryption algorithms that are considered strong and +secure by the cryptography community.

    +

    For AES, the weakest modes are CBC (Cipher Block Chaining) and ECB

    +

    (Electronic Codebook), as they are either vulnerable to padding oracles or do not provide authentication mechanisms.

    +

    And for RSA, the weakest algorithms are either using it without padding or using the PKCS1v1.5 padding scheme.

    +

    What is the potential impact?

    +

    The cleartext of an encrypted message might be recoverable. Additionally, it might be possible to modify the cleartext of an encrypted message.

    +

    Below are some real-world scenarios that illustrate possible impacts of an attacker exploiting the vulnerability.

    +

    Theft of sensitive data

    +

    The encrypted message might contain data that is considered sensitive and should not be known to third parties.

    +

    By using a weak algorithm the likelihood that an attacker might be able to recover the cleartext drastically increases.

    +

    Additional attack surface

    +

    By modifying the cleartext of the encrypted message it might be possible for an attacker to trigger other vulnerabilities in the code. Encrypted +values are often considered trusted, since under normal circumstances it would not be possible for a third party to modify them.

    +

    How to fix it in PyCrypto

    +

    Code examples

    +

    Noncompliant code example

    +

    Example with a symmetric cipher, AES:

    +
    +from Crypto.Cipher import AES
    +
    +AES.new(key, AES.MODE_ECB) # Noncompliant
    +
    +

    Example with an asymmetric cipher, RSA:

    +
    +from Crypto.Cipher import PKCS1_v1_5
    +
    +PKCS1_v1_5.new(key) # Noncompliant
    +
    +

    Compliant solution

    +

    Since PyCrypto is not supported anymore, another library should be used. In the current context, Cryptodome uses a similar API.

    +

    For the AES symmetric cipher, use the GCM mode:

    +
    +from Crypto.Cipher import AES
    +
    +AES.new(key, AES.MODE_GCM)
    +
    +

    For the RSA asymmetric cipher, use the Optimal Asymmetric Encryption Padding (OAEP):

    +
    +from Crypto.Cipher import PKCS1_OAEP
     
    -# Example for a asymmetric cipher: RSA
    -cipher = PKCS1_v1_5.new(key) # Noncompliant
    +PKCS1_OAEP.new(key)
     
    -

    pyca library:

    -
    -import os
    -from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
    +

    How does this work?

    +

    As a rule of thumb, use the cryptographic algorithms and mechanisms that are considered strong by the cryptographic community.

    +

    Appropriate choices are currently the following.

    +

    For AES: Use Galois/Counter mode (GCM)

    +

    GCM mode combines encryption with authentication and integrity checks using a cryptographic hash function and provides both confidentiality and +authenticity of data.

    +

    Other similar modes are:

    +
      +
    • CCM: Counter with CBC-MAC
    • +
    • CWC: Cipher Block Chaining with Message Authentication Code
    • +
    • EAX: Encrypt-and-Authenticate
    • +
    • IAPM: Integer Authenticated Parallelizable Mode
    • +
    • OCB: Offset Codebook Mode
    • +
    +

    It is also possible to use AES-CBC with HMAC for integrity checks. However, it

    +

    is considered more straightforward to use AES-GCM directly instead.

    +

    For RSA: use the OAEP scheme

    +

    The Optimal Asymmetric Encryption Padding scheme (OAEP) adds randomness and a secure hash function that strengthens the regular inner workings of +RSA.

    +

    How to fix it in pyca

    +

    Code examples

    +

    Noncompliant code example

    +

    Example with a symmetric cipher, AES:

    +
    +from cryptography.hazmat.primitives.ciphers import (
    +    Cipher,
    +    algorithms,
    +    modes,
    +)
     from cryptography.hazmat.backends import default_backend
    -from cryptography.hazmat.primitives.asymmetric import rsa, padding
    -from cryptography.hazmat.primitives import hashes
     
    -# Example for a symmetric cipher: AES
    -aes = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())  # Noncompliant
    -aes = Cipher(algorithms.AES(key), modes.ECB(), backend=default_backend())  # Noncompliant
    +Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()) # Noncompliant
    +
    +

    Example with an asymmetric cipher, RSA:

    +
    +from cryptography.hazmat.primitives.asymmetric import (
    +    rsa,
    +    padding,
    +)
     
    -# Example for a asymmetric cipher: RSA
    -ciphertext = public_key.encrypt(
    -  message,
    -  padding.PKCS1v15() # Noncompliant
    +private_key = rsa.generate_private_key(
    +  public_exponent=65537,
    +  key_size=2048,
    +  backend=default_backend()
     )
     
    -plaintext = private_key.decrypt(
    -  ciphertext,
    +public_key = private_key.public_key()
    +
    +public_key.encrypt(
    +  message,
       padding.PKCS1v15() # Noncompliant
     )
     
    -

    pydes library:

    -
    -# For DES cipher
    -des = pyDes.des('ChangeIt') # Noncompliant
    -des = pyDes.des('ChangeIt', pyDes.CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=pyDes.PAD_PKCS5) # Noncompliant
    -des = pyDes.des('ChangeIt', pyDes.ECB, "\0\0\0\0\0\0\0\0", pad=None, padmode=pyDes.PAD_PKCS5) # Noncompliant
    -
    -

    pycrypto library is not maintained and therefore should not be used:

    -
    -# https://pycrypto.readthedocs.io/en/latest/
    -from Crypto.Cipher import *
    -from Crypto.Random import get_random_bytes
    -from Crypto.Util import Counter
    -from Crypto.PublicKey import RSA
    -
    -# Example for a symmetric cipher: AES
    -AES.new(key, AES.MODE_ECB)  # Noncompliant
    -AES.new(key, AES.MODE_CBC, IV=iv)  # Noncompliant
    +

    Compliant solution

    +

    For the AES symmetric cipher, use the GCM mode:

    +
    +from cryptography.hazmat.primitives.ciphers import (
    +    Cipher,
    +    algorithms,
    +    modes,
    +)
    +from cryptography.hazmat.backends import default_backend
     
    -# Example for a asymmetric cipher: RSA
    -cipher = PKCS1_v1_5.new(key) # Noncompliant
    -
    -

    Compliant solution

    -

    pycryptodomex library:

    -
    -from Cryptodome.Cipher import AES
    -from Cryptodome.Random import get_random_bytes
    -from Cryptodome.PublicKey import RSA
    -
    -# AES is the recommended symmetric cipher with GCM mode
    -AES.new(key, AES.MODE_GCM)  # Compliant
    -
    -# RSA is the recommended asymmetric cipher with OAEP padding
    -cipher = PKCS1_OAEP.new(key) # Compliant
    +Cipher(algorithms.AES(key), modes.GCM(iv), backend=default_backend())
     
    -

    pyca library:

    -
    -import os
    -from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
    -from cryptography.hazmat.backends import default_backend
    -from cryptography.hazmat.primitives.asymmetric import rsa, padding
    +
    +from cryptography.hazmat.primitives.asymmetric import (
    +    rsa,
    +    padding,
    +)
     from cryptography.hazmat.primitives import hashes
     
    -# AES is the recommended symmetric cipher with GCM mode
    -aes = Cipher(algorithms.AES(key), modes.GCM(iv), backend=default_backend())  # Compliant
    +private_key = rsa.generate_private_key(
    +  public_exponent=65537,
    +  key_size=2048,
    +  backend=default_backend()
    +)
    +
    +public_key = private_key.public_key()
     
    -# RSA is the recommended asymmetric cipher with OAEP padding
    -ciphertext = public_key.encrypt(
    +public_key.encrypt(
       message,
    -  padding.OAEP( # Compliant
    +  padding.OAEP(
         mgf=padding.MGF1(algorithm=hashes.SHA256()),
         algorithm=hashes.SHA256(),
         label=None
       )
     )
    +
    +

    How does this work?

    +

    As a rule of thumb, use the cryptographic algorithms and mechanisms that are considered strong by the cryptographic community.

    +

    Appropriate choices are currently the following.

    +

    For AES: Use Galois/Counter mode (GCM)

    +

    GCM mode combines encryption with authentication and integrity checks using a cryptographic hash function and provides both confidentiality and +authenticity of data.

    +

    Other similar modes are:

    +
      +
    • CCM: Counter with CBC-MAC
    • +
    • CWC: Cipher Block Chaining with Message Authentication Code
    • +
    • EAX: Encrypt-and-Authenticate
    • +
    • IAPM: Integer Authenticated Parallelizable Mode
    • +
    • OCB: Offset Codebook Mode
    • +
    +

    It is also possible to use AES-CBC with HMAC for integrity checks. However, it

    +

    is considered more straightforward to use AES-GCM directly instead.

    +

    For RSA: use the OAEP scheme

    +

    The Optimal Asymmetric Encryption Padding scheme (OAEP) adds randomness and a secure hash function that strengthens the regular inner workings of +RSA.

    +

    How to fix it in Cryptodome

    +

    Code examples

    +

    Noncompliant code example

    +

    Example with a symmetric cipher, AES:

    +
    +from Crypto.Cipher import AES     # pycryptodome
    +from Cryptodome.Cipher import AES # pycryptodomex
     
    -plaintext = private_key.decrypt(
    -  ciphertext,
    -  padding.OAEP( # Compliant
    -    mgf=padding.MGF1(algorithm=hashes.SHA256()),
    -    algorithm=hashes.SHA256(),
    -    label=None
    -  )
    +AES.new(key, AES.MODE_ECB)  # Noncompliant
    +
    +

    Example with an asymmetric cipher, RSA:

    +
    +from Crypto.Cipher import PKCS1_V1_5     # pycryptodome
    +from Cryptodome.Cipher import PKCS1_V1_5 # pycryptodomex
    +
    +PKCS1_v1_5.new(key) # Noncompliant
    +
    +

    Compliant solution

    +

    For the AES symmetric cipher, use the GCM mode:

    +
    +from Crypto.Cipher import AES     # pycryptodome
    +from Cryptodome.Cipher import AES # pycryptodomex
    +
    +AES.new(key, AES.MODE_GCM)
    +
    +

    For the RSA asymmetric cipher, use the Optimal Asymmetric Encryption Padding (OAEP):

    +
    +from Crypto.Cipher import PKCS1_V1_5     # pycryptodome
    +from Cryptodome.Cipher import PKCS1_V1_5 # pycryptodomex
    +
    +PKCS1_OAEP.new(key)
    +
    +

    How does this work?

    +

    As a rule of thumb, use the cryptographic algorithms and mechanisms that are considered strong by the cryptographic community.

    +

    Appropriate choices are currently the following.

    +

    For AES: Use Galois/Counter mode (GCM)

    +

    GCM mode combines encryption with authentication and integrity checks using a cryptographic hash function and provides both confidentiality and +authenticity of data.

    +

    Other similar modes are:

    +
      +
    • CCM: Counter with CBC-MAC
    • +
    • CWC: Cipher Block Chaining with Message Authentication Code
    • +
    • EAX: Encrypt-and-Authenticate
    • +
    • IAPM: Integer Authenticated Parallelizable Mode
    • +
    • OCB: Offset Codebook Mode
    • +
    +

    It is also possible to use AES-CBC with HMAC for integrity checks. However, it

    +

    is considered more straightforward to use AES-GCM directly instead.

    +

    For RSA: use the OAEP scheme

    +

    The Optimal Asymmetric Encryption Padding scheme (OAEP) adds randomness and a secure hash function that strengthens the regular inner workings of +RSA.

    +

    How to fix it in pyDes

    +

    Code examples

    +

    Noncompliant code example

    +
    +import pyDes
    +
    +pyDes.des(key) # Noncompliant
    +
    +

    Compliant solution

    +

    Since pyDes only provides DES, it is recommended to use another library like pyca.

    +
    +from cryptography.hazmat.primitives.ciphers import (
    +    Cipher,
    +    algorithms,
    +    modes,
     )
    +from cryptography.hazmat.backends import default_backend
    +
    +Cipher(algorithms.AES(key), modes.GCM(iv), backend=default_backend())
     
    +

    How does this work?

    +

    As a rule of thumb, use the cryptographic algorithms and mechanisms that are considered strong by the cryptographic community.

    +

    Appropriate choices are currently the following.

    +

    For AES: Use Galois/Counter mode (GCM)

    +

    GCM mode combines encryption with authentication and integrity checks using a cryptographic hash function and provides both confidentiality and +authenticity of data.

    +

    Other similar modes are:

    +
      +
    • CCM: Counter with CBC-MAC
    • +
    • CWC: Cipher Block Chaining with Message Authentication Code
    • +
    • EAX: Encrypt-and-Authenticate
    • +
    • IAPM: Integer Authenticated Parallelizable Mode
    • +
    • OCB: Offset Codebook Mode
    • +
    +

    It is also possible to use AES-CBC with HMAC for integrity checks. However, it

    +

    is considered more straightforward to use AES-GCM directly instead.

    +

    For RSA: use the OAEP scheme

    +

    The Optimal Asymmetric Encryption Padding scheme (OAEP) adds randomness and a secure hash function that strengthens the regular inner workings of +RSA.

    Resources

    +

    Articles & blog posts

    + +

    Standards

    • OWASP Top 10 2021 Category A2 - Cryptographic Failures
    • OWASP Top 10 2017 Category A6 - Security diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5547.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5547.html index 7bc0811e24..0fbb173d62 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5547.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5547.html @@ -1,115 +1,118 @@ +

      This vulnerability makes it possible that the cleartext of the encrypted message might be recoverable without prior knowledge of the key.

      Why is this an issue?

      -

      Strong cipher algorithms are cryptographic systems resistant to cryptanalysis, they -are not vulnerable to well-known attacks like brute force attacks for example.

      -

      A general recommendation is to only use cipher algorithms intensively tested and promoted by the cryptographic community.

      -

      More specifically for block cipher, it’s not recommended to use algorithm with a block size inferior than 128 bits.

      -

      Noncompliant code example

      -

      pycryptodomex library:

      -
      -from Cryptodome.Cipher import DES, DES3, ARC2, ARC4, Blowfish, AES
      -from Cryptodome.Random import get_random_bytes
      -
      -key = b'-8B key-'
      -DES.new(key, DES.MODE_OFB) # Noncompliant: DES works with 56-bit keys allow attacks via exhaustive search
      -
      -key = DES3.adjust_key_parity(get_random_bytes(24))
      -cipher = DES3.new(key, DES3.MODE_CFB) # Noncompliant: Triple DES is vulnerable to meet-in-the-middle attack
      -
      -key = b'Sixteen byte key'
      -cipher = ARC2.new(key, ARC2.MODE_CFB) # Noncompliant: RC2 is vulnerable to a related-key attack
      -
      -key = b'Very long and confidential key'
      -cipher = ARC4.new(key) # Noncompliant: vulnerable to several attacks (see https://en.wikipedia.org/wiki/RC4#Security)
      -
      -key = b'An arbitrarily long key'
      -cipher = Blowfish.new(key, Blowfish.MODE_CBC) # Noncompliant: Blowfish use a 64-bit block size makes it vulnerable to birthday attacks
      +

      Encryption algorithms are essential for protecting sensitive information and ensuring secure communication in various domains. They are used for +several important reasons:

      +
        +
      • Confidentiality, privacy, and intellectual property protection.
      • +
      • Security during transmission or on storage devices.
      • +
      • Data integrity, general trust, and authentication.
      • +
      +

      When selecting encryption algorithms, tools, or combinations, you should also consider two things:

      +
        +
      1. No encryption is unbreakable.
      2. +
      3. The strength of an encryption algorithm is usually measured by the effort required to crack it within a reasonable time frame.
      4. +
      +

      For these reasons, as soon as cryptography is included in a project, it is important to choose encryption algorithms that are considered strong and +secure by the cryptography community.

      +

      What is the potential impact?

      +

      The cleartext of an encrypted message might be recoverable. Additionally, it might be possible to modify the cleartext of an encrypted message.

      +

      Below are some real-world scenarios that illustrate some impacts of an attacker exploiting the vulnerability.

      +

      Theft of sensitive data

      +

      The encrypted message might contain data that is considered sensitive and should not be known to third parties.

      +

      By using a weak algorithm the likelihood that an attacker might be able to recover the cleartext drastically increases.

      +

      Additional attack surface

      +

      By modifying the cleartext of the encrypted message it might be possible for an attacker to trigger other vulnerabilities in the code. Encrypted +values are often considered trusted, since under normal circumstances it would not be possible for a third party to modify them.

      +

      How to fix it in Cryptodome

      +

      Code examples

      +

      The following code contains examples of algorithms that are not considered highly resistant to cryptanalysis and thus should be avoided.

      +

      Noncompliant code example

      +
      +from Crypto.Cipher import DES # pycryptodome
      +from Cryptodome.Cipher import DES # pycryptodomex
      +
      +cipher = DES.new(key, DES.MODE_OFB) # Noncompliant
       
      -

      pycryptodome library:

      -
      -from Crypto.Cipher import DES, DES3, ARC2, ARC4, Blowfish, AES
      -from Crypto.Random import get_random_bytes
      -
      -key = b'-8B key-'
      -DES.new(key, DES.MODE_OFB) # Noncompliant: DES works with 56-bit keys allow attacks via exhaustive search
      -
      -key = DES3.adjust_key_parity(get_random_bytes(24))
      -cipher = DES3.new(key, DES3.MODE_CFB) # Noncompliant: Triple DES is vulnerable to meet-in-the-middle attack
      +

      Compliant solution

      +
      +from Crypto.Cipher import AES # pycryptodome
      +from Cryptodome.Cipher import AES # pycryptodomex
       
      -key = b'Sixteen byte key'
      -cipher = ARC2.new(key, ARC2.MODE_CFB) # Noncompliant: RC2 is vulnerable to a related-key attack
      -
      -key = b'Very long and confidential key'
      -cipher = ARC4.new(key) # Noncompliant: vulnerable to several attacks (see https://en.wikipedia.org/wiki/RC4#Security)
      -
      -key = b'An arbitrarily long key'
      -cipher = Blowfish.new(key, Blowfish.MODE_CBC) # Noncompliant: Blowfish use a 64-bit block size makes it vulnerable to birthday attacks
      +cipher = AES.new(key, AES.MODE_CCM)
       
      -

      pyca library:

      -
      -import os
      -from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
      +

      How does this work?

      +

      Use a secure algorithm

      +

      It is highly recommended to use an algorithm that is currently considered secure by the cryptographic community. A common choice for such an +algorithm is the Advanced Encryption Standard (AES).

      +

      For block ciphers, it is not recommended to use algorithms with a block size that is smaller than 128 bits.

      +

      How to fix it in pyca

      +

      Code examples

      +

      The following code contains examples of algorithms that are not considered highly resistant to cryptanalysis and thus should be avoided.

      +

      Noncompliant code example

      +
      +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms
       from cryptography.hazmat.backends import default_backend
       
      -key = os.urandom(16)
      -iv = os.urandom(16)
      -
      -tdes4 = Cipher(algorithms.TripleDES(key), mode=None, backend=default_backend()) # Noncompliant: Triple DES is vulnerable to meet-in-the-middle attack
      -bf3 = Cipher(algorithms.Blowfish(key), mode=None, backend=default_backend()) # Noncompliant: Blowfish use a 64-bit block size makes it vulnerable to birthday attacks
      -rc42 = Cipher(algorithms.ARC4(key), mode=None, backend=default_backend()) # Noncompliant: vulnerable to several attacks (see https://en.wikipedia.org/wiki/RC4#Security)
      +cipher = Cipher(algorithms.TripleDES(key), mode=None, backend=default_backend()) # Noncompliant
       
      -

      pydes library:

      -
      -import pyDes;
      -
      -des1 = pyDes.des('ChangeIt')  # Noncompliant: DES works with 56-bit keys allow attacks via exhaustive search
      -des2 = pyDes.des('ChangeIt', pyDes.CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=pyDes.PAD_PKCS5) # Noncompliant: DES works with 56-bit keys allow attacks via exhaustive search
      +

      Compliant solution

      +
      +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
      +from cryptography.hazmat.backends import default_backend
       
      -tdes1 = pyDes.triple_des('ChangeItWithYourKey!!!!!')  # Noncompliant: Triple DES is vulnerable to meet-in-the-middle attack
      -tdes2 = pyDes.triple_des('ChangeItWithYourKey!!!!!', pyDes.CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=pyDes.PAD_PKCS5) # Noncompliant: Triple DES is vulnerable to meet-in-the-middle attack
      +cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
       
      -

      pycrypto library is not maintained and therefore should not be used:

      -
      -from Crypto.Cipher import *
      -
      -des3 = DES.new('ChangeIt') # Noncompliant: DES works with 56-bit keys allow attacks via exhaustive search
      -tdes3 = DES3.new('ChangeItChangeIt') # Noncompliant: Triple DES is vulnerable to meet-in-the-middle attack
      -bf2 = Blowfish.new('ChangeItWithYourKey', Blowfish.MODE_CBC, 'ChangeIt') # Noncompliant: Blowfish use a 64-bit block size makes it
      -rc21 = ARC2.new('ChangeItWithYourKey', ARC2.MODE_CFB, 'ChangeIt') # Noncompliant: RC2 is vulnerable to a related-key attack
      -rc41 = ARC4.new('ChangeItWithYourKey') # Noncompliant: vulnerable to several attacks (see https://en.wikipedia.org/wiki/RC4#Security)
      +

      How does this work?

      +

      Use a secure algorithm

      +

      It is highly recommended to use an algorithm that is currently considered secure by the cryptographic community. A common choice for such an +algorithm is the Advanced Encryption Standard (AES).

      +

      For block ciphers, it is not recommended to use algorithms with a block size that is smaller than 128 bits.

      +

      How to fix it in PyCrypto

      +

      Code examples

      +

      The following code contains examples of algorithms that are not considered highly resistant to cryptanalysis and thus should be avoided.

      +

      Noncompliant code example

      +
      +from Crypto.Cipher import DES
      +
      +cipher = DES.new(key) # Noncompliant
       
      -

      Compliant solution

      -

      pycryptodomex library:

      -
      -from Cryptodome.Cipher import AES
      +

      Compliant solution

      +

      PyCrypto is deprecated, thus it is recommended to use another library like pyca.

      +
      +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
      +from cryptography.hazmat.backends import default_backend
       
      -key = b'Sixteen byte key'
      -cipher = AES.new(key, AES.MODE_CCM) # Compliant
      +cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
       
      -

      pycryptodome library:

      -
      -from Crypto.Cipher import AES
      -
      -key = b'Sixteen byte key'
      -cipher = AES.new(key, AES.MODE_CCM) # Compliant
      +

      How does this work?

      +

      Use a secure algorithm

      +

      It is highly recommended to use an algorithm that is currently considered secure by the cryptographic community. A common choice for such an +algorithm is the Advanced Encryption Standard (AES).

      +

      For block ciphers, it is not recommended to use algorithms with a block size that is smaller than 128 bits.

      +

      How to fix it in pyDes

      +

      Code examples

      +

      The following code contains examples of algorithms that are not considered highly resistant to cryptanalysis and thus should be avoided.

      +

      Noncompliant code example

      +
      +import pyDes
      +
      +cipher = pyDes.des(key) # Noncompliant
       
      -

      pyca library:

      -
      -import os
      +

      Compliant solution

      +

      Since pyDes only provides DES, it is recommended to use another library like pyca.

      +
       from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
       from cryptography.hazmat.backends import default_backend
       
      -key = os.urandom(16)
      -iv = os.urandom(16)
      -
      -aes2 = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()) # Compliant
      -
      -

      pycrypto library is not maintained and therefore should not be used:

      -
      -from Crypto.Cipher import *
      -
      -aes1 = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456') # Compliant
      +cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
       
      +

      How does this work?

      +

      Use a secure algorithm

      +

      It is highly recommended to use an algorithm that is currently considered secure by the cryptographic community. A common choice for such an +algorithm is the Advanced Encryption Standard (AES).

      +

      For block ciphers, it is not recommended to use algorithms with a block size that is smaller than 128 bits.

      Resources

      +

      Standards

      • OWASP Top 10 2021 Category A2 - Cryptographic Failures
      • OWASP Top 10 2017 Category A3 - Sensitive Data diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6321.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6321.html index a9d28bf2bf..87405f4c64 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6321.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6321.html @@ -2,14 +2,20 @@

        Why is this an issue?

        Cloud platforms such as AWS, Azure, or GCP support virtual firewalls that can be used to restrict access to services by controlling inbound and outbound traffic.
        Any firewall rule allowing traffic from all IP addresses to standard network ports on which administration services traditionally listen, such as 22 for SSH, can expose these services to exploits and unauthorized access.

        -

        Recommended Secure Coding Practices

        -

        It’s recommended to restrict access to remote administration services to only trusted IP addresses. In practice, trusted IP addresses are those +

        What is the potential impact?

        +

        Like any other service, administration services can contain vulnerabilities. Administration services run with elevated privileges and thus a +vulnerability could have a high impact on the system.

        +

        Additionally, credentials might be leaked through phishing or similar techniques. Attackers who are able to reach the services could use the +credentials to log in to the system.

        +

        How to fix it

        +

        It is recommended to restrict access to remote administration services to only trusted IP addresses. In practice, trusted IP addresses are those held by system administrators or those of bastion-like servers.

        -

        Noncompliant code example

        +

        Code examples

        +

        Noncompliant code example

        For aws_cdk.aws_ec2.Instance and other constructs that support a connections attribute:

        -
        +
         from aws_cdk import aws_ec2 as ec2
         
         instance = ec2.Instance(
        @@ -31,7 +37,7 @@ 

        Noncompliant code example

        )

        For aws_cdk.aws_ec2.SecurityGroup

        -
        +
         from aws_cdk import aws_ec2 as ec2
         security_group = ec2.SecurityGroup(
             self,
        @@ -45,7 +51,7 @@ 

        Noncompliant code example

        )

        For aws_cdk.aws_ec2.CfnSecurityGroup

        -
        +
         from aws_cdk import aws_ec2 as ec2
         
         ec2.CfnSecurityGroup(
        @@ -76,7 +82,7 @@ 

        Noncompliant code example

        For aws_cdk.aws_ec2.CfnSecurityGroupIngress

        -
        +
         from aws_cdk import aws_ec2 as ec2
         
         ec2.CfnSecurityGroupIngress( # Noncompliant
        @@ -97,10 +103,10 @@ 

        Noncompliant code example

        group_id=security_group.attr_group_id )
        -

        Compliant solution

        +

        Compliant solution

        For aws_cdk.aws_ec2.Instance and other constructs that support a connections attribute:

        -
        +
         from aws_cdk import aws_ec2 as ec2
         
         instance = ec2.Instance(
        @@ -123,7 +129,7 @@ 

        Compliant solution

        )

        For aws_cdk.aws_ec2.SecurityGroup

        -
        +
         from aws_cdk import aws_ec2 as ec2
         security_group = ec2.SecurityGroup(
             self,
        @@ -137,7 +143,7 @@ 

        Compliant solution

        )

        For aws_cdk.aws_ec2.CfnSecurityGroup

        -
        +
         from aws_cdk import aws_ec2 as ec2
         
         ec2.CfnSecurityGroup(
        @@ -164,7 +170,7 @@ 

        Compliant solution

        For aws_cdk.aws_ec2.CfnSecurityGroupIngress

        -
        +
         from aws_cdk import aws_ec2 as ec2
         
         ec2.CfnSecurityGroupIngress(
        @@ -188,14 +194,18 @@ 

        Compliant solution

        )

        Resources

        +

        Documentation

        +

        Standards

        + diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6326.json b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6326.json index 0bb12f5315..c13873d389 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6326.json +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6326.json @@ -13,5 +13,5 @@ "ruleSpecification": "RSPEC-6326", "sqKey": "S6326", "scope": "Main", - "quickfix": "targeted" + "quickfix": "covered" } diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6397.json b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6397.json index 668396efe5..c0f84a62a5 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6397.json +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6397.json @@ -13,5 +13,5 @@ "ruleSpecification": "RSPEC-6397", "sqKey": "S6397", "scope": "All", - "quickfix": "targeted" + "quickfix": "covered" } diff --git a/sonarpedia.json b/sonarpedia.json index 08ffd2de32..c240104574 100644 --- a/sonarpedia.json +++ b/sonarpedia.json @@ -3,7 +3,7 @@ "languages": [ "PY" ], - "latest-update": "2023-05-08T08:44:25.683797701Z", + "latest-update": "2023-06-20T13:03:06.140648Z", "options": { "no-language-in-filenames": true, "preserve-filenames": true