Troubleshooting of Sonar issue: Difference between revisions

From LemonWiki共筆
Jump to navigation Jump to search
Tags: Mobile edit Mobile web edit
 
(14 intermediate revisions by the same user not shown)
Line 1: Line 1:
Troubleshooting of SonarQube issue


{{Draft}}
{{Tip | tip='''What is SonarQube?''' SonarQube is an open-source platform for continuous code quality inspection using static program analysis to detect bugs and code smells across multiple programming languages. It provides automated analysis reports and integrates seamlessly with various development tools. (Source: [https://en.wikipedia.org/wiki/SonarQube Wikipedia])}}


== How to resolve "Add a new line at the end of this file." ==
== SonarQube issues ==
=== How to resolve "Add a new line at the end of this file." ===
Error message: Files should contain an empty newline at the end<ref>[https://gist.github.com/OleksiyRudenko/d51388345ea55767b7672307fe35adf3 Why should text files end with a newline?]</ref>
Error message: Files should contain an empty newline at the end<ref>[https://gist.github.com/OleksiyRudenko/d51388345ea55767b7672307fe35adf3 Why should text files end with a newline?]</ref>


Line 21: Line 23:
# Retrieve the directory path argument
# Retrieve the directory path argument
dir_path="$1"
dir_path="$1"
# Initialize a counter for modified files
modified_count=0


# Iterate through all .php files in the specified directory
# Iterate through all .php files in the specified directory
Line 33: Line 38:
             # If it's not empty, append a newline character
             # If it's not empty, append a newline character
             echo "" >> "$file"
             echo "" >> "$file"
            # Increment the modified files counter
            ((modified_count++))
         fi
         fi
     fi
     fi
done
done
# Display the number of modified files
echo "Number of modified files: $modified_count"




Line 43: Line 54:
* Usage {{kbd | key=<nowiki>./add_newline_to_php_files.sh /path/to/php/directory_of_scripts</nowiki>}}
* Usage {{kbd | key=<nowiki>./add_newline_to_php_files.sh /path/to/php/directory_of_scripts</nowiki>}}


== How to resolve "Define and throw a dedicated exception instead of using a generic one" ==
 
=== How to resolve "Define a constant instead of duplicating this literal" ===
 
Error condition which met "Define a constant instead of duplicating this literal" - violates DRY (Don't Repeat Yourself) principle and creates maintenance issues <ref>[Clean Code principles - Avoid Magic Numbers/Strings]</ref>
 
Original problematic code (Python):
<pre>
def parse_date(row):
    if isinstance(row['time_field'], pd.Timestamp):
        formatted_date = row['time_field'].strftime("%Y-%m")
    elif isinstance(row['time_field'], str):
        date_obj = datetime.strptime(row['time_field'], "%Y-%m-%d %H:%M:%S")
        formatted_date = date_obj.strftime("%Y-%m")
    elif isinstance(row['time_field'], datetime):
        formatted_date = row['time_field'].strftime("%Y-%m")
</pre>
 
Possible solution: define the constants
<pre>
# Date format constants
DATE_FORMAT_YEAR_MONTH = "%Y-%m"
 
def parse_date(row):
    if isinstance(row['time_field'], pd.Timestamp):
        formatted_date = row['time_field'].strftime(DATE_FORMAT_YEAR_MONTH)
    elif isinstance(row['time_field'], str):
        date_obj = datetime.strptime(row['time_field'], "%Y-%m-%d %H:%M:%S")
        formatted_date = date_obj.strftime(DATE_FORMAT_YEAR_MONTH)
    elif isinstance(row['time_field'], datetime):
        formatted_date = row['time_field'].strftime(DATE_FORMAT_YEAR_MONTH)
</pre>
 
Benefits:
# Maintainability: Format strings can be updated in one central location
# Consistency: All date formatting uses the same format definitions
# Error Prevention: Reduces risk of typos in repeated string literals
 
=== How to resolve "Define and throw a dedicated exception instead of using a generic one" ===


Error condition which met "Define and throw a dedicated exception instead of using a generic one" <ref>[https://cwe.mitre.org/data/definitions/397 CWE - CWE-397: Declaration of Throws for Generic Exception (4.12)]</ref>
Error condition which met "Define and throw a dedicated exception instead of using a generic one" <ref>[https://cwe.mitre.org/data/definitions/397 CWE - CWE-397: Declaration of Throws for Generic Exception (4.12)]</ref>
Line 61: Line 109:
</pre>
</pre>


== How to resolve "replace all tab characters in this file by sequences of white-spaces (Tabulation characters should not be used)" ==
=== How to resolve "Merge this if statement with the enclosing one." ===
Example of Code Not Meeting Standards
<pre>
if (isTrueCondition1) {
  if (isTrueCondition2) {
    ...
  }
}
</pre>
 
Example of Code Meeting Standards
<pre>
if (isTrueCondition1 && isTrueCondition2) {
  ...
}
</pre>
 
Example of Code Not Meeting Standards
<pre>
if (isTrueCondition1) {
  if (isTrueCondition2) {
    ...
  }
 
  if (isTrueCondition3) {
    ...
  }
}
</pre>
 
Example of Code Meeting Standards
<pre>
if (isTrueCondition1 && isTrueCondition2) {
    ...
}
 
if (isTrueCondition1 && isTrueCondition3) {
    ...
}
</pre>
 
=== How to resolve "Method visibility should be explicitly declared" ===
 
Possible solution
 
* Use a text editor that supports [[Regular expression | regular expressions]]
* Find: {{kbd | key=<nowiki>^(\s+)(function)(\s)</nowiki>}}
* Replace with: {{kbd | key=<nowiki>$1public function$3</nowiki>}}
 
=== How to resolve "replace all tab characters in this file by sequences of white-spaces (Tabulation characters should not be used)" ===
Solution: Using the editor which supports [[Regular expression | regular expression]]<ref>[https://community.sonarsource.com/t/replace-all-tab-characters-in-this-file-by-sequences-of-white-spaces-error-in-sonarcloud-t-sql/40078 Replace all tab characters in this file by sequences of white-spaces - Error in SonarCloud T-SQL - SonarCloud - Sonar Community]</ref>
Solution: Using the editor which supports [[Regular expression | regular expression]]<ref>[https://community.sonarsource.com/t/replace-all-tab-characters-in-this-file-by-sequences-of-white-spaces-error-in-sonarcloud-t-sql/40078 Replace all tab characters in this file by sequences of white-spaces - Error in SonarCloud T-SQL - SonarCloud - Sonar Community]</ref>
* Replace {{kbd | key=<nowiki>\t</nowiki>}}
* Replace {{kbd | key=<nowiki>\t</nowiki>}}
* with {{kbd | key=<nowiki>    </nowiki>}} (four whitespaces)
* with {{kbd | key=<nowiki>    </nowiki>}} (four whitespaces)


== How to resolve "Refactor this function to reduce its Cognitive Complexity from 17 to the 15 allowed." ==
=== How to resolve "Refactor this function to reduce its Cognitive Complexity from XX to the 15 allowed." ===
 
Possible solution<ref>[https://www.compozelabs.com/post/avoiding-and-fix-spaghetti-code How to fix your spaghetti code (and avoid it in the first place) | Compoze Labs]</ref><ref>[https://en.wikipedia.org/wiki/Spaghetti_code Spaghetti code - Wikipedia]</ref>
* Created smaller, more specific functions (following [https://en.wikipedia.org/wiki/Single-responsibility_principle Single Responsibility Principle]) to handle specific parts of the logic. Use these secondary  functions to make the main function easier to read and understand.
* Avoid nested conditionals
* Simplify boolean expressions
 
=== How to resolve "This image might run with root as the default user. Make sure it is safe here." ===
 
'''🛑 Problem Condition'''
 
During the CI/CD process, security scanning tools such as Anchore or Checkmarx report the following warning:
 
<pre>
This image might run with root as the default user. Make sure it is safe here.
</pre>
 
This warning appears because the Docker image is configured to run as the <code>root</code> user by default, which poses a potential security risk—especially in production or publicly exposed environments.
 
'''✅ Solution'''
 
Modify the <code>Dockerfile</code> to create a non-root user and configure the container to run using this user. Here's a general example:
 
<pre>
FROM alpine:3.19
 
# Create a non-root user and group =
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
 
# Create the working directory and set permissions =
RUN mkdir -p /app && chown -R appuser:appgroup /app
 
# Copy application files =
COPY app /app
WORKDIR /app
 
# Switch to the non-root user =
USER appuser
 
# Expose application port (if applicable) =
EXPOSE 80
 
# Start your application (example only) =
CMD ["your-app-command"]
</pre>
 
'''💡 Explanation'''


Possible solution
By default, Docker containers run as the "root" user, which increases the risk of privilege escalation if an attacker exploits a vulnerability. To  avoid the risk by creating a dedicated, unprivileged user and ensuring that your application directory has the correct ownership and permissions. Then, you configure the container to run under this non-root user.
* Created smaller, more specific functions (following [https://en.wikipedia.org/wiki/Single-responsibility_principle Single Responsibility Principle]) to handle specific parts of the logic.
 
* Use these functions to make the main function easier to read and understand.
 
References
* [https://www.docker.com/blog/understanding-the-docker-user-instruction/ Understanding the Docker USER Instruction | Docker]
* [https://docs.docker.com/engine/security/rootless/ Rootless mode | Docker Docs]
* [https://medium.com/@Kfir-G/securing-docker-non-root-user-best-practices-5784ac25e755 Securing Docker: Non-Root User Best Practices | by Kfir Gisman | Medium]
 
=== Unresolved issues ===
* SonarLint: Replace "require_once" with namespace import mechanism through the "use" keyword.


== Further reading ==
== Further reading ==
Line 85: Line 235:


[[Category: Programming]]
[[Category: Programming]]
[[Category: PHP]]
[[Category: Security]]
[[Category: Security]]
[[Category: Revised with LLMs]]

Latest revision as of 22:47, 28 May 2025

Troubleshooting of SonarQube issue

Owl icon.jpg What is SonarQube? SonarQube is an open-source platform for continuous code quality inspection using static program analysis to detect bugs and code smells across multiple programming languages. It provides automated analysis reports and integrates seamlessly with various development tools. (Source: Wikipedia)

SonarQube issues[edit]

How to resolve "Add a new line at the end of this file."[edit]

Error message: Files should contain an empty newline at the end[1]

Solution:

Another solution:

  • Add an new file add_newline_to_php_files.sh with the following content
#!/bin/bash

# Check if a directory path argument has been provided
if [ "$#" -ne 1 ]; then
    echo "Usage: ./add_newline_to_php_files.sh [Directory Path]"
    exit 1
fi

# Retrieve the directory path argument
dir_path="$1"

# Initialize a counter for modified files
modified_count=0

# Iterate through all .php files in the specified directory
for file in "$dir_path"/*.php; do
    # Check if the file exists
    if [ -f "$file" ]; then
        # Read the last line of the file
        last_line=$(tail -n 1 "$file")
        
        # Check if the last line is empty
        if [ "$last_line" != "" ]; then
            # If it's not empty, append a newline character
            echo "" >> "$file"
            # Increment the modified files counter
            ((modified_count++))
        fi
    fi
done

# Display the number of modified files
echo "Number of modified files: $modified_count"



  • Grant the execution permission chmod +x add_newline_to_php_files.sh
  • Usage ./add_newline_to_php_files.sh /path/to/php/directory_of_scripts


How to resolve "Define a constant instead of duplicating this literal"[edit]

Error condition which met "Define a constant instead of duplicating this literal" - violates DRY (Don't Repeat Yourself) principle and creates maintenance issues [2]

Original problematic code (Python):

def parse_date(row):
    if isinstance(row['time_field'], pd.Timestamp):
        formatted_date = row['time_field'].strftime("%Y-%m")
    elif isinstance(row['time_field'], str):
        date_obj = datetime.strptime(row['time_field'], "%Y-%m-%d %H:%M:%S")
        formatted_date = date_obj.strftime("%Y-%m")
    elif isinstance(row['time_field'], datetime):
        formatted_date = row['time_field'].strftime("%Y-%m")

Possible solution: define the constants

# Date format constants
DATE_FORMAT_YEAR_MONTH = "%Y-%m"

def parse_date(row):
    if isinstance(row['time_field'], pd.Timestamp):
        formatted_date = row['time_field'].strftime(DATE_FORMAT_YEAR_MONTH)
    elif isinstance(row['time_field'], str):
        date_obj = datetime.strptime(row['time_field'], "%Y-%m-%d %H:%M:%S")
        formatted_date = date_obj.strftime(DATE_FORMAT_YEAR_MONTH)
    elif isinstance(row['time_field'], datetime):
        formatted_date = row['time_field'].strftime(DATE_FORMAT_YEAR_MONTH)

Benefits:

  1. Maintainability: Format strings can be updated in one central location
  2. Consistency: All date formatting uses the same format definitions
  3. Error Prevention: Reduces risk of typos in repeated string literals

How to resolve "Define and throw a dedicated exception instead of using a generic one"[edit]

Error condition which met "Define and throw a dedicated exception instead of using a generic one" [3]

if(is_null($some_variable)){
            $error = 'The variable $some_variable is not defined.';
            throw new Exception($error);
        }

Possible solution

if(!is_null($some_variable)){
            $error = 'The variable $some_variable is not defined.';
            throw new InvalidArgumentException($error);
        }

How to resolve "Merge this if statement with the enclosing one."[edit]

Example of Code Not Meeting Standards

if (isTrueCondition1) {
  if (isTrueCondition2) {
    ...
  }
}

Example of Code Meeting Standards

if (isTrueCondition1 && isTrueCondition2) {
  ...
}

Example of Code Not Meeting Standards

if (isTrueCondition1) {
  if (isTrueCondition2) {
    ...
  }

  if (isTrueCondition3) {
    ...
  }
}

Example of Code Meeting Standards

if (isTrueCondition1 && isTrueCondition2) {
    ...
}

if (isTrueCondition1 && isTrueCondition3) {
    ...
}

How to resolve "Method visibility should be explicitly declared"[edit]

Possible solution

  • Use a text editor that supports regular expressions
  • Find: ^(\s+)(function)(\s)
  • Replace with: $1public function$3

How to resolve "replace all tab characters in this file by sequences of white-spaces (Tabulation characters should not be used)"[edit]

Solution: Using the editor which supports regular expression[4]

  • Replace \t
  • with (four whitespaces)

How to resolve "Refactor this function to reduce its Cognitive Complexity from XX to the 15 allowed."[edit]

Possible solution[5][6]

  • Created smaller, more specific functions (following Single Responsibility Principle) to handle specific parts of the logic. Use these secondary functions to make the main function easier to read and understand.
  • Avoid nested conditionals
  • Simplify boolean expressions

How to resolve "This image might run with root as the default user. Make sure it is safe here."[edit]

🛑 Problem Condition

During the CI/CD process, security scanning tools such as Anchore or Checkmarx report the following warning:

This image might run with root as the default user. Make sure it is safe here.

This warning appears because the Docker image is configured to run as the root user by default, which poses a potential security risk—especially in production or publicly exposed environments.

✅ Solution

Modify the Dockerfile to create a non-root user and configure the container to run using this user. Here's a general example:

FROM alpine:3.19

# Create a non-root user and group =
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# Create the working directory and set permissions =
RUN mkdir -p /app && chown -R appuser:appgroup /app

# Copy application files =
COPY app /app
WORKDIR /app

# Switch to the non-root user =
USER appuser

# Expose application port (if applicable) =
EXPOSE 80

# Start your application (example only) =
CMD ["your-app-command"]

💡 Explanation

By default, Docker containers run as the "root" user, which increases the risk of privilege escalation if an attacker exploits a vulnerability. To avoid the risk by creating a dedicated, unprivileged user and ensuring that your application directory has the correct ownership and permissions. Then, you configure the container to run under this non-root user.


References

Unresolved issues[edit]

  • SonarLint: Replace "require_once" with namespace import mechanism through the "use" keyword.

Further reading[edit]

References[edit]