Skip to content

Add YAML security rules and tests for ldap3 and MariaDB #179

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 24, 2025

Conversation

ESS-ENN
Copy link
Collaborator

@ESS-ENN ESS-ENN commented Mar 24, 2025

Summary by CodeRabbit

  • New Features

    • Introduced security enhancements to identify insecure password configurations in Python applications using LDAP and MariaDB, helping ensure proper credential management.
  • Tests

    • Added comprehensive test scenarios and snapshot validations to confirm the effectiveness of these security rules.

Copy link

coderabbitai bot commented Mar 24, 2025

Walkthrough

This pull request introduces several new YAML files that define security rules for Python applications using the ldap3 and MariaDB libraries. The rules detect cases where a connection is established with either an empty password or a hardcoded secret. In addition, corresponding snapshot files and test cases are added to validate the functionality of these rules. The changes include pattern matching using AST analysis and reference CWE guidelines and OWASP best practices for secrets management.

Changes

File(s) Change Summary
rules/python/security/python-ldap3-empty-password-python.yml,
rules/python/security/python-ldap3-hardcoded-secret-python.yml
Introduced security rules to detect empty passwords and hardcoded secrets in ldap3.Connection calls, including pattern matching, severity warnings, and references to CWE-287, CWE-798 and OWASP guidelines.
rules/python/security/python-mariadb-empty-password-python.yml,
rules/python/security/python-mariadb-hardcoded-secret-python.yml
Added rules to flag empty passwords and hardcoded secrets in MariaDB connection calls, using AST analysis with utility patterns and security guideline references.
tests/__snapshots__/python-ldap3-empty-password-python-snapshot.yml,
tests/__snapshots__/python-ldap3-hardcoded-secret-python-snapshot.yml
Added snapshots demonstrating how ldap3.Connection handles empty and hardcoded password cases, complete with labeled segments for clarity.
tests/__snapshots__/python-mariadb-empty-password-python-snapshot.yml,
tests/__snapshots__/python-mariadb-hardcoded-secret-python-snapshot.yml
Provided snapshot tests covering multiple scenarios for MariaDB connection calls involving empty and hardcoded passwords.
tests/python/python-ldap3-empty-password-python-test.yml,
tests/python/python-ldap3-hardcoded-secret-python-test.yml
Defined YAML test cases to validate the correct identification of empty and hardcoded passwords in ldap3.Connection usages.
tests/python/python-mariadb-empty-password-python-test.yml,
tests/python/python-mariadb-hardcoded-secret-python-test.yml
Introduced test cases to assert the behavior of the new MariaDB security rules against invalid password configurations.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer Code
    participant Scanner as Security Scanner
    Dev->>Scanner: Submit Python source code
    Scanner->>Scanner: Parse AST for connection calls
    alt ldap3.Connection detected
         Scanner->>Scanner: Check for empty or hardcoded password
         Scanner--)Dev: Emit warning if vulnerability found
    else mariadb.connect detected
         Scanner->>Scanner: Verify password is not empty/hardcoded
         Scanner--)Dev: Emit security warning if issue found
    end
Loading

Possibly related PRs

Suggested reviewers

  • ganeshpatro321

Poem

I'm a hopping little bunny,
Scanning code with bright-eyed glee,
Empty strings and secrets beware,
For secure vaults keep them out of the way,
I nibble bugs and code with cheer,
Hopping on through lines so dear—
Hip hop, hop, safe code is here!


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai bot changed the title @coderabbitai Add YAML security rules and tests for ldap3 and MariaDB Mar 24, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (13)
tests/python/python-ldap3-hardcoded-secret-python-test.yml (1)

10-10: Missing Newline at End of File
YAMLlint reports no newline at the end of the file. Please add a newline character at the end to satisfy formatting standards.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 10-10: no new line character at the end of file

(new-line-at-end-of-file)

tests/python/python-ldap3-empty-password-python-test.yml (1)

10-10: Missing Newline at End of File
A newline at the end of the file is missing as indicated by YAMLlint. Please add one to conform to the style guidelines.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 10-10: no new line character at the end of file

(new-line-at-end-of-file)

tests/__snapshots__/python-ldap3-empty-password-python-snapshot.yml (1)

30-78: Verification of Variable-Based Password Snapshot (Block 2)
This snapshot tests an instance where an empty string is assigned to a variable (test = "") and then passed as the password. The labels are comprehensive, though there is some repetitive capturing of the initialization (test = ""). If possible, consider streamlining the redundant label entries to improve clarity.

tests/__snapshots__/python-mariadb-empty-password-python-snapshot.yml (1)

1-58: Review of MariaDB Connection Snapshot with Variable
This snapshot validates the case where an empty password is provided via a variable (PASSWORD1 = "") in the connection call. The labels offer exhaustive details (tracking the variable, the password keyword, and the empty string literal), although some entries appear repetitively. You might consider consolidating similar labels if they do not add extra matching value.

tests/__snapshots__/python-mariadb-hardcoded-secret-python-snapshot.yml (2)

3-62: Review of Hardcoded Secret Snapshot with Variable
This snapshot validates the scenario where a hardcoded password is stored in a variable (PASSWORD1 = "test") and then used in a MariaDB connection. The labels are detailed and capture both the variable declaration and its usage in the connection call.


63-101: Review of Direct Hardcoded Password Snapshot
The snapshot that uses conn = mariadb.connect(password="test") clearly demonstrates the hardcoded secret case. Although the label definitions are exhaustive, there is minor redundancy in capturing the string literal portions.

rules/python/security/python-ldap3-empty-password-python.yml (1)

16-60: Review of Utilities for Pattern Matching (Part 1)
The first utility block defines a pattern (ldap3.Connection(..., password="",...)_INSTANCE) to capture scenarios where an empty password is used. The nested conditions checking attributes and the argument list are comprehensive. Adding inline documentation or comments within this block might improve maintainability by clarifying the purpose of each nested condition.

rules/python/security/python-ldap3-hardcoded-secret-python.yml (1)

32-55: Review of Password Definition Utility
The define_password utility leverages both the previously defined string matching and an identifier pattern to detect password values. Although its nested structure is somewhat complex, consider adding inline comments to explain the matching logic for future maintainers.

rules/python/security/python-mariadb-empty-password-python.yml (3)

18-31: Utility Pattern for Empty String Matching
The define_string utility is designed to detect an empty string by requiring a string start and end while ensuring no string content exists. This is a precise approach to identify an empty password.

Consider adding inline comments to explain the purpose of each condition for future maintainers.


136-155: Attribute Access via Direct Module Call
The pattern here matches calls where connect is accessed as an attribute on the mariadb module (e.g. mariadb.connect(...)). This provides additional coverage for detecting empty password usage in different coding styles.

Consider whether this pattern could be consolidated with similar segments to reduce redundancy while maintaining clarity.


156-204: Detection with Aliased Import Matching Using $MARIADB_ALIAS
This segment is designed to detect cases where connect is called via an alias obtained from an aliased import, identified by $MARIADB_ALIAS. The use of the inside clause (ensuring the call follows an import statement with an aliased import) adds robustness by confirming the source of the call.

Refactoring common sub-patterns (possibly via YAML anchors or reusable blocks) might simplify future maintenance and reduce duplication across segments.

rules/python/security/python-mariadb-hardcoded-secret-python.yml (2)

136-155: Attribute Access Detection for Hardcoded Secrets
The rule here detects calls where connect is accessed via an attribute (e.g. mariadb.connect). This pattern ensures that even when the function is invoked in this style, any hard-coded password values are flagged.

Similar to the empty password rule, consider consolidating overlapping detection patterns to avoid future maintenance challenges.


156-204: Aliased Import Matching Using $MARIADB_ALIAS for Hardcoded Secrets
This segment handles cases where connect is invoked through an alias provided by an aliased import (matched with $MARIADB_ALIAS). The use of an inner inside clause to restrict the search to proper import statements increases the robustness of the detection.

Investigate the possibility of reusing shared pattern definitions (for example, via YAML anchors) to reduce code duplication between the hardcoded secret and empty password rules.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d3542b and 8379413.

📒 Files selected for processing (12)
  • rules/python/security/python-ldap3-empty-password-python.yml (1 hunks)
  • rules/python/security/python-ldap3-hardcoded-secret-python.yml (1 hunks)
  • rules/python/security/python-mariadb-empty-password-python.yml (1 hunks)
  • rules/python/security/python-mariadb-hardcoded-secret-python.yml (1 hunks)
  • tests/__snapshots__/python-ldap3-empty-password-python-snapshot.yml (1 hunks)
  • tests/__snapshots__/python-ldap3-hardcoded-secret-python-snapshot.yml (1 hunks)
  • tests/__snapshots__/python-mariadb-empty-password-python-snapshot.yml (1 hunks)
  • tests/__snapshots__/python-mariadb-hardcoded-secret-python-snapshot.yml (1 hunks)
  • tests/python/python-ldap3-empty-password-python-test.yml (1 hunks)
  • tests/python/python-ldap3-hardcoded-secret-python-test.yml (1 hunks)
  • tests/python/python-mariadb-empty-password-python-test.yml (1 hunks)
  • tests/python/python-mariadb-hardcoded-secret-python-test.yml (1 hunks)
🧰 Additional context used
🪛 YAMLlint (1.35.1)
tests/python/python-ldap3-empty-password-python-test.yml

[error] 10-10: no new line character at the end of file

(new-line-at-end-of-file)

tests/python/python-ldap3-hardcoded-secret-python-test.yml

[error] 10-10: no new line character at the end of file

(new-line-at-end-of-file)

🔇 Additional comments (38)
tests/python/python-ldap3-hardcoded-secret-python-test.yml (2)

1-4: Valid Configuration and Readability
The valid example clearly uses a variable (test) for the password rather than a hardcoded string, which aligns with secure credential management practices.


5-10: Invalid Cases Clearly Specified
Both invalid examples—one with a hardcoded string ("test") and one with a variable assigned a hardcoded value—are clearly delineated. Consider adding inline documentation or comments referencing the relevant CWE/OWASP guidelines to aid future maintainers in understanding the security implications.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 10-10: no new line character at the end of file

(new-line-at-end-of-file)

tests/python/python-mariadb-empty-password-python-test.yml (4)

1-4: Valid Case for Empty Password Handling
The valid snippet uses an environment variable (os.env['pass']) to supply the password, which avoids hardcoding secrets. Verify that the class name MySQLDatabe is intentional.


6-8: Invalid Example: Variable with Empty Password
Assigning an empty string to a variable (PASSWORD1) and passing it as the password correctly demonstrates the risk associated with empty credentials.


9-10: Invalid Example: Direct Empty Password
The direct use of an empty string in the connection function call effectively illustrates the issue.


11-13: Invalid Example: Alias with Empty Password
The snippet using an alias (mrdbl123) to connect with an empty password further reinforces that alternative import names do not circumvent the risk. Consider adding a brief comment to emphasize the security concern.

tests/python/python-mariadb-hardcoded-secret-python-test.yml (4)

1-4: Valid Configuration Avoiding Hardcoded Secrets
The valid snippet correctly retrieves the password from an environment variable, thereby avoiding hardcoded credentials. Again, ensure MySQLDatabe is the intended class name for consistency.


6-8: Invalid Case: Hardcoded Password via Variable
Assigning a hardcoded password to a variable (PASSWORD1) and then using it in the connection demonstrates a clear security risk.


9-10: Invalid Case: Direct Hardcoded Password
Directly passing "test" to the connection function is correctly flagged as an insecure practice.


11-13: Invalid Case: Aliased Import with Hardcoded Credential
Even though the MariaDB module is imported with an alias, using a hardcoded credential (with the parameter passwd) remains a security concern.

tests/python/python-ldap3-empty-password-python-test.yml (3)

1-4: Valid Example for LDAP3 Connection
The valid snippet uses a variable (test) for the password, which is preferable to using an empty literal.


5-7: Invalid Example: Direct Empty Password
Using an empty string directly in ldap3.Connection (line 7) illustrates an insecure configuration.


8-10: Invalid Example: Variable Assigned an Empty String
Assigning an empty string to a variable (test) and then using it in the connection call reinforces the concern.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 10-10: no new line character at the end of file

(new-line-at-end-of-file)

tests/__snapshots__/python-ldap3-hardcoded-secret-python-snapshot.yml (2)

1-42: Comprehensive Snapshot for Direct Hardcoded Secret
The first snapshot accurately captures the case of a hardcoded password (e.g. ldap3.Connection(password="test")) with detailed labels that specify token positions. This detailed mapping is very useful for precise AST matching and automated security checks.


43-101: Detailed Snapshot for Variable-Based Hardcoded Secret
The second snapshot, capturing the example where a variable is assigned a hardcoded value (test = "password") before being passed into the connection call, is well structured. The granular label breakdown aids in identifying potential security flaws. Be sure to update these positions if the rule logic or source formatting changes in the future.

tests/__snapshots__/python-ldap3-empty-password-python-snapshot.yml (1)

1-29: Approval for LDAP3 Empty Password Snapshot (Block 1)
The snapshot clearly captures the use of an empty password directly in the call (ldap3.Connection(password="")). The detailed labels accurately delineate the various segments (e.g. the function call, the password keyword, and the empty string literal). Please verify that the specified start and end indices precisely match the intended AST regions.

tests/__snapshots__/python-mariadb-empty-password-python-snapshot.yml (2)

59-93: Review of Direct Empty Password Snapshot
The snapshot using conn = mariadb.connect(password="") is clear and well-labeled. Ensure that the defined start and end positions correctly capture the relevant substrings from the source.


94-137: Review of Aliased Connection Snapshot
This snapshot tests the usage of an aliased MariaDB module (mariadb as mrdbl123). It comprehensively captures the connection call with additional parameters (host, user, and database), ensuring that alias-based invocations are also flagged.

tests/__snapshots__/python-mariadb-hardcoded-secret-python-snapshot.yml (1)

102-149: Review of Aliased Hardcoded Secret Snapshot
This snapshot covers the scenario where the module is imported under an alias (mrdbl123) and the connection call uses a hardcoded password. The labels correctly reflect the structure of this call, ensuring that alias usage is taken into account by the security rule.

rules/python/security/python-ldap3-empty-password-python.yml (3)

1-15: Review of Metadata and Description
The metadata section effectively details the risk of creating a database connection with an empty password. The message and references (including CWE-287 and the OWASP Secrets Management Cheat Sheet) provide clear context and rationale for the rule.


61-86: Review of Utilities for Pattern Matching (Part 2)
This block captures direct calls to ldap3.Connection with an explicit empty string for the password. It neatly complements the previous utility definition to cover both variable-based and literal password cases.


87-100: Review of Final Security Rule Logic
The rule section combines the defined utility patterns using an any operator and appropriately excludes error conditions. This logical composition ensures that both patterns (instance-based and direct literal call) trigger the warning. Testing this rule against real-world code examples will help verify comprehensive coverage.

rules/python/security/python-ldap3-hardcoded-secret-python.yml (3)

1-16: Review of Hardcoded Secret Rule Metadata
The metadata clearly outlines the dangers of embedding hard-coded secrets, with references to CWE-798 and OWASP A07:2021. The message is informative and emphasizes best practices for secret management.


18-30: Review of String Definition Utility
The define_string utility is well-crafted to match string literals by verifying the start, content, and end components. This clear separation supports accurate pattern matching in the subsequent rules.


56-154: Review of Final Hardcoded Secret Detection Rule
The rule combines multiple matching strategies to capture hard-coded secrets in connection calls, including both direct calls and those using aliased imports. The multi-pronged approach is robust and should effectively flag insecure patterns.

rules/python/security/python-mariadb-empty-password-python.yml (6)

1-10: Metadata and Message Clarity Check
The metadata fields (id, severity, language) are clearly defined, and the multi-line message properly describes the risk of using an empty password when connecting to MariaDB. The message text is clear and aligns with CWE-287.


11-15: Note Field Accuracy and Reference
The note block correctly cites [CWE-287] and provides an external reference to OWASP's Secrets Management Cheat Sheet. This well supports the intended security advisory.


16-16: AST Essentials Flag Confirmation
The ast-grep-essentials: true flag is set appropriately, ensuring that AST-based pattern matching is enabled.


32-55: Utility Pattern for Password Detection
The define_password block correctly combines two alternative matching strategies (either matching the empty string pattern via define_string or matching an identifier pattern with $PWD_IDENTIFIER in a specific assignment context). The nested structure is clear and fulfills the detection requirements.


56-92: Direct Call Pattern Detection
This rule segment targets direct calls to connect (identified by a regex match) where the keyword argument (named password or passwd) is provided. The use of an inside clause to restrict the match to an import-from statement from the mariadb module helps in reducing false positives.


93-135: Aliased Call Pattern Matching Using $SASL_ALIAS
This segment captures cases where the connect call is relayed via an alias ($SASL_ALIAS). It mirrors the logic of the first segment while ensuring that the password parameter conforms to the defined password pattern.

rules/python/security/python-mariadb-hardcoded-secret-python.yml (7)

1-10: Hardcoded Secret Metadata and Message Clarity
The metadata in this rule (id, language, severity) is clearly specified, and the multi-line message effectively communicates the risk of hard-coded secrets. It emphasizes the importance of using environment variables or secure vaults for managing sensitive data, aligning well with CWE-798 and OWASP guidelines.


11-15: Note Field for Hardcoded Credential Risks
The note field here includes critical references ([CWE-798] and [OWASP A07:2021]) along with an external reference. This correctly reinforces the secure coding practices intended by the rule.


16-16: AST Essentials Flag Confirmation
The ast-grep-essentials: true flag is appropriately enabled for AST-based pattern matching.


18-30: Utility Pattern for Non-Empty String Matching
The define_string utility here is configured to match strings containing content (by verifying string_start, string_content, and string_end). This is suitable for detecting hard-coded secret values, distinguishing it from an empty string match.


32-55: Utility Pattern for Password Detection in Hardcoded Secrets
The define_password block leverages the non-empty string pattern to detect password literals. Its structure mirrors that of the empty password rule but is appropriately adapted to expect non-empty string content.


56-92: Direct Call Pattern for Hardcoded Secrets
This segment targets direct calls to connect where the password keyword argument is passed. By using define_password, it can detect hard-coded (non-empty) secret values. The match is further scoped by ensuring the call resides within an import-from statement from the mariadb module.


93-135: Aliased Call Pattern Matching Using $SASL_ALIAS for Hardcoded Secrets
This segment precisely captures calls involving an alternative alias ($SASL_ALIAS), ensuring that passwords passed to connect adhere to the hardcoded secret detection logic.

@ganeshpatro321 ganeshpatro321 merged commit b231b4a into main Mar 24, 2025
2 checks passed
@ganeshpatro321 ganeshpatro321 deleted the ldap3_mariadb_password_python branch March 24, 2025 13:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants