Last active
December 16, 2025 12:30
-
-
Save jerinisready/f588121fb487feb7edbfe9ee2be11a0e to your computer and use it in GitHub Desktop.
Please dont reuse, without actuall knowledge of license. This is not really recommedned for enterprices. I dont know which licenses these containse. This is just for Experimental purpose
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| rules: | |
| - id: ruby_ftp_rule-AvoidTaintedFTPCall | |
| mode: taint | |
| pattern-sources: | |
| - pattern: params | |
| - pattern: cookies | |
| - pattern: request.env | |
| pattern-sinks: | |
| - pattern-either: | |
| - pattern: Net::FTP.$X(...) | |
| - patterns: | |
| - pattern-inside: '$FTP = Net::FTP.$OPEN(...) | |
| ... | |
| $FTP.$METHOD(...) | |
| ' | |
| - pattern: $FTP.$METHOD(...) | |
| message: "The application was found calling the Net::FTP modules methods with\n\ | |
| user supplied input. A malicious actor could use this to modify or access files\n\ | |
| they should not have access to.\n\nDirectly incorporating user-controlled input\ | |
| \ from `params`, `cookies`, \nor `request.env` into FTP commands or connection\ | |
| \ setups can lead to \nvarious security vulnerabilities, including Remote Code\ | |
| \ Execution \n(RCE), unauthorized file access, and data exfiltration. It's crucial\ | |
| \ \nto validate, sanitize, and, where possible, avoid using user-controlled \n\ | |
| data in sensitive operations like FTP transactions. Ensure that any input \nused\ | |
| \ in FTP operations is strictly controlled and validated against \nexpected patterns.\n\ | |
| \nRemediation Strategy:\nTo mitigate these risks, ensure that all user-provided\ | |
| \ input is strictly \nvalidated and sanitized before being used in FTP operations.\ | |
| \ \n- Verify the format and content of the input to ensure it meets expected \n\ | |
| criteria.\n- Use allowlists to restrict the input to known safe values.\n- Employ\ | |
| \ built-in security features of the programming language or \nframework to escape\ | |
| \ or safely handle user input.\n\nSecure Code Example:\n```\nfilename = params[:filename]\n\ | |
| # Validate the filename to ensure it's a known, safe file\nraise \"Invalid filename\"\ | |
| \ unless filename =~ /\\A[\\w]+\\.\\w+\\z/\n\nNet::FTP.open('example.com', 'user',\ | |
| \ 'password') do |ftp|\n # Proceed with the FTP operation using the validated\ | |
| \ and sanitized filename\n ftp.getbinaryfile(filename, \"local_#{filename}\"\ | |
| , 1024)\nend\n```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-76 | |
| shortDescription: Improper neutralization of equivalent special elements | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/avoid-tainted-ftp-call.yaml | |
| category: security | |
| security-severity: MEDIUM | |
| technology: | |
| - ruby | |
| - rails | |
| - id: ruby_crypto_rule-WeakHashesMD5 | |
| message: "The MD5 hashing algorithm is considered cryptographically weak and \n\ | |
| vulnerable to collision attacks, where two different inputs generate \nthe same\ | |
| \ output hash. When used for hashing sensitive data, attackers \ncan exploit this\ | |
| \ weakness to generate collisions, allowing them to bypass \nsecurity checks or\ | |
| \ masquerade malicious data as legitimate. This \nvulnerability is particularly\ | |
| \ critical in authentication mechanisms, \ndigital signatures, SSL/TLS certificates,\ | |
| \ and data integrity checks.\n\nRemediation:\nTo mitigate this vulnerability,\ | |
| \ replace the MD5 hashing algorithm with \nstronger cryptographic hash functions,\ | |
| \ such as SHA-256 or SHA-3. These \nalgorithms offer significantly improved security\ | |
| \ and are resistant to \ncollision attacks, making them suitable for cryptographic\ | |
| \ purposes in \nmodern applications.\n\nSecure Code example:\n```\nrequire 'openssl'\n\ | |
| \ndata = \"sensitive information\"\n# Using SHA-256\ndigest = OpenSSL::Digest::SHA256.new\n\ | |
| hash = digest.digest(data)\nhex_hash = digest.hexdigest(data)\n\n# Using SHA-3\ | |
| \ (256 bits)\ndigest = OpenSSL::Digest::SHA3.new(256)\nhash2 = digest.digest(data)\n\ | |
| hex_hash2 = digest.hexdigest(data)\n```\n" | |
| metadata: | |
| shortDescription: Use of weak hash | |
| category: security | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-328 | |
| security-severity: MEDIUM | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/weak-hashes-md5.yaml | |
| - https://www.ibm.com/support/pages/security-bulletin-vulnerability-md5-signature-and-hash-algorithm-affects-sterling-integrator-and-sterling-file-gateway-cve-2015-7575 | |
| technology: | |
| - ruby | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| pattern-either: | |
| - pattern: Digest::MD5.base64digest $X | |
| - pattern: Digest::MD5.hexdigest $X | |
| - pattern: Digest::MD5.digest $X | |
| - pattern: Digest::MD5.new | |
| - pattern: OpenSSL::Digest::MD5.base64digest $X | |
| - pattern: OpenSSL::Digest::MD5.hexdigest $X | |
| - pattern: OpenSSL::Digest::MD5.digest $X | |
| - pattern: OpenSSL::Digest::MD5.new | |
| - id: ruby_crypto_rule-InsufficientRSAKeySize | |
| message: "The RSA key size $SIZE is insufficent by NIST standards. It is \nrecommended\ | |
| \ to use a key length of 2048 or higher. The RSA algorithm, \nbeing widely used\ | |
| \ for secure data transmission, relies on key size \nfor its security. Smaller\ | |
| \ key sizes (e.g., 1024 bits and below) are \nmore susceptible to brute-force\ | |
| \ attacks, where an attacker uses \ncomputational power to decrypt data or forge\ | |
| \ signatures. \n\nTo address this security concern, ensure that all RSA keys are\ | |
| \ \ngenerated with a size of 2048 bits or more.\n\nFolowing is a secure code example:\n\ | |
| ```\nrequire 'openssl'\n\n# Generate a new RSA key of 2048 bits\nrsa_key = OpenSSL::PKey::RSA.new(2048)\n\ | |
| \n# To export the RSA key\nprivate_key = rsa_key.to_pem\npublic_key = rsa_key.public_key.to_pem\n\ | |
| ```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| category: security | |
| shortDescription: Inadequate encryption strength | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-326 | |
| technology: | |
| - ruby | |
| security-severity: MEDIUM | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/insufficient-rsa-key-size.yaml | |
| - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57Pt3r1.pdf | |
| patterns: | |
| - pattern-either: | |
| - pattern: OpenSSL::PKey::RSA.generate($SIZE,...) | |
| - pattern: OpenSSL::PKey::RSA.new($SIZE, ...) | |
| - patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: '$ASSIGN = $SIZE | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: OpenSSL::PKey::RSA.new($ASSIGN, ...) | |
| - pattern: OpenSSL::PKey::RSA.generate($ASSIGN, ...) | |
| - patterns: | |
| - pattern-inside: 'def $METHOD1(...) | |
| ... | |
| $ASSIGN = $SIZE | |
| ... | |
| end | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: OpenSSL::PKey::RSA.new($ASSIGN, ...) | |
| - pattern: OpenSSL::PKey::RSA.generate($ASSIGN, ...) | |
| - metavariable-comparison: | |
| metavariable: $SIZE | |
| comparison: $SIZE < 2048 | |
| - id: ruby_crypto_rule-WeakHashesSHA1 | |
| message: "The SHA-1 hashing algorithm is no longer considered secure for\ncryptographic\ | |
| \ applications due to its vulnerability to collision attacks,\nwhere two different\ | |
| \ inputs produce the same output hash. SHA-1's\nsusceptibility to collision attacks\ | |
| \ undermines the security of\ncryptographic operations, allowing attackers to\ | |
| \ forge signatures or\nmanipulate data without detection. This poses significant\ | |
| \ risks in\nauthentication systems, data integrity validations, and secure\ncommunications.\ | |
| \ \n\nRemediation: To mitigate this vulnerability, replace the SHA1 hashing \n\ | |
| algorithm with stronger cryptographic hash functions, such as SHA-256 \nor SHA-3.\ | |
| \ These algorithms offer significantly improved security and \nare resistant to\ | |
| \ collision attacks, making them suitable for cryptographic \npurposes in modern\ | |
| \ applications.\n\nSecure Code example : \n``` \nrequire 'openssl'\n\ndata = \"\ | |
| sensitive information\"\n# Using SHA-256\ndigest = OpenSSL::Digest::SHA256.new\n\ | |
| hash = digest.digest(data)\nhex_hash = digest.hexdigest(data)\n\n# Using SHA-3\ | |
| \ (256 bits)\ndigest = OpenSSL::Digest::SHA3.new(256)\nhash2 = digest.digest(data)\n\ | |
| hex_hash2 = digest.hexdigest(data)\n```\n" | |
| metadata: | |
| shortDescription: Use of weak hash | |
| category: security | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-328 | |
| security-severity: MEDIUM | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/weak-hashes-sha1.yaml | |
| - https://security.googleblog.com/2017/02/announcing-first-sha1-collision.html | |
| - https://shattered.io/ | |
| technology: | |
| - ruby | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| pattern-either: | |
| - pattern: Digest::SHA1.$FUNC | |
| - pattern: OpenSSL::Digest::SHA1.$FUNC | |
| - pattern: OpenSSL::HMAC.$FUNC("sha1",...) | |
| - id: ruby_ssl_rule-SSLModeNoVerify | |
| pattern: OpenSSL::SSL::VERIFY_NONE | |
| fix-regex: | |
| regex: VERIFY_NONE | |
| replacement: VERIFY_PEER | |
| message: "The application was found using `OpenSSL::SSL::VERIFY_NONE`.\nThis effectively\ | |
| \ disables the validation of TLS certificates.\n\nThis allows for an adversary\ | |
| \ who is in between the application and the \ntarget host to intercept potentially\ | |
| \ sensitive information or transmit \nmalicious data.\n\nTo remediate this issue,\ | |
| \ use 'OpenSSL::SSL::VERIFY_PEER' instead.\n" | |
| severity: WARNING | |
| languages: | |
| - ruby | |
| metadata: | |
| cwe: CWE-295 | |
| shortDescription: Improper certificate validation | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A07:2021-Identification and Authentication Failures | |
| category: security | |
| security-severity: MEDIUM | |
| technology: | |
| - ruby | |
| references: | |
| - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/ssl-mode-no-verify.yaml | |
| - id: ruby_ssl_rule-ForceSSLFalse | |
| pattern: config.force_ssl = false | |
| fix-regex: | |
| regex: =\s*false | |
| replacement: = true | |
| message: "The application was found setting `force_ssl` to `false`. This setting\n\ | |
| can expose the application to the risk of network\ninterception of unencrypted\ | |
| \ traffic. Enabling `force_ssl` by setting \n`config.force_ssl = true` in the\ | |
| \ application's configuration, specifically \nwithin `config/environments/production.rb`,\ | |
| \ forces the use of HTTPS, \nencrypting data in transit and safeguarding against\ | |
| \ eavesdropping or data \ntampering. \n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| cwe: CWE-319 | |
| shortDescription: Cleartext transmission of sensitive information | |
| category: security | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A04:2021-Insecure Design | |
| security-severity: MEDIUM | |
| technology: | |
| - ruby | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/force-ssl-false.yaml | |
| - id: ruby_escaping_rule-JSONEntityEscape | |
| pattern-either: | |
| - pattern: 'ActiveSupport.escape_html_entities_in_json = false | |
| ' | |
| - pattern: 'config.active_support.escape_html_entities_in_json = false | |
| ' | |
| message: "This rule checks if HTML escaping is globally disabled for JSON output,\ | |
| \ \nwhich can lead to Cross-Site Scripting (XSS) vulnerabilities. \nXSS attacks\ | |
| \ allow attackers to inject malicious scripts into web pages \nviewed by other\ | |
| \ users, compromising the integrity and confidentiality \nof user data. When HTML\ | |
| \ escaping is disabled, special HTML characters \nin JSON output are not converted\ | |
| \ to their entity equivalents, making \nit possible for an attacker to inject\ | |
| \ executable scripts into the web \napplication's output. \n\nTo mitigate this\ | |
| \ risk, ensure that HTML escaping is enabled when \ngenerating JSON output, particularly\ | |
| \ in web applications \nthat dynamically insert user-generated content into the\ | |
| \ DOM.\n\nSecure Code Example:\n```\n# For an initializer configuration (e.g.,\ | |
| \ in config/initializers/active_support.rb)\n# Enable HTML entity escaping in\ | |
| \ JSON to prevent XSS\nActiveSupport.escape_html_entities_in_json = true\n\n#\ | |
| \ For application-wide configuration (e.g., in config/application.rb)\nmodule\ | |
| \ YourApplication\n class Application < Rails::Application\n # Enable HTML\ | |
| \ entity escaping in JSON to prevent XSS\n config.active_support.escape_html_entities_in_json\ | |
| \ = true\n end\nend\n```\n" | |
| languages: | |
| - ruby | |
| metadata: | |
| shortDescription: Improper neutralization of input during web page generation | |
| ('Cross-site Scripting') | |
| category: security | |
| cwe: CWE-79 | |
| owasp: | |
| - A7:2017-Cross-Site Scripting (XSS) | |
| - A03:2021-Injection | |
| security-severity: MEDIUM | |
| technology: | |
| - rails | |
| references: | |
| - https://owasp.org/Top10/A03_2021-Injection | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/json-entity-escape.yaml | |
| severity: WARNING | |
| - id: ruby_file_rule-CheckRenderLocalFileInclude | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern: params[...] | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: 'render ..., file: $X | |
| ' | |
| - pattern: 'render ..., inline: $X | |
| ' | |
| - pattern: 'render ..., template: $X | |
| ' | |
| - pattern: 'render ..., action: $X | |
| ' | |
| - pattern: 'render $X, ... | |
| ' | |
| - focus-metavariable: $X | |
| pattern-sanitizers: | |
| - patterns: | |
| - pattern: $MAP[...] | |
| - metavariable-pattern: | |
| metavariable: $MAP | |
| patterns: | |
| - pattern-not-regex: params | |
| - pattern: File.basename(...) | |
| message: "The application dynamically constructs file or path information with user\ | |
| \ input when calling the `render` function. This can allow end\nusers to request\ | |
| \ arbitrary local files which may result in leaking\nsensitive information persisted\ | |
| \ on disk. Where possible, avoid letting\nusers specify template paths for `render`.\ | |
| \ If you must allow user input,\nuse an allow-list of known templates or normalize\ | |
| \ the user-supplied value\nwith `File.basename(...)`.\n\nTo mitigate this vulnerability,\ | |
| \ follow these steps:\n- Avoid direct user input: If possible, do not use user\ | |
| \ input \nto determine file paths. Use a mapping of user input to server-side\ | |
| \ \ndefined file paths instead.\n- Use `File.basename`: If user input must be\ | |
| \ used to specify a file, \nensure that the input is normalized using `File.basename`\ | |
| \ to extract \nthe filename without any directory path. This prevents directory\ | |
| \ \ntraversal attacks.\n- Path allow listing: Implement an allow list of permitted\ | |
| \ files or \ndirectories and check user input against this list before processing.\n\ | |
| \nSecure Code Example:\n```\nclass PagesController < ApplicationController\n \ | |
| \ # Allowlist\n def show\n valid_pages = ['home', 'about_us', 'contact']\n\ | |
| \ if valid_pages.include?(params[:page])\n render params[:page]\n else\n\ | |
| \ render 'not_found'\n end\n end\n\n # Sanitizing User Input\n def\ | |
| \ show\n # Sanitize the user input to extract just the file name\n page\ | |
| \ = File.basename(params[:page])\n # Optionally, further validate the sanitized\ | |
| \ input against an allow-list or other criteria\n render page\n end\nend\n\ | |
| ```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| cwe: CWE-22 | |
| shortDescription: Improper limitation of a pathname to a restricted directory | |
| ('Path Traversal') | |
| references: | |
| - https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.1-Testing_for_Local_File_Inclusion | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-render-local-file-include.yaml | |
| category: security | |
| security-severity: MEDIUM | |
| technology: | |
| - rails | |
| - id: ruby_file_rule-CheckSendFile | |
| mode: taint | |
| pattern-sources: | |
| - pattern-either: | |
| - pattern: 'cookies[...] | |
| ' | |
| - patterns: | |
| - pattern: 'cookies. ... .$PROPERTY[...] | |
| ' | |
| - metavariable-regex: | |
| metavariable: $PROPERTY | |
| regex: (?!signed|encrypted) | |
| - pattern: 'params[...] | |
| ' | |
| - pattern: 'request.env[...] | |
| ' | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: 'send_file ... | |
| ' | |
| message: "The application dynamically constructs file or path information with user\ | |
| \ input when calling\nthe `send_file` method in Ruby. This practice can lead to\ | |
| \ a serious \nsecurity vulnerability known as Local File Inclusion (LFI), allowing\ | |
| \ \nattackers to read arbitrary files on the server. \nLFI vulnerabilities can\ | |
| \ lead to the exposure of sensitive information, \nsuch as configuration files,\ | |
| \ source code, or even data files, \nwhich could be exploited to gain further\ | |
| \ access or to mount more \nsevere attacks.\n\nTo mitigate this vulnerability,\ | |
| \ follow these steps:\n- Avoid direct user input: If possible, do not use user\ | |
| \ input \nto determine file paths. Use a mapping of user input to server-side\ | |
| \ \ndefined file paths instead.\n- Use `File.basename`: If user input must be\ | |
| \ used to specify a file, \nensure that the input is normalized using `File.basename`\ | |
| \ to extract \nthe filename without any directory path. This prevents directory\ | |
| \ \ntraversal attacks.\n- Path allow listing: Implement an allow list of permitted\ | |
| \ files or \ndirectories and check user input against this list before processing.\n\ | |
| \nSecure Code Example:\n```\ndef download\n filename = params[:filename]\n filepath\ | |
| \ = \"path/to/secure/directory/#{File.basename(filename)}\"\n\n # Optionally,\ | |
| \ further validate the resolved filepath against a whitelist\n\n if File.exist?(filepath)\ | |
| \ && !File.directory?(filepath)\n send_file filepath, x_sendfile: true\n else\n\ | |
| \ render plain: \"File not found\", status: :not_found\n end\nend\n```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| cwe: CWE-73 | |
| shortDescription: External control of file name or path | |
| references: | |
| - https://owasp.org/www-community/attacks/Path_Traversal | |
| - https://owasp.org/Top10/A01_2021-Broken_Access_Control/ | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-send-file.yaml | |
| category: security | |
| security-severity: MEDIUM | |
| technology: | |
| - ruby | |
| - rails | |
| - id: ruby_file_rule-AvoidTaintedFileAccess | |
| mode: taint | |
| pattern-sources: | |
| - pattern: params | |
| - pattern: cookies | |
| - pattern: request.env | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: Dir.$X(...) | |
| - pattern: File.$X(...) | |
| - pattern: IO.$X(...) | |
| - pattern: Kernel.$X(...) | |
| - pattern: PStore.$X(...) | |
| - pattern: Pathname.$X(...) | |
| - metavariable-pattern: | |
| metavariable: $X | |
| patterns: | |
| - pattern-either: | |
| - pattern: chdir | |
| - pattern: chroot | |
| - pattern: delete | |
| - pattern: entries | |
| - pattern: foreach | |
| - pattern: glob | |
| - pattern: install | |
| - pattern: lchmod | |
| - pattern: lchown | |
| - pattern: link | |
| - pattern: load | |
| - pattern: load_file | |
| - pattern: makedirs | |
| - pattern: move | |
| - pattern: new | |
| - pattern: open | |
| - pattern: read | |
| - pattern: readlines | |
| - pattern: rename | |
| - pattern: rmdir | |
| - pattern: safe_unlink | |
| - pattern: symlink | |
| - pattern: syscopy | |
| - pattern: sysopen | |
| - pattern: truncate | |
| - pattern: unlink | |
| message: "The application dynamically constructs file or path information with user\ | |
| \ input. When an application uses data from \nuntrusted sources (like `params`,\ | |
| \ `cookies`, or `request.env`) to perform \nactions on the file system, it opens\ | |
| \ up potential vulnerabilities. \nA malicious actor could exploit this to access,\ | |
| \ modify, or delete \nfiles they shouldn't have access to, leading to information\ | |
| \ disclosure, \ndata loss, or server compromise. This type of vulnerability is\ | |
| \ often \nreferred to as a File Inclusion vulnerability or Path Traversal attack,\ | |
| \ \ndepending on the nature of the exploit.\n\nTo mitigate these risks, follow\ | |
| \ these best practices:\n- Validate and sanitize input: Ensure all user inputs\ | |
| \ are strictly \nvalidated and sanitized to prevent path traversal characters\ | |
| \ (like `../`) \nor other malicious patterns. Only allow filenames or paths that\ | |
| \ match \nspecific, safe patterns.\n- Use secure libraries: Utilize libraries\ | |
| \ or frameworks that abstract \nfile access in a secure manner, automatically\ | |
| \ handling the risks \nassociated with raw user input.\n- Least privilege principle:\ | |
| \ Run your application with the minimum \nnecessary file system permissions. Restrict\ | |
| \ the application's access \nto only those directories and files it absolutely\ | |
| \ needs.\n- Directory whitelisting: Maintain an allow list of permitted directories\ | |
| \ \nfor file operations, rejecting any requests for paths outside of these \n\ | |
| directories.\n\nSecure Code Example:\n```\ndef safe_file_read(filename)\n # Define\ | |
| \ a list of allowed files or use regex to validate the filename format\n allowed_files\ | |
| \ = ['allowed_file.txt', 'another_safe_file.txt']\n \n if allowed_files.include?(filename)\n\ | |
| \ file_path = Rails.root.join('safe_directory', filename)\n content = File.read(file_path)\n\ | |
| \ return content\n else\n raise \"Access to the requested file is not allowed.\"\ | |
| \n end\nend\n```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| cwe: CWE-22 | |
| shortDescription: Improper limitation of a pathname to a restricted directory | |
| ('Path Traversal') | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/avoid-tainted-file-access.yaml | |
| category: security | |
| security-severity: MEDIUM | |
| technology: | |
| - rails | |
| - id: ruby_mass_assignment_rule-UnprotectedMassAssign | |
| patterns: | |
| - pattern-either: | |
| - pattern: '$MOD.new(params[$CODE]) | |
| ' | |
| - pattern: '$MOD.new(..., params[$CODE], :without_protection => true, ...) | |
| ' | |
| - pattern-not-inside: 'attr_accessible $VAR | |
| ... | |
| $MOD.new(params[$CODE]) | |
| ' | |
| message: "Checks for calls to `without_protection` during mass assignment (which\ | |
| \ \nallows record creation from hash values). This can lead to users bypassing\ | |
| \ \npermissions protections. Using `:without_protection => true` makes your \n\ | |
| application vulnerable to attackers who may craft malicious requests to \nmodify\ | |
| \ sensitive attributes, leading to unauthorized access or data \nmanipulation.\ | |
| \ For Rails 4 and higher, mass protection is on by default.\n\nTo mitigate this\ | |
| \ issue, don't use :without_protection => true. Instead, \nconfigure attr_accessible\ | |
| \ to control attribute access.\n\nSecure Code Example:\n```\nclass User < ActiveRecord::Base\n\ | |
| \ # Only name and email can be updated via mass assignment\n attr_accessible\ | |
| \ :name, :email\n\n # admin and account_id are not listed here, so they cannot\ | |
| \ be mass-assigned\nend\n```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| category: security | |
| shortDescription: Improperly controlled modification of dynamically-determined | |
| object attributes | |
| cwe: CWE-915 | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A08:2021-Software and Data Integrity Failures | |
| security-severity: MEDIUM | |
| technology: | |
| - ruby | |
| - rails | |
| references: | |
| - https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/unprotected-mass-assign.yaml | |
| - id: ruby_mass_assignment_rule-ModelAttrAccessible | |
| pattern-either: | |
| - pattern: '....permit(..., :admin, ...) | |
| ' | |
| - pattern: '....permit(..., :role, ...) | |
| ' | |
| - pattern: '....permit(..., :banned, ...) | |
| ' | |
| - pattern: '....permit(..., :account_id, ...) | |
| ' | |
| - pattern: 'attr_accessible ..., :admin, ... | |
| ' | |
| - pattern: 'attr_accessible ..., :role, ... | |
| ' | |
| - pattern: 'attr_accessible ..., :banned, ... | |
| ' | |
| - pattern: 'attr_accessible ..., :account_id, ... | |
| ' | |
| - pattern: 'params.permit! | |
| ' | |
| message: "The application was found permitting attributes which could lead to mass\ | |
| \ assignment\nvulnerabilities. Permitting attributes such as `admin`, `role`,\ | |
| \ `banned` etc, \nwithout proper authorization checks can lead to security issues\ | |
| \ like unauthorized \naccess or privilege escalation.\n\nRemediation Strategy\n\ | |
| - Explicitly permit attributes: Carefully review which attributes are \npermissible\ | |
| \ and avoid including sensitive ones in the list.\n- Role-based permissions: Implement\ | |
| \ checks that allow only authorized \nusers (e.g., administrators) to modify sensitive\ | |
| \ attributes.\n- Avoid using `params.permit!`: Use specific permit statements\ | |
| \ instead of \npermitting all parameters to ensure only expected attributes are\ | |
| \ allowed \nfor mass assignment.\n\nSecure Code Example:\n```\n# Secure: Conditionally\ | |
| \ permit sensitive attributes based on user role\ndef user_params\npermitted =\ | |
| \ params.require(:user).permit(:name, :email)\npermitted[:role] = params[:user][:role]\ | |
| \ if current_user.admin? && params[:user][:role].present?\npermitted\nend\n\n\ | |
| def user_params2\n permitted_attributes = [:username, :email]\n # Only allow\ | |
| \ 'admin' attribute to be updated by users with admin role\n permitted_attributes\ | |
| \ << :admin if current_user.admin?\n params.require(:user).permit(*permitted_attributes)\n\ | |
| end\n```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| category: security | |
| shortDescription: Improperly controlled modification of dynamically-determined | |
| object attributes | |
| cwe: CWE-915 | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A08:2021-Software and Data Integrity Failures | |
| security-severity: MEDIUM | |
| technology: | |
| - ruby | |
| - rails | |
| references: | |
| - https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/model-attr-accessible.yaml | |
| - id: ruby_xss_rule-ManualTemplateCreation | |
| pattern: ERB.new(...) | |
| message: "The application was identified manually creating ERB templates. Manual\ | |
| \ creation of templates\nmay expose your application to server-side template injection\ | |
| \ (SSTI) or\ncross-site scripting (XSS) attacks if user input is used to create\ | |
| \ the\ntemplate. Instead, create a '.erb' template file and use 'render'.\n\n\ | |
| Secure Code Example:\n```\n# Controller: messages_controller.rb\nclass MessagesController\ | |
| \ < ApplicationController\n def show\n # Safely assign user input to an instance\ | |
| \ variable\n @message_content = sanitize(params[:user_content])\n \n \ | |
| \ # Render the static .erb template\n render 'messages/show'\n end\nend\n\n\ | |
| <!-- Static ERB Template Example - app/views/messages/show.html.erb -->\n<div>\n\ | |
| \ Message: <%= @message_content %>\n</div>\n```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Improper neutralization of input during web page generation | |
| ('Cross-site Scripting') | |
| category: security | |
| cwe: CWE-79 | |
| owasp: | |
| - A7:2017-Cross-Site Scripting (XSS) | |
| - A03:2021-Injection | |
| security-severity: MEDIUM | |
| technology: | |
| - rails | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/xss/manual-template-creation.yaml | |
| - id: ruby_xss_rule-AvoidLinkTo | |
| mode: taint | |
| pattern-sources: | |
| - pattern: params | |
| - pattern: cookies | |
| - pattern: request.env | |
| - pattern-either: | |
| - pattern: $MODEL.url(...) | |
| - pattern: $MODEL.uri(...) | |
| - pattern: $MODEL.link(...) | |
| - pattern: $MODEL.page(...) | |
| - pattern: $MODEL.site(...) | |
| pattern-sinks: | |
| - pattern: link_to(...) | |
| pattern-sanitizers: | |
| - patterns: | |
| - pattern: '"...#{...}..." | |
| ' | |
| - pattern-not: '"#{...}..." | |
| ' | |
| message: "This code includes user input in `link_to`. In Rails, the body of \n`link_to`\ | |
| \ is not escaped. This means that user input which reaches the \nbody will be\ | |
| \ executed when the HTML is rendered. Even in other versions, \nvalues starting\ | |
| \ with `javascript:` or `data:` are not escaped. \n\nMitigation Strategy:\nAlways\ | |
| \ sanitize user input used within `link_to` method calls. For versions of \nRails\ | |
| \ where `link_to` does not automatically escape the body, or when dealing \nwith\ | |
| \ schemes that are not escaped (`javascript:`, `data:`), manually escape or \n\ | |
| validate the input against a list of safe values. Consider using the `sanitize`\ | |
| \ \nhelper method or other Rails sanitization helpers to clean user input before\ | |
| \ \nrendering.\n\nSecure Code Example:\n```\nuser_input = params[:user_link_text]\n\ | |
| \n# This example uses the `sanitize` helper to ensure any HTML tags or JavaScript\ | |
| \ in the user input are escaped\nsafe_link_text = sanitize(user_input)\n\n# Use\ | |
| \ the sanitized text as the body of the `link_to` method\n<%= link_to safe_link_text,\ | |
| \ some_safe_path %>\n```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Improper neutralization of input during web page generation | |
| ('Cross-site Scripting') | |
| category: security | |
| cwe: CWE-79 | |
| owasp: | |
| - A7:2017-Cross-Site Scripting (XSS) | |
| - A03:2021-Injection | |
| security-severity: MEDIUM | |
| technology: | |
| - rails | |
| references: | |
| - https://brakemanscanner.org/docs/warning_types/link_to/ | |
| - https://brakemanscanner.org/docs/warning_types/link_to_href/ | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/xss/avoid-link-to.yaml | |
| - id: ruby_xss_rule-AvoidRenderInline | |
| pattern: 'render inline: ...' | |
| message: "The application was found calling `render inline: ...` which renders an\ | |
| \ entire ERB template inline and is potentially dangerous.\nIf user supplied input\ | |
| \ is used, the application can be exploited by malicious \nactors via server-side\ | |
| \ template injection (SSTI) or cross-site scripting (XSS) attacks.\nInstead, consider\ | |
| \ using a partial or another safe rendering method.\n\nSecure Code Example:\n\ | |
| ```\n# In your controller or view\nuser_input = params[:user_input]\nrender partial:\ | |
| \ 'users/user_input', locals: { user_input: user_input }\n\n# erb file\n<!-- app/views/users/_user_input.html.erb\ | |
| \ -->\n<!-- Display user input safely -->\n<div>\n <%= sanitize(user_input) %>\n\ | |
| </div>\n```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Improper neutralization of input during web page generation | |
| ('Cross-site Scripting') | |
| category: security | |
| cwe: CWE-79 | |
| owasp: | |
| - A7:2017-Cross-Site Scripting (XSS) | |
| - A03:2021-Injection | |
| security-severity: MEDIUM | |
| technology: | |
| - rails | |
| references: | |
| - https://brakemanpro.com/2017/09/08/cross-site-scripting-in-rails#inline-renders---even-worse-than-xss | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/xss/avoid-render-inline.yaml | |
| - id: ruby_xss_rule-AvoidRenderText | |
| pattern: 'render text: ...' | |
| fix-regex: | |
| regex: 'text:' | |
| replacement: 'plain:' | |
| message: "The application was found calling `render text: ...` which actually sets\ | |
| \ the \ncontent-type to 'text/html'. If external data can reach here, this exposes\ | |
| \ your \napplication to cross-site scripting (XSS) attacks. Instead, use `render\ | |
| \ plain: ...` to\nrender non-HTML text.\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Improper neutralization of input during web page generation | |
| ('Cross-site Scripting') | |
| category: security | |
| cwe: CWE-79 | |
| owasp: | |
| - A7:2017-Cross-Site Scripting (XSS) | |
| - A03:2021-Injection | |
| security-severity: MEDIUM | |
| technology: | |
| - rails | |
| references: | |
| - https://brakemanpro.com/2017/09/08/cross-site-scripting-in-rails#inline-renders---even-worse-than-xss | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/xss/avoid-render-text.yaml | |
| - id: ruby_regex_rule-CheckValidationRegex | |
| mode: search | |
| patterns: | |
| - pattern-either: | |
| - pattern: 'validates ..., :format => <... $V ...>,... | |
| ' | |
| - pattern: 'validates_format_of ..., :with => <... $V ...>,... | |
| ' | |
| - metavariable-regex: | |
| metavariable: $V | |
| regex: /(.{2}(?<!\\A)[^\/]+|[^\/]+(?<!\\[Zz]))\/ | |
| message: "An incorrectly-bounded regex was passed to `validates_format_of` \nor\ | |
| \ `validate ... format => ...`.\n\nRuby regex behavior is multiline by default\ | |
| \ and lines should be terminated \nby `\\A` for beginning of line and `\\Z` for\ | |
| \ end of line, respectively.\n\nSecure Code Example:\n```\nclass User < ApplicationRecord\n\ | |
| \ # Securely anchored from start to end of the string\n validates :username,\ | |
| \ format: { with: /\\A(?=.*[a-zA-Z])[a-zA-Z0-9]+\\z/ }\nend\n```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| category: security | |
| cwe: CWE-185 | |
| shortDescription: Incorrect regular expression | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| security-severity: MEDIUM | |
| technology: | |
| - ruby | |
| - rails | |
| references: | |
| - https://brakemanscanner.org/docs/warning_types/format_validation/ | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-validation-regex.yaml | |
| - id: ruby_regex_rule-CheckRegexDOS | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: 'cookies[...] | |
| ' | |
| - patterns: | |
| - pattern: 'cookies. ... .$PROPERTY[...] | |
| ' | |
| - metavariable-regex: | |
| metavariable: $PROPERTY | |
| regex: (?!signed|encrypted) | |
| - pattern: 'params[...] | |
| ' | |
| - pattern: 'request.env[...] | |
| ' | |
| - patterns: | |
| - pattern: $Y | |
| - pattern-either: | |
| - pattern-inside: '$RECORD.read_attribute($Y) | |
| ' | |
| - pattern-inside: '$RECORD[$Y] | |
| ' | |
| - metavariable-regex: | |
| metavariable: $RECORD | |
| regex: '[A-Z][a-z]+' | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern: $Y | |
| - pattern-inside: '/...#{...}.../ | |
| ' | |
| - patterns: | |
| - pattern: $Y | |
| - pattern-inside: 'Regexp.new(...) | |
| ' | |
| message: "The application was found constructing a regular expression with user-controllable\n\ | |
| input. This may result in excessive resource consumption \nwhen applied to certain\ | |
| \ inputs, or when the user is allowed to control \nthe match target.\n\nTo mitigate\ | |
| \ the issue, avoid allowing users to specify regular expressions \nprocessed by\ | |
| \ the server. If you must support user-controllable input in a \nregular expression,\ | |
| \ use an allow-list to restrict the expressions users \nmay supply to limit catastrophic\ | |
| \ backtracking.\n\nSecure Code Example:\n```\n# Define an allow-list of safe,\ | |
| \ predefined patterns\nALLOWED_PATTERNS = {\n 'digits_only' => /^\\d+$/,\n 'letters_only'\ | |
| \ => /^[a-zA-Z]+$/,\n 'email_format' => /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\ | |
| .[a-zA-Z]{2,}$/\n}\nuser_pattern_key = params[:pattern_key]\ntarget_data = params[:data]\n\ | |
| \nif ALLOWED_PATTERNS.key?(user_pattern_key)\n # Fetch the safe pattern from\ | |
| \ the allow-list\n safe_pattern = ALLOWED_PATTERNS[user_pattern_key]\n \n #\ | |
| \ Apply the regular expression safely\n if target_data.match(safe_pattern)\n\ | |
| \ # Do something\n else\n # Do something\n end\nelse\n # Handle case\ | |
| \ where the pattern is not allowed\nend\n```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| category: security | |
| cwe: CWE-1333 | |
| shortDescription: Inefficient regular expression complexity | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A04:2021-Insecure Design | |
| security-severity: MEDIUM | |
| technology: | |
| - ruby | |
| - rails | |
| references: | |
| - https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-regex-dos.yaml | |
| - id: ruby_exceptions_rule-DetailedExceptions | |
| patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern: 'config.consider_all_requests_local = true | |
| ' | |
| - patterns: | |
| - pattern-inside: "class $CONTROLLER < ApplicationController\n ...\nend\n" | |
| - pattern: "def show_detailed_exceptions? (...)\n ...\nreturn $RETURN\nend\n" | |
| - metavariable-pattern: | |
| metavariable: $RETURN | |
| patterns: | |
| - pattern-not: 'false | |
| ' | |
| message: "The `consider_all_requests_local` setting was found set to true, which\ | |
| \ enables detailed exception reports. This setting, \nwhile useful during development\ | |
| \ for debugging purposes, can \ninadvertently expose sensitive system or application\ | |
| \ information \nto end users when enabled in production environments. Such \n\ | |
| information exposure could potentially aid attackers in crafting \nfurther attacks\ | |
| \ against the system.\n\nIt is advisable to disable detailed exception reporting\ | |
| \ in production \nenvironments to prevent the leakage of sensitive information.\ | |
| \ \n\nSecure Configuration Example:\n```\n# config/environments/production.rb\n\ | |
| Rails.application.config.consider_all_requests_local = false\n```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A05:2021-Security Misconfiguration | |
| shortDescription: Generation of error message containing sensitive information | |
| cwe: CWE-209 | |
| category: security | |
| security-severity: MEDIUM | |
| technology: | |
| - rails | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/detailed-exceptions.yaml | |
| - id: ruby_csrf_rule-MissingCSRFProtection | |
| patterns: | |
| - pattern: "class $CONTROLLER < ActionController::Base\n ...\nend\n" | |
| - pattern-not: "class $CONTROLLER < ActionController::Base\n ...\n protect_from_forgery\n\ | |
| end\n" | |
| message: "Detected controller which does not enable cross-site request forgery\n\ | |
| protections using `protect_from_forgery`. When a Rails application does \nnot\ | |
| \ use `protect_from_forgery` in its controllers, it is vulnerable to \nCSRF attacks.\ | |
| \ This vulnerability can allow attackers to submit unauthorized \nrequests on\ | |
| \ behalf of authenticated users, potentially leading to \nunauthorized actions\ | |
| \ being performed. \nTo mitigate this risk, Rails offers the `protect_from_forgery`\ | |
| \ method, \nwhich integrates CSRF token verification in every form submitted to\ | |
| \ \nyour application, ensuring that requests are legitimate. \nAdd `protect_from_forgery\ | |
| \ with: :exception` to your controller class. \nThe `with: :exception` option\ | |
| \ configures Rails to raise an exception \nif a CSRF token cannot be verified,\ | |
| \ providing an additional layer of security. \nThis approach ensures that unverified\ | |
| \ requests do not proceed silently, \nallowing for appropriate error handling\ | |
| \ and response measures.\n\nSecure Code Example:\n```\nclass YourController <\ | |
| \ ApplicationController\n protect_from_forgery with: :exception\n # Your controller\ | |
| \ actions here\nend\n```\nFor more information on CSRF, see OWASP guide:\nhttps://owasp.org/www-community/attacks/csrf\n" | |
| languages: | |
| - ruby | |
| metadata: | |
| shortDescription: Cross-site request forgery (CSRF) | |
| category: security | |
| cwe: CWE-352 | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| security-severity: MEDIUM | |
| technology: | |
| - ruby | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/missing-csrf-protection.yaml | |
| - https://owasp.org/Top10/A01_2021-Broken_Access_Control | |
| severity: WARNING | |
| - id: ruby_injection_rule-BadSend | |
| pattern-either: | |
| - pattern: '$PARAM = params[...] | |
| ... | |
| $RES = $MOD.send($PARAM.$FUNC) | |
| ' | |
| - pattern: '$PARAM = params[...] | |
| ... | |
| $RES = $MOD.try($PARAM.$FUNC) | |
| ' | |
| - pattern: '$PARAM = params[...] | |
| ... | |
| $RES = $MOD.__send__($PARAM.$FUNC) | |
| ' | |
| - pattern: '$PARAM = params[...] | |
| ... | |
| $RES = $MOD.public_send($PARAM.$FUNC) | |
| ' | |
| message: "The application was found calling dynamic method invocations in Ruby.\ | |
| \ \nIn particular one of the methods of: `Object#send`, `Object#try`, `Object#__send__`,\ | |
| \ \nor `Object#public_send`. These methods are powerful Ruby features that allow\ | |
| \ \ncalling another method on an object \nby name, where the method's name is\ | |
| \ passed as a string or symbol. \nHowever, when combined with untrusted input,\ | |
| \ such as parameters from \nweb requests, they can lead to severe security vulnerabilities,\ | |
| \ including \narbitrary method execution and potentially arbitrary code execution.\n\ | |
| \nTo mitigate these risks, it's crucial to validate and sanitize any user \ninput\ | |
| \ that might determine which methods are invoked. Moreover, consider \nusing safer\ | |
| \ alternatives to direct method invocation based on user input, \nsuch as explicitly\ | |
| \ whitelisting allowed methods or using conditional logic \nto determine method\ | |
| \ calls.\n\nSecure Code Example:\n```\n# Secure method invocation with validation\ | |
| \ and allow lists\nmethod_name = params[:method].to_sym\nallowed_methods = [:allowed_method_1,\ | |
| \ :allowed_method_2, :safe_method]\n\nif allowed_methods.include?(method_name)\n\ | |
| \ result = object.public_send(method_name)\nelse\n raise \"Unauthorized method\ | |
| \ call\"\nend\n```\n" | |
| languages: | |
| - ruby | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Improper control of generation of code ('Code Injection') | |
| category: security | |
| cwe: CWE-94 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: HIGH | |
| technology: | |
| - ruby | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/no-send.yaml | |
| - https://the.igreque.info/posts/2016/01-object-send-considered-harmful-en.html | |
| - id: ruby_injection_rule-DangerousExec | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern: "def $F(...,$ARG,...)\n ...\nend\n" | |
| - focus-metavariable: $ARG | |
| - pattern: params | |
| - pattern: cookies | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: '$EXEC(...) | |
| ' | |
| - pattern-not: '$EXEC("...","...","...",...) | |
| ' | |
| - pattern-not: '$EXEC(["...","...","...",...],...) | |
| ' | |
| - pattern-not: '$EXEC({...},"...","...","...",...) | |
| ' | |
| - pattern-not: '$EXEC({...},["...","...","...",...],...) | |
| ' | |
| - metavariable-regex: | |
| metavariable: $EXEC | |
| regex: ^(system|exec|spawn|Process.exec|Process.spawn|Open3.capture2|Open3.capture2e|Open3.capture3|Open3.popen2|Open3.popen2e|Open3.popen3|IO.popen|Gem::Util.popen|PTY.spawn)$ | |
| message: "OS command injection is a critical vulnerability that can lead to a full\ | |
| \ system\ncompromise as it may allow an adversary to pass in arbitrary commands\ | |
| \ or arguments\nto be executed.\n\nUser input should never be used in constructing\ | |
| \ commands or command arguments\nto functions which execute OS commands. This\ | |
| \ includes filenames supplied by\nuser uploads or downloads.\n\nTo mitigate this\ | |
| \ vulnerability, follow these best practices:\n- Validate input: Ensure that all\ | |
| \ user inputs are validated against a \nstrict pattern that only allows safe characters\ | |
| \ for the context. Reject \nany input that does not meet these criteria.\n- Sanitize\ | |
| \ input: When validation is not feasible, sanitize the input \nby escaping or\ | |
| \ removing potentially dangerous characters.\n- Use secure methods: Prefer using\ | |
| \ secure methods or libraries designed \nto execute system commands with parameters,\ | |
| \ which automatically handle \nproper escaping of user inputs, such as `Open3.capture3`\ | |
| \ in Ruby.\n- Least privilege: Run your application with the least privileges\ | |
| \ \nnecessary, limiting what an attacker can do if they manage to execute a \n\ | |
| command.\n\nSecure Code Example:\nInstead of directly interpolating user input\ | |
| \ into system commands, validate \nuser input against an allowlist, then use parameterized\ | |
| \ execution or safer \nAPIs like Open3:\n```\nrequire 'open3'\n\nuser_input =\ | |
| \ params[:user_input]\n# Define an allow list of permitted arguments\nallowed_arguments\ | |
| \ = ['allowed_argument1', 'allowed_argument2', 'allowed_argument3']\n\n# Validate\ | |
| \ user_input against the list\nif allowed_arguments.include?(user_input)\n #\ | |
| \ Using Open3 to safely execute system commands with allowed arguments\n stdout,\ | |
| \ stderr, status = Open3.capture3('grep', user_input, 'my_file.txt')\n if status.success?\n\ | |
| \ puts stdout\n else\n warn \"Error: #{stderr}\"\n end\nelse\n warn \"\ | |
| Error: Unpermitted argument.\"\nend\n```\n" | |
| languages: | |
| - ruby | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Improper control of generation of code ('Code Injection') | |
| category: security | |
| cwe: CWE-94 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: HIGH | |
| technology: | |
| - ruby | |
| - rails | |
| references: | |
| - https://guides.rubyonrails.org/security.html#command-line-injection | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/dangerous-exec.yaml | |
| - id: ruby_injection_rule-AvoidTaintedShellCall | |
| mode: taint | |
| pattern-sources: | |
| - pattern-either: | |
| - pattern: params[...] | |
| - pattern: cookies | |
| - pattern: request.env | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern: Kernel.$X(...) | |
| - patterns: | |
| - pattern-either: | |
| - pattern: Shell.$X(...) | |
| - patterns: | |
| - pattern-inside: '$SHELL = Shell.$ANY(...) | |
| ... | |
| $SHELL.$X(...) | |
| ' | |
| - pattern: $SHELL.$X(...) | |
| - metavariable-pattern: | |
| metavariable: $X | |
| patterns: | |
| - pattern-either: | |
| - pattern: cat | |
| - pattern: chdir | |
| - pattern: chroot | |
| - pattern: delete | |
| - pattern: entries | |
| - pattern: exec | |
| - pattern: foreach | |
| - pattern: glob | |
| - pattern: install | |
| - pattern: lchmod | |
| - pattern: lchown | |
| - pattern: link | |
| - pattern: load | |
| - pattern: load_file | |
| - pattern: makedirs | |
| - pattern: move | |
| - pattern: new | |
| - pattern: open | |
| - pattern: read | |
| - pattern: readlines | |
| - pattern: rename | |
| - pattern: rmdir | |
| - pattern: safe_unlink | |
| - pattern: symlink | |
| - pattern: syscopy | |
| - pattern: sysopen | |
| - pattern: system | |
| - pattern: truncate | |
| - pattern: unlink | |
| message: "User input should never be used in constructing commands or command arguments\n\ | |
| to functions which execute OS related functionality. Using external \ninput without\ | |
| \ validation in functions like `Kernel.system`, `exec`, or any \noperations that\ | |
| \ interact with the shell or file system (`cat`, `delete` \netc.) poses a severe\ | |
| \ security risk. These patterns can lead to command \ninjection vulnerabilities,\ | |
| \ where an attacker could execute arbitrary \ncommands on the system the application\ | |
| \ is hosted on, leading to data \nbreaches, unauthorized access, or worse.\n\n\ | |
| To prevent command injection vulnerabilities, validate and sanitize all \nuser\ | |
| \ input before using it in any system or shell operation. Additionally, \nconsider\ | |
| \ using safer alternatives for executing system commands that don't \ndirectly\ | |
| \ pass user input to the shell, such as parameterized APIs or \nfunctions that\ | |
| \ handle arguments safely.\n\nSecure Code Example:\n```\nuser_filename_key = params[:filename_key]\n\ | |
| \nallowed_filenames = {\n 'file1' => 'allowed_file_1.txt',\n 'file2' => 'allowed_file_2.txt',\n\ | |
| }\n\n# Validate and select the filename from the lookup table\nif allowed_filenames.has_key?(user_filename_key)\n\ | |
| \ safe_filename = allowed_filenames[user_filename_key]\n\n # Use a safer API\ | |
| \ to read file content without invoking the shell\n content = File.read(safe_filename)\n\ | |
| else\n puts \"Invalid filename.\"\nend\n```\n" | |
| languages: | |
| - ruby | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Improper neutralization of special elements used in an OS command | |
| ('OS Command Injection') | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-78 | |
| security-severity: HIGH | |
| technology: | |
| - rails | |
| - ruby | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/avoid-tainted-shell-call.yaml | |
| - id: ruby_http_rule-AvoidTaintedHTTPRequest | |
| mode: taint | |
| pattern-sources: | |
| - pattern: params | |
| - pattern: cookies | |
| - pattern: request.env | |
| pattern-sinks: | |
| - pattern-either: | |
| - patterns: | |
| - pattern: Net::HTTP::$METHOD.new(...) | |
| - metavariable-pattern: | |
| metavariable: $METHOD | |
| patterns: | |
| - pattern-either: | |
| - pattern: Copy | |
| - pattern: Delete | |
| - pattern: Get | |
| - pattern: Head | |
| - pattern: Lock | |
| - pattern: Mkcol | |
| - pattern: Move | |
| - pattern: Options | |
| - pattern: Patch | |
| - pattern: Post | |
| - pattern: Propfind | |
| - pattern: Proppatch | |
| - pattern: Put | |
| - pattern: Trace | |
| - pattern: Unlock | |
| - patterns: | |
| - pattern: Net::HTTP.$X(...) | |
| - metavariable-pattern: | |
| metavariable: $X | |
| patterns: | |
| - pattern-either: | |
| - pattern: get | |
| - pattern: get2 | |
| - pattern: head | |
| - pattern: head2 | |
| - pattern: options | |
| - pattern: patch | |
| - pattern: post | |
| - pattern: post2 | |
| - pattern: post_form | |
| - pattern: put | |
| - pattern: request | |
| - pattern: request_get | |
| - pattern: request_head | |
| - pattern: request_post | |
| - pattern: send_request | |
| - pattern: trace | |
| - pattern: get_print | |
| - pattern: get_response | |
| - pattern: start | |
| message: "The application was found including unvalidated user input into `Net::HTTP`\ | |
| \ methods, \nwhich could lead to HTTP Parameter Pollution (HPP) or worse, Server\ | |
| \ Side Request Forgery (SSRF).\nSpecifically, it looks for methods like GET, POST,\ | |
| \ DELETE, etc., \nbeing called with parameters that could be controlled by an\ | |
| \ end-user. \nUsing untrusted input in such a manner without proper validation\ | |
| \ and \nsanitization can lead to a variety of security vulnerabilities, including\ | |
| \ \nSSRF, injection attacks, unintended data leaks, and unauthorized actions \n\ | |
| being performed on behalf of the attacker.\n\nEnsure all user-controlled input\ | |
| \ is validated against a strict set of rules \n(e.g., expected data types, patterns,\ | |
| \ and lengths) and sanitized to remove \nor encode potentially harmful characters\ | |
| \ before being used in HTTP requests. \nAdditionally, consider using higher-level\ | |
| \ abstractions or frameworks that \nautomatically handle some of these concerns.\n\ | |
| \nSecure Code Example:\n```\nrequire 'uri'\n\n# Validate and sanitize the user\ | |
| \ input before using it in the HTTP request\nbegin\n user_input = params[:url]\n\ | |
| \ uri = URI.parse(user_input)\n\n # Ensure the URI is HTTP/HTTPS and refers\ | |
| \ to a trusted domain\n if uri.scheme.match?(/\\Ahttps?\\z/) && uri.host == 'www.abc.com'\n\ | |
| \ response = Net::HTTP.get(uri)\n else\n raise \"Invalid URL\"\n end\n\ | |
| rescue URI::InvalidURIError\n puts \"Provided URL is not valid\"\nend\n```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| category: security | |
| shortDescription: Server side request forgery (SSRF) | |
| cwe: CWE-918 | |
| owasp: | |
| - A1:2017-Injection | |
| - A10:2021-Server-Side Request Forgery | |
| security-severity: MEDIUM | |
| technology: | |
| - rails | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/avoid-tainted-http-request.yaml | |
| - id: ruby_http_rule-CheckHTTPVerbConfusion | |
| mode: search | |
| patterns: | |
| - pattern: "if request.get?\n ...\nelse\n ...\nend\n" | |
| - pattern-not-inside: "if ...\nelsif ...\n ...\nend\n" | |
| message: "Found an improperly constructed control flow block with `request.get?`.\ | |
| \ \nRails will route HEAD requests as GET requests but they will fail the \n`request.get?`\ | |
| \ check, potentially causing unexpected behavior unless an \n`elsif` condition\ | |
| \ is used.\n\nSecure Code Example:\n```\nif request.get?\n # Handle GET request\ | |
| \ logic here\nelsif request.head?\n # Handle HEAD request logic here\nelse\n\ | |
| \ # Handle others if needed\nend\n```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| category: security | |
| shortDescription: Improper check for unusual or exceptional conditions | |
| cwe: CWE-754 | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A04:2021-Insecure Design | |
| security-severity: MEDIUM | |
| technology: | |
| - ruby | |
| - rails | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-http-verb-confusion.yaml | |
| - id: ruby_redirect_rule-CheckRedirectTo | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: params | |
| - pattern: cookies | |
| - pattern: request.env | |
| - pattern: url_for(params[...],...,:only_path => false,...) | |
| pattern-sanitizers: | |
| - patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern: '$F(...) | |
| ' | |
| - metavariable-pattern: | |
| metavariable: $F | |
| patterns: | |
| - pattern-not-regex: (params|url_for|cookies|request.env|permit|redirect_to) | |
| - pattern: 'params.merge! :only_path => true | |
| ... | |
| ' | |
| - pattern: 'params.slice(...) | |
| ... | |
| ' | |
| - pattern: 'redirect_to [...] | |
| ' | |
| - patterns: | |
| - pattern: '$MODEL. ... .$M(...) | |
| ... | |
| ' | |
| - metavariable-regex: | |
| metavariable: $MODEL | |
| regex: '[A-Z]\w+' | |
| - metavariable-regex: | |
| metavariable: $M | |
| regex: (all|create|find|find_by|find_by_sql|first|last|new|from|group|having|joins|lock|order|reorder|select|where|take) | |
| - patterns: | |
| - pattern: 'params.$UNSAFE_HASH.merge(...,:only_path => true,...) | |
| ... | |
| ' | |
| - metavariable-regex: | |
| metavariable: $UNSAFE_HASH | |
| regex: to_unsafe_h(ash)? | |
| - patterns: | |
| - pattern: params.permit(...,$X,...) | |
| - metavariable-pattern: | |
| metavariable: $X | |
| patterns: | |
| - pattern-not-regex: (host|port|(sub)?domain) | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: $X | |
| - pattern-inside: 'redirect_to $X, ... | |
| ' | |
| - pattern-not-regex: params\.\w+(?<!permit)\(.*?\) | |
| message: "The application was found handling redirect behavior with user-supplied\ | |
| \ input. \nDo not pass `params` to `redirect_to` without the `:only_path => true`\ | |
| \ \nhash value. Using `:only_path => true` ensures that the URL is interpreted\ | |
| \ \nas a relative path, not allowing redirection to an arbitrary external URL,\ | |
| \ \nthus mitigating the risk of open redirects. Alternatively, validate or \n\ | |
| sanitize the input to ensure it's safe and intended.\n\nSecure Code Example:\n\ | |
| ```\n# Secure - Ensuring redirection is only to internal paths\ndef secure_redirect\n\ | |
| \ redirect_to params[:redirect_url], only_path: true\nend\n```\n" | |
| languages: | |
| - ruby | |
| severity: INFO | |
| metadata: | |
| shortDescription: URL redirection to untrusted site 'open redirect' | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-601 | |
| security-severity: LOW | |
| technology: | |
| - ruby | |
| - rails | |
| references: | |
| - https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-redirect-to.yaml | |
| - id: ruby_cookie_rule-CookieSerialization | |
| message: "The rule warns of a significant security risk in applications that use\ | |
| \ \nRuby's Marshal module for deserializing cookies. Marshal can serialize \n\ | |
| and deserialize Ruby objects, which, while powerful, poses a risk if \nmisused.\ | |
| \ If an attacker crafts a malicious cookie that is deserialized, \nit could lead\ | |
| \ to remote code execution (RCE) on the server due to \nMarshal.load's ability\ | |
| \ to execute code in deserialized objects. To mitigate \nthis risk, developers\ | |
| \ are advised to switch from Marshal to JSON for cookie \nserialization. JSON\ | |
| \ is safer as it cannot execute arbitrary code, reducing \nthe threat of RCE vulnerabilities\ | |
| \ from deserialized user data. The hybrid \ncheck is just to warn users to migrate\ | |
| \ to :json for best practice.\n\nSecure code example:\n```\n# In Rails, configure\ | |
| \ the cookie serializer to :json\n# config/initializers/cookies_serializer.rb\n\ | |
| Rails.application.config.action_dispatch.cookies_serializer = :json\n```\n\nAdditionally,\ | |
| \ always validate and sanitize user-supplied data as much \nas possible, even\ | |
| \ when using JSON, to further secure your application \nagainst various injection\ | |
| \ attacks.\n" | |
| languages: | |
| - ruby | |
| metadata: | |
| shortDescription: Improper control of generation of code ('Code Injection') | |
| category: security | |
| cwe: CWE-94 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| technology: | |
| - ruby | |
| security-severity: HIGH | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/cookie-serialization.yaml | |
| - https://robertheaton.com/2013/07/22/how-to-hack-a-rails-app-using-its-secret-token/ | |
| severity: ERROR | |
| pattern-either: | |
| - pattern: 'Rails.application.config.action_dispatch.cookies_serializer = :marshal | |
| ' | |
| - pattern: Rails.application.config.action_dispatch.cookies_serializer = :hybrid | |
| - id: ruby_cookie_rule-CheckCookieStoreSessionSecurityAttributes | |
| patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern: ':$KEY => false | |
| ' | |
| - pattern-inside: 'ActionController::Base.session = {...} | |
| ' | |
| - pattern: '$MODULE::Application.config.session_store :cookie_store, ..., :$KEY | |
| => false, ... | |
| ' | |
| - pattern: '$CLASS.application.config.session_store :cookie_store, ..., $KEY: | |
| false, ... | |
| ' | |
| - metavariable-regex: | |
| metavariable: $KEY | |
| regex: ^(session_)?(http_?only|secure)$ | |
| message: "The detected issue pertains to a Rails application where the session \n\ | |
| configuration, specifically using cookie_store, has been identified \nwith the\ | |
| \ $KEY attribute set to false. This setting is potentially \ninsecure because\ | |
| \ it may relate to crucial security attributes such \nas HttpOnly or Secure flags\ | |
| \ not being enforced. In the context of \nweb applications, these flags play a\ | |
| \ vital role in enhancing session \nsecurity:\n\n- HttpOnly Flag: When enabled,\ | |
| \ this flag prevents client-side scripts\nfrom accessing the cookie. This mitigation\ | |
| \ is crucial for reducing \nthe risk of cross-site scripting (XSS) attacks, where\ | |
| \ an attacker \nmight attempt to steal session cookies.\n- Secure Flag: This flag\ | |
| \ ensures that cookies are sent over secure, \nencrypted connections only (HTTPS).\ | |
| \ It's a critical security measure \nthat helps prevent cookies from being intercepted\ | |
| \ by attackers when \ntransmitted over an unencrypted connection.\n\nTo mitigate\ | |
| \ the identified security risk and ensure that your Rails \napplication's session\ | |
| \ cookies are securely configured. \n\nSecure Code Example:\n```\n# config/initializers/session_store.rb\n\ | |
| Rails.application.config.session_store :cookie_store, key: '_your_app_session',\n\ | |
| \ httponly: true,\n \ | |
| \ secure: Rails.env.production?\n```\n" | |
| languages: | |
| - ruby | |
| severity: INFO | |
| metadata: | |
| category: security | |
| shortDescription: Sensitive cookie without 'HttpOnly' and 'Secure' flags | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-1004 | |
| technology: | |
| - ruby | |
| - rails | |
| security-severity: LOW | |
| references: | |
| - https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/06-Session_Management_Testing/02-Testing_for_Cookies_Attributes | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-cookie-store-session-security-attributes.yaml | |
| - id: ruby_eval_rule-NoEval | |
| message: "The `eval` method in Ruby executes a string argument as Ruby code. When\ | |
| \ \n`eval` is used with input that can be controlled or manipulated by an \nexternal\ | |
| \ user, it can allow arbitrary code execution. This \nmeans an attacker could\ | |
| \ potentially execute malicious code on the server, \nleading to unauthorized\ | |
| \ access, data leakage, or server compromise.\n\nRemediation Steps:\n- Validate\ | |
| \ and sanitize input: If there's an absolute necessity to use \n`eval`, ensure\ | |
| \ that any user input is rigorously validated and sanitized \nto remove potentially\ | |
| \ harmful code. However, this is generally not \nrecommended due to the difficulty\ | |
| \ of securely sanitizing code.\n- Use safer alternatives: Depending on the requirement,\ | |
| \ consider using \nsafer alternatives to `eval`, such as `send` for calling methods\ | |
| \ dynamically \nor employing DSLs (Domain-Specific Languages) and safe parsing\ | |
| \ libraries \ndesigned for specific tasks.\n\nSecure Code Example:\n```\nclass\ | |
| \ Calculator\n def add(a, b)\n a + b\n end\nend\n\n# Safer alternative using\ | |
| \ send\ncalculator = Calculator.new\nmethod = params[:operation] # Example: 'add'\ | |
| \ or 'subtract'\na = params[:a].to_i\nb = params[:b].to_i\n\nif calculator.respond_to?(method)\n\ | |
| \ result = calculator.send(method, a, b)\nelse\n puts \"Invalid operation\"\n\ | |
| end\n```\n\nIn this example, `send` is used to dynamically call a method on the\ | |
| \ \nCalculator object based on user input. This approach is safer than \neval\ | |
| \ because it strictly limits the operations to those defined in \nthe class, preventing\ | |
| \ arbitrary code execution.\n" | |
| severity: ERROR | |
| metadata: | |
| cwe: CWE-95 | |
| shortDescription: Improper neutralization of directives in dynamically evaluated | |
| code ('Eval Injection') | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: HIGH | |
| references: | |
| - https://owasp.org/Top10/A03_2021-Injection | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/no-eval.yaml | |
| technology: | |
| - rails | |
| languages: | |
| - ruby | |
| mode: taint | |
| pattern-sources: | |
| - pattern-either: | |
| - pattern: params | |
| - pattern: cookies | |
| - patterns: | |
| - pattern: 'RubyVM::InstructionSequence.compile(...) | |
| ' | |
| - pattern-not: 'RubyVM::InstructionSequence.compile("...") | |
| ' | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: $X.eval | |
| - pattern: $X.class_eval | |
| - pattern: $X.instance_eval | |
| - pattern: $X.module_eval | |
| - pattern: $X.eval(...) | |
| - pattern: $X.class_eval(...) | |
| - pattern: $X.instance_eval(...) | |
| - pattern: $X.module_eval(...) | |
| - pattern: eval(...) | |
| - pattern: class_eval(...) | |
| - pattern: module_eval(...) | |
| - pattern: instance_eval(...) | |
| - pattern-not: $M("...",...) | |
| - id: ruby_find_rule-CheckUnscopedFind | |
| mode: taint | |
| pattern-sources: | |
| - pattern-either: | |
| - pattern: 'cookies[...] | |
| ' | |
| - patterns: | |
| - pattern: 'cookies. ... .$PROPERTY[...] | |
| ' | |
| - metavariable-regex: | |
| metavariable: $PROPERTY | |
| regex: (?!signed|encrypted) | |
| - pattern: 'params[...] | |
| ' | |
| - pattern: 'request.env[...] | |
| ' | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: $MODEL.find(...) | |
| - pattern: $MODEL.find_by_id(...) | |
| - pattern: $MODEL.find_by_id!(...) | |
| - metavariable-regex: | |
| metavariable: $MODEL | |
| regex: '[A-Z]\S+' | |
| message: "The application was found calling the `find(...)` method with user-controlled\ | |
| \ input. If the \nActiveRecord model being searched against is sensitive, this\ | |
| \ may lead to \nInsecure Direct Object Reference (IDOR) behavior and allow users\ | |
| \ to read \narbitrary records. This could lead to data breaches, including the\ | |
| \ \nexposure of personal information, account takeovers, and other security \n\ | |
| issues.\n\nTo mitigate this risk, it's essential to scope queries to the current\ | |
| \ \nuser or another appropriate scope that ensures users can only access \ndata\ | |
| \ they are authorized to see. This is done by using ActiveRecord \nassociations\ | |
| \ and scopes to limit the records that can be retrieved. \n\nSecure Code Example:\n\ | |
| ```\n# Secure way to scope the find to the current user's accounts\ndef show\n\ | |
| \ @account = current_user.accounts.find(params[:id])\nend\n```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| cwe: CWE-639 | |
| shortDescription: Authorization bypass through user-controlled key | |
| references: | |
| - https://brakemanscanner.org/docs/warning_types/unscoped_find/ | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-unscoped-find.yaml | |
| category: security | |
| security-severity: MEDIUM | |
| technology: | |
| - ruby | |
| - rails | |
| - id: ruby_filter_rule-CheckBeforeFilter | |
| mode: search | |
| patterns: | |
| - pattern-either: | |
| - pattern: 'skip_filter ..., :except => $ARGS | |
| ' | |
| - pattern: 'skip_before_filter ..., :except => $ARGS | |
| ' | |
| message: "The application was found disabling controller checks by setting `skip_filter`\ | |
| \ \nor `skip_before_filter` with an `:except` option. This approach can \ninadvertently\ | |
| \ open up parts of your application to unauthorized access \nbecause it relies\ | |
| \ on a blocklist approach, where only specified actions \nare protected. \n\n\ | |
| A safer method of providing this functionality involves specifying \nexactly which\ | |
| \ controller actions should have checks applied using an \n`:only` option, effectively\ | |
| \ creating an allowlist. This method ensures \nthat only specified actions are\ | |
| \ affected, and any new actions added to \nthe controller will have the filters\ | |
| \ applied by default, adhering to the \nprinciple of secure by default.\n\nSecure\ | |
| \ Code Example:\n```\nclass UsersController < ApplicationController\n # Apply\ | |
| \ the filter only to these actions, making it clear and secure by default\n skip_before_action\ | |
| \ :authenticate_user!, only: [:new, :create]\nend\n```\n\nIn the secure example,\ | |
| \ `:authenticate_user!` filter is explicitly skipped \nonly for the `:new` and\ | |
| \ `:create actions`. This means any new action added \nto the UsersController\ | |
| \ in the future will have the `authenticate_user!` \nfilter applied by default,\ | |
| \ ensuring that new parts of the application \nare secure from the start. \n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| cwe: CWE-749 | |
| shortDescription: Exposed dangerous method or function | |
| references: | |
| - https://owasp.org/Top10/A01_2021-Broken_Access_Control/ | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-before-filter.yaml | |
| category: security | |
| security-severity: LOW | |
| technology: | |
| - ruby | |
| - rails | |
| - id: ruby_error_rule-DivideByZero | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern: $VAR | |
| - metavariable-regex: | |
| metavariable: $VAR | |
| regex: ^\d*(?!\.)$ | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-inside: $NUMBER / 0 | |
| - pattern: $NUMBER | |
| message: "A ZeroDivisionError exception has been detected, this occurs when an arithmetic\ | |
| \ operation attempts to \ndivide a number by zero. This can happen in various\ | |
| \ contexts, such as \nprocessing user inputs, performing calculations with variables,\ | |
| \ or \nworking with data from external sources. Such errors not only disrupt \n\ | |
| the normal flow of the application but also can be exploited in certain \nscenarios\ | |
| \ to cause harm (eg. possible dos) or extract information based \non the application's\ | |
| \ response to the error.\n\nTo prevent ZeroDivisionError exceptions and ensure\ | |
| \ application robustness:\n- Error handling: Implement error handling around division\ | |
| \ operations to \ncatch and manage ZeroDivisionError gracefully.\n- Validation:\ | |
| \ Always validate inputs that are used in division operations \nto ensure they\ | |
| \ are not zero or unexpected values.\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Divide a number by zero | |
| category: security | |
| cwe: CWE-369 | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A04:2021-Insecure Design | |
| security-severity: LOW | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/divide-by-zero.yaml | |
| technology: | |
| - ruby | |
| - id: ruby_routes_rule-AvoidDefaultRoutes | |
| patterns: | |
| - pattern-either: | |
| - pattern: map.connect ":controller/:action/:id" | |
| - pattern: match ':controller(/:action(/:id(.:format)))' | |
| paths: | |
| include: | |
| - '*routes.rb' | |
| message: "Default routes are enabled in this routes file. This means any public\ | |
| \ method on a\ncontroller can be called as an action. It is easy to accidentally\ | |
| \ expose\nmethods. Instead, remove the offending line and explicitly include all\n\ | |
| routes that are intended for external users to follow.\n\nSecure Code Example:\n\ | |
| ```\n# In routes.rb\nRails.application.routes.draw do\n get 'posts' => 'posts#index',\ | |
| \ as: :posts\n get 'posts/:id' => 'posts#show', as: :post\n post 'posts' =>\ | |
| \ 'posts#create'\n\n # Other CRUD actions for posts can be defined similarly\n\ | |
| end\n```\n" | |
| languages: | |
| - ruby | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| cwe: CWE-276 | |
| shortDescription: Incorrect Default Permissions | |
| security-severity: MEDIUM | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/xss/avoid-default-routes.yaml | |
| category: security | |
| technology: | |
| - rails | |
| - id: ruby_reflection_rule-CheckUnsafeReflectionMethods | |
| mode: taint | |
| pattern-sources: | |
| - pattern-either: | |
| - pattern: 'cookies[...] | |
| ' | |
| - patterns: | |
| - pattern: 'cookies. ... .$PROPERTY[...] | |
| ' | |
| - metavariable-regex: | |
| metavariable: $PROPERTY | |
| regex: (?!signed|encrypted) | |
| - pattern: 'params[...] | |
| ' | |
| - pattern: 'request.env[...] | |
| ' | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: $X | |
| - pattern-either: | |
| - pattern-inside: '$X. ... .to_proc | |
| ' | |
| - patterns: | |
| - pattern-inside: '$Y.method($Z) | |
| ' | |
| - focus-metavariable: $Z | |
| - patterns: | |
| - pattern-inside: '$Y.tap($Z) | |
| ' | |
| - focus-metavariable: $Z | |
| - patterns: | |
| - pattern-inside: '$Y.tap{ |$ANY| $Z } | |
| ' | |
| - focus-metavariable: $Z | |
| message: "The application was found calling a reflection method with user-controllable\n\ | |
| input. This practice can lead to unauthorized alteration of program behavior,\ | |
| \ \nincluding the potential execution of arbitrary code. Reflection methods \n\ | |
| allow dynamic execution of code, which is powerful but risky if not properly \n\ | |
| sanitized, as it could enable attackers to execute unintended methods or \nblocks.\n\ | |
| \nRemediation:\n- Validate and sanitize input: Ensure that any user input is strictly\ | |
| \ \nvalidated against a whitelist of allowed values before being passed to \n\ | |
| reflection methods. Avoid direct mapping of user input to method names \nor proc\ | |
| \ conversions.\n- Limit reflection use: Minimize the use of reflection with user\ | |
| \ input. \nPrefer direct method calls or other non-reflective approaches whenever\ | |
| \ \npossible.\n- Use safer alternatives: When dynamic behavior is necessary, use\ | |
| \ controlled \nmethods like `public_send` with proper input validation to reduce\ | |
| \ risk.\n\nSecure Code Example:\n```\n# Assume user input is to invoke a method\ | |
| \ on an object\nuser_method = params[:method_name]\n\n# Define an allow list of\ | |
| \ permissible methods\nallowed_methods = ['safe_method_1', 'safe_method_2']\n\n\ | |
| if allowed_methods.include?(user_method)\n # Using public_send for controlled\ | |
| \ method invocation\n result = my_object.public_send(user_method)\nelse\n \ | |
| \ raise 'Unauthorized method access'\nend\n```\n" | |
| languages: | |
| - ruby | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Improper control of generation of code ('Code Injection') | |
| category: security | |
| cwe: CWE-94 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: HIGH | |
| technology: | |
| - ruby | |
| - rails | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-unsafe-reflection-methods.yaml | |
| - id: ruby_reflection_rule-CheckUnsafeReflection | |
| mode: taint | |
| pattern-sources: | |
| - pattern-either: | |
| - pattern: 'cookies[...] | |
| ' | |
| - patterns: | |
| - pattern: 'cookies. ... .$PROPERTY[...] | |
| ' | |
| - metavariable-regex: | |
| metavariable: $PROPERTY | |
| regex: (?!signed|encrypted) | |
| - pattern: 'params[...] | |
| ' | |
| - pattern: 'request.env[...] | |
| ' | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: $X | |
| - pattern-either: | |
| - pattern-inside: '$X.constantize | |
| ' | |
| - pattern-inside: '$X. ... .safe_constantize | |
| ' | |
| - pattern-inside: 'const_get(...) | |
| ' | |
| - pattern-inside: 'qualified_const_get(...) | |
| ' | |
| message: "The application was found calling a reflection method with user-controllable\n\ | |
| input. Reflection in Ruby allows a program to examine and modify its own \nstructure\ | |
| \ and behavior at runtime. When user input is used unsafely \nwith reflection\ | |
| \ methods (like `constantize`, `safe_constantize`, `const_get`, \n`qualified_const_get`),\ | |
| \ it poses a significant security risk, potentially \nleading to arbitrary code\ | |
| \ execution.\n\nTo mitigate these risks:\n- Avoid direct user input in reflection:\ | |
| \ Never use user-controllable input \ndirectly with reflection methods.\n- Validate\ | |
| \ and sanitize input: If user input must influence program behavior, \nrigorously\ | |
| \ validate and sanitize the input against a whitelist of allowed \nvalues.\n-\ | |
| \ Use indirect references: Instead of allowing direct specification of class \n\ | |
| or method names, map user inputs to a predefined set of allowed actions or \n\ | |
| classes.\n- Do not provide user-controllable input to reflection functionality.\ | |
| \ \n- Do not call symbol conversion on user-controllable input.\n\nSecure Code\ | |
| \ Example:\n```\nclass SafeClassHandler\n ALLOWED_CLASSES = {\n 'user' =>\ | |
| \ User,\n 'product' => Product\n }.freeze\n\n def self.handle_class_action(class_key)\n\ | |
| \ klass = ALLOWED_CLASSES[class_key]\n raise ArgumentError, \"Invalid class\ | |
| \ key\" unless klass\n\n klass.some_method\n end\nend\n\n# Example usage\n\ | |
| SafeClassHandler.handle_class_action(params[:class_key])\n```\n" | |
| languages: | |
| - ruby | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Improper control of generation of code ('Code Injection') | |
| category: security | |
| cwe: CWE-94 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: HIGH | |
| technology: | |
| - ruby | |
| - rails | |
| references: | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-unsafe-reflection.yaml | |
| - id: ruby_deserialization_rule-BadDeserializationYAML | |
| patterns: | |
| - pattern: 'YAML.$LOAD($...ARGS) | |
| ' | |
| - pattern-not: 'YAML.$LOAD(..., safe: true, ...) | |
| ' | |
| - pattern-not: 'YAML.$LOAD("...", ...) | |
| ' | |
| - pattern-not-inside: '$FILE = File.read("...", ...) | |
| ... | |
| YAML.$LOAD(..., $FILE, ...) | |
| ' | |
| - pattern-not-inside: '$FILENAME = "..." | |
| ... | |
| $FILE = File.read($FILENAME, ...) | |
| ... | |
| YAML.$LOAD(..., $FILE, ...) | |
| ' | |
| - pattern-not-inside: 'YAML.$LOAD(..., File.read("...", ...), ...) | |
| ' | |
| - metavariable-regex: | |
| metavariable: $LOAD | |
| regex: load(?:_stream)?\b|parse_stream | |
| fix: Psych.safe_load($...ARGS) | |
| message: "Unsafe deserialization from YAML. \nYAML is a popular format for configuration\ | |
| \ files in Ruby applications \ndue to its readability and simplicity. However,\ | |
| \ the `load` method \nprovided by Ruby's YAML module can be dangerous when used\ | |
| \ to deserialize \ndata from untrusted sources. The method can instantiate objects\ | |
| \ based \non the YAML input, which can lead to remote code execution (RCE) if\ | |
| \ the \ninput contains malicious code. \n\nTo mitigate the risk of RCE through\ | |
| \ unsafe deserialization practices, \nconsider the following recommendations:\n\ | |
| - Prefer JSON for untrusted data: JSON is generally safer for \ndeserializing\ | |
| \ untrusted data because, by design, it does not support \nthe execution of arbitrary\ | |
| \ code. Ensure that any JSON deserialization \nis performed with caution, validating\ | |
| \ and sanitizing the input before \nuse.\n- Use safe YAML loading methods: If\ | |
| \ you must use YAML, prefer safe \nloading methods like `safe_load` instead of\ | |
| \ `load`. The `safe_load` method \nlimits the objects that can be deserialized,\ | |
| \ reducing the risk of \nexecuting arbitrary code.\n- Static YAML files: Loading\ | |
| \ YAML from static, trusted files (like \nconfiguration files that are not exposed\ | |
| \ to user input) is generally \nsafe. Ensure these files are securely managed\ | |
| \ and not modifiable by \nuntrusted sources.\n\nSecure Code Example:\n```\nrequire\ | |
| \ 'yaml'\nrequire 'json'\n\n# Safe YAML deserialization\ndef safe_load_yaml(file_path)\n\ | |
| \ YAML.safe_load(File.read(file_path), [Date, Time], [], true)\nend\n\n# Example\ | |
| \ of safely loading a static YAML file\nconfig_data = safe_load_yaml('config.yml')\n\ | |
| puts config_data.inspect\n\n# Safe JSON deserialization\ndef safe_load_json(json_input)\n\ | |
| \ # Always validate and sanitize input before deserialization\n JSON.parse(json_input)\n\ | |
| end\n\n# Example JSON input\njson_input = '{\"name\": \"Jack Monroe\", \"age\"\ | |
| : 30}'\nuser_data = safe_load_json(json_input)\nputs user_data.inspect\n```\n" | |
| languages: | |
| - ruby | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Deserialization of untrusted data | |
| category: security | |
| cwe: CWE-502 | |
| owasp: | |
| - A8:2017-Insecure Deserialization | |
| - A08:2021-Software and Data Integrity Failures | |
| security-severity: HIGH | |
| technology: | |
| - ruby | |
| - yaml | |
| references: | |
| - https://groups.google.com/g/rubyonrails-security/c/61bkgvnSGTQ/m/nehwjA8tQ8EJ | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/bad-deserialization-yaml.yaml | |
| - id: ruby_deserialization_rule-BadDeserializationEnv | |
| mode: taint | |
| pattern-sources: | |
| - pattern-either: | |
| - pattern: request.env | |
| pattern-sinks: | |
| - pattern-either: | |
| - pattern: 'Marshal.load(...) | |
| ' | |
| - pattern: 'Marshal.restore(...) | |
| ' | |
| - pattern: 'Oj.object_load(...) | |
| ' | |
| - pattern: 'Oj.load($X) | |
| ' | |
| message: "In Ruby, objects can be serialized into strings using various methods\ | |
| \ \nand later reconstituted into objects. The `load` and `object_load` \nmethods,\ | |
| \ associated with modules like Marshal and CSV, is particularly \nrisky when used\ | |
| \ to deserialize data from untrusted sources. \nIf an attacker is able to manipulate\ | |
| \ the serialized data, they could \nexecute arbitrary code on the system when\ | |
| \ the data is deserialized. \nThis vulnerability can lead to remote code execution\ | |
| \ (RCE), where an \nattacker gains the ability to execute commands on the host\ | |
| \ machine. \nThe Marshal and CSV modules are often used for serialization and\ | |
| \ \ndeserialization in Ruby but they do not inherently sanitize or validate \n\ | |
| the data being processed. This makes them unsafe for handling input from \nuntrusted\ | |
| \ sources.\n\nTo mitigate the risks associated with unsafe deserialization, it\ | |
| \ is \nrecommended to:\n- Avoid deserializing from untrusted sources\n- Use JSON\ | |
| \ for serialization/deserialization as JSON is considered \nsafer for data interchange\ | |
| \ between systems. However, it's crucial \nto use JSON securely by validating\ | |
| \ and sanitizing the input before \ndeserialization.\n\nSecure Code Example:\n\ | |
| ```\nrequire 'json'\n\ndef safe_deserialize(json_data)\n # Validate and sanitize\ | |
| \ json_data before parsing\n begin\n parsed_data = JSON.parse(json_data)\n\ | |
| \ return parsed_data\n rescue JSON::ParserError => e\n puts \"Error parsing\ | |
| \ JSON data: #{e.message}\"\n return nil\n end\nend\n\n# Example usage\n#\ | |
| \ Example of input JSON string\njson_input = '{\"name\": \"John Doe\", \"age\"\ | |
| : 30}' \nuser_data = safe_deserialize(json_input)\nputs user_data.inspect if user_data\n\ | |
| ```\n\nAlways ensure that any data deserialized from JSON (or any format) is \n\ | |
| validated and sanitized according to the context of your application \nto prevent\ | |
| \ injection attacks or other security issues.\n" | |
| languages: | |
| - ruby | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Deserialization of untrusted data | |
| category: security | |
| cwe: CWE-502 | |
| owasp: | |
| - A8:2017-Insecure Deserialization | |
| - A08:2021-Software and Data Integrity Failures | |
| security-severity: HIGH | |
| technology: | |
| - ruby | |
| references: | |
| - https://groups.google.com/g/rubyonrails-security/c/61bkgvnSGTQ/m/nehwjA8tQ8EJ | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/bad-deserialization-env.yaml | |
| - id: ruby_deserialization_rule-BadDeserialization | |
| mode: taint | |
| pattern-sources: | |
| - pattern-either: | |
| - pattern: params | |
| - pattern: cookies | |
| pattern-sinks: | |
| - pattern-either: | |
| - pattern: 'Marshal.load(...) | |
| ' | |
| - pattern: 'Marshal.restore(...) | |
| ' | |
| - pattern: 'Oj.object_load(...) | |
| ' | |
| - pattern: 'Oj.load($X) | |
| ' | |
| message: "In Ruby, objects can be serialized into strings using various methods\ | |
| \ \nand later reconstituted into objects. The `load` and `object_load` \nmethods,\ | |
| \ associated with modules like Marshal and CSV, is particularly \nrisky when used\ | |
| \ to deserialize data from untrusted sources. \nIf an attacker is able to manipulate\ | |
| \ the serialized data, they could \nexecute arbitrary code on the system when\ | |
| \ the data is deserialized. \nThis vulnerability can lead to remote code execution\ | |
| \ (RCE), where an \nattacker gains the ability to execute commands on the host\ | |
| \ machine. \nThe Marshal and CSV modules are often used for serialization and\ | |
| \ \ndeserialization in Ruby but they do not inherently sanitize or validate \n\ | |
| the data being processed. This makes them unsafe for handling input from \nuntrusted\ | |
| \ sources.\n\nTo mitigate the risks associated with unsafe deserialization, it\ | |
| \ is \nrecommended to:\n- Avoid deserializing from untrusted sources\n- Use JSON\ | |
| \ for serialization/deserialization as JSON is considered \nsafer for data interchange\ | |
| \ between systems. However, it's crucial \nto use JSON securely by validating\ | |
| \ and sanitizing the input before \ndeserialization.\n\nSecure Code Example:\n\ | |
| ```\nrequire 'json'\n\ndef safe_deserialize(json_data)\n # Validate and sanitize\ | |
| \ json_data before parsing\n begin\n parsed_data = JSON.parse(json_data)\n\ | |
| \ return parsed_data\n rescue JSON::ParserError => e\n puts \"Error parsing\ | |
| \ JSON data: #{e.message}\"\n return nil\n end\nend\n\n# Example usage\n#\ | |
| \ Example of input JSON string\njson_input = '{\"name\": \"John Doe\", \"age\"\ | |
| : 30}' \nuser_data = safe_deserialize(json_input)\nputs user_data.inspect if user_data\n\ | |
| ```\n\nAlways ensure that any data deserialized from JSON (or any format) is \n\ | |
| validated and sanitized according to the context of your application \nto prevent\ | |
| \ injection attacks or other security issues.\n" | |
| languages: | |
| - ruby | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Deserialization of untrusted data | |
| category: security | |
| cwe: CWE-502 | |
| owasp: | |
| - A8:2017-Insecure Deserialization | |
| - A08:2021-Software and Data Integrity Failures | |
| security-severity: HIGH | |
| technology: | |
| - ruby | |
| references: | |
| - https://groups.google.com/g/rubyonrails-security/c/61bkgvnSGTQ/m/nehwjA8tQ8EJ | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/bad-deserialization.yaml | |
| - id: ruby_session_rule-AvoidSessionManipulation | |
| mode: taint | |
| pattern-sources: | |
| - pattern: params | |
| - pattern: cookies | |
| - pattern: request.env | |
| pattern-sinks: | |
| - pattern: session[...] | |
| message: "The application was found retrieving session data using user input. A\ | |
| \ \nmalicious user may be able to retrieve information from the session \nthat\ | |
| \ was not meant to be allowed. \nSession manipulation can occur when an application\ | |
| \ allows user-input in \nsession keys. Since sessions are typically considered\ | |
| \ a source of truth \n(e.g. to check the logged-in user or to match CSRF tokens),\ | |
| \ allowing an \nattacker to manipulate the session may lead to unintended behavior.\ | |
| \ \n\nTo mitigate this issue, never use user input as a session key. Instead,\ | |
| \ \nconsider an allow list approach to control access to session keys, \nensuring\ | |
| \ only predefined keys are accessible, and user input is not used\nto directly\ | |
| \ access the session key values. \n\nSecure Code Example:\n```\n# Define an allowed\ | |
| \ list of permitted session keys\nALLOWED_SESSION_KEYS = ['display_settings',\ | |
| \ 'locale']\n\nuser_provided_key = params[:key]\n\n# Validate the key against\ | |
| \ the list\nif ALLOWED_SESSION_KEYS.include?(user_provided_key)\n # Access the\ | |
| \ session value safely\n value = session[user_provided_key]\nelse\n raise \"\ | |
| Invalid session key provided.\"\nend\n```\n" | |
| languages: | |
| - ruby | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Incorrect default permissions | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| cwe: CWE-276 | |
| security-severity: CRITICAL | |
| references: | |
| - https://brakemanscanner.org/docs/warning_types/session_manipulation/ | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/avoid-session-manipulation.yaml | |
| category: security | |
| technology: | |
| - rails | |
| - id: ruby_sql_rule-CheckSQL | |
| mode: taint | |
| pattern-sources: | |
| - pattern-either: | |
| - pattern: 'cookies[...] | |
| ' | |
| - patterns: | |
| - pattern: 'cookies. ... .$PROPERTY[...] | |
| ' | |
| - metavariable-regex: | |
| metavariable: $PROPERTY | |
| regex: (?!signed|encrypted) | |
| - pattern: 'params[...] | |
| ' | |
| - pattern: 'request.env[...] | |
| ' | |
| pattern-sanitizers: | |
| - patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern: $X | |
| - pattern-either: | |
| - pattern-inside: ':$KEY => $X | |
| ' | |
| - pattern-inside: '["...",$X,...] | |
| ' | |
| - pattern: 'params[...].to_i | |
| ' | |
| - pattern: 'params[...].to_f | |
| ' | |
| - patterns: | |
| - pattern: 'params[...] ? $A : $B | |
| ' | |
| - metavariable-pattern: | |
| metavariable: $A | |
| patterns: | |
| - pattern-not: 'params[...] | |
| ' | |
| - metavariable-pattern: | |
| metavariable: $B | |
| patterns: | |
| - pattern-not: 'params[...] | |
| ' | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: $X | |
| - pattern-not-inside: '$P.where("...",...) | |
| ' | |
| - pattern-not-inside: '$P.where(:$KEY => $VAL,...) | |
| ' | |
| - pattern-either: | |
| - pattern-inside: '$P.$M(...) | |
| ' | |
| - pattern-inside: '$P.$M("...",...) | |
| ' | |
| - pattern-inside: "class $P < ActiveRecord::Base\n ...\nend\n" | |
| - metavariable-regex: | |
| metavariable: $M | |
| regex: (where|find|first|last|select|minimum|maximum|calculate|sum|average) | |
| message: "SQL Injection is a critical vulnerability that can lead to data or system\ | |
| \ compromise. By\ndynamically generating SQL query strings, user input may be\ | |
| \ able to influence the logic of\nthe SQL statement. This could lead to an adversary\ | |
| \ accessing information they should\nnot have access to, or in some circumstances,\ | |
| \ being able to execute OS functionality or code.\n\nTo mitigate this issue, always\ | |
| \ use parameterized queries or the \nActiveRecord query interface, which ensures\ | |
| \ that inputs are properly \nescaped, preventing SQL injection attacks. Avoid\ | |
| \ string interpolation \nor concatenation with user-controlled input for constructing\ | |
| \ SQL queries.\n\nSecure Code Example:\n```\n# Secure: Using parameterized queries\ | |
| \ with ActiveRecord\nuser_id = params[:id]\nUser.where(\"id = ?\", user_id)\n\n\ | |
| # Secure: Using ActiveRecord's query methods, which automatically handle parameterization\n\ | |
| # Converting to integer as an additional layer of input sanitization\nuser_id\ | |
| \ = params[:id].to_i \nUser.where(id: user_id)\n```\n" | |
| languages: | |
| - ruby | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Improper neutralization of special elements used in a SQL command | |
| ('SQL Injection') | |
| category: security | |
| cwe: CWE-89 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: HIGH | |
| technology: | |
| - ruby | |
| - rails | |
| references: | |
| - https://owasp.org/www-community/attacks/SQL_Injection | |
| - https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-sql.yaml | |
| - id: rules_lgpl_javascript_jwt_rule-hardcoded-jwt-secret | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: 'const $JWT = require("jsonwebtoken"); | |
| ... | |
| ' | |
| - pattern-inside: 'const $JOSE = require("jose"); | |
| ... | |
| ' | |
| - pattern-inside: 'import $JWT from "jsonwebtoken" | |
| ... | |
| ' | |
| - pattern-inside: 'import $JOSE from "jose" | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: $JWT.sign($PAYLOAD, "...", ...) | |
| - pattern: $JWT.verify($PAYLOAD, "...", ...) | |
| - pattern: new $JOSE.SignJWT(...). ... .sign("...") | |
| - pattern: 'var $TOKEN = new $JOSE.SignJWT(...). ... | |
| ... | |
| $TOKEN. ... .sign("...") | |
| ' | |
| - pattern: $JOSE.jwtVerify( $TKN, "...", ... ) | |
| - patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: "var $KEY = $X\n ...\n" | |
| - pattern-either: | |
| - pattern: new $JOSE.SignJWT(...). ... .sign($KEY) | |
| - patterns: | |
| - pattern: 'var $TOKEN = new $JOSE.SignJWT(...). ... | |
| ... | |
| $TOKEN. ... .sign($KEY) | |
| ' | |
| - pattern: $TOKEN. ... .sign($KEY) | |
| - pattern: $JOSE.jwtVerify( $TKN, $KEY, ... ) | |
| - pattern: new $JOSE.SignJWT(...). ... .sign($X) | |
| - patterns: | |
| - pattern: 'var $TOKEN = new $JOSE.SignJWT(...). ... | |
| ... | |
| $TOKEN. ... .sign($X) | |
| ' | |
| - pattern: $TOKEN. ... .sign($X) | |
| - pattern: $JOSE.jwtVerify( $TKN, $X, ... ) | |
| - metavariable-pattern: | |
| metavariable: $X | |
| pattern-either: | |
| - pattern: new TextEncoder().encode( "...",... ) | |
| - pattern: Uint8Array.from("...", ...) | |
| message: "Hardcoded JWT secret or private key was found. Hardcoding secrets like\ | |
| \ JWT signing keys poses a significant security risk. \nIf the source code ends\ | |
| \ up in a public repository or is compromised, the secret is exposed. Attackers\ | |
| \ could then use the secret to \ngenerate forged tokens and access the system.\ | |
| \ Store it properly in an environment variable.\n\nHere are some recommended safe\ | |
| \ ways to access JWT secrets:\n - Use environment variables to store the secret\ | |
| \ and access it in code instead of hardcoding. This keeps it out of source control.\n\ | |
| \ - Use a secrets management service to securely store and tightly control access\ | |
| \ to the secret. Applications can request the secret at runtime.\n - For local\ | |
| \ development, use a .env file that is gitignored and access the secret from process.env.\n\ | |
| \nsample code snippet of accessing JWT secret from env variables\n```\n const\ | |
| \ token = jwt.sign(payload, process.env.SECRET, { algorithm: 'HS256' });\n```\n" | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-798 | |
| shortDescription: Use of hard-coded credentials | |
| security-severity: HIGH | |
| category: security | |
| - id: rules_lgpl_javascript_jwt_rule-jwt-exposed-credentials | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: 'const $JWT = require("jsonwebtoken"); | |
| ... | |
| ' | |
| - pattern-inside: 'const $JOSE = require("jose"); | |
| ... | |
| ' | |
| - pattern-inside: 'import $JWT from "jsonwebtoken" | |
| ... | |
| ' | |
| - pattern-inside: 'import $JOSE from "jose" | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: '$JWT.sign(<... {$PASSWORD: $VALUE} ...>, ...)' | |
| - patterns: | |
| - pattern: '$OBJ = <... {$PASSWORD: $VALUE} ...> | |
| ... | |
| $TOKEN = $JWT.sign(<... $OBJ ...>, ...) | |
| ' | |
| - pattern: $TOKEN = $JWT.sign(<... $OBJ ...>, ...) | |
| - patterns: | |
| - pattern: '$OBJ. ... .$PASSWORD = ... | |
| ... | |
| $TOKEN = $JWT.sign(<... $OBJ ...>, ...) | |
| ' | |
| - pattern: $TOKEN = $JWT.sign(<... $OBJ ...>, ...) | |
| - pattern: 'new $JOSE.SignJWT(<... {$PASSWORD: $VALUE} ...>)' | |
| - patterns: | |
| - pattern: '$OBJ = <... {$PASSWORD: $VALUE} ...> | |
| ... | |
| new $JOSE.SignJWT(<... $OBJ ...>) | |
| ' | |
| - pattern: new $JOSE.SignJWT(<... $OBJ ...>) | |
| - patterns: | |
| - pattern: '$OBJ. ... .$PASSWORD = ... | |
| ... | |
| new $JOSE.SignJWT(<... $OBJ ...>) | |
| ' | |
| - pattern: new $JOSE.SignJWT(<... $OBJ ...>) | |
| - metavariable-regex: | |
| metavariable: $PASSWORD | |
| regex: (?i)\b(?:.*password.*)\b | |
| severity: ERROR | |
| languages: | |
| - javascript | |
| metadata: | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-522 | |
| shortDescription: Insufficiently protected credentials | |
| security-severity: HIGH | |
| category: security | |
| message: "The application is storing a password in the JWT token payload. Storing\ | |
| \ \npasswords in JWT token payloads is an insecure practice that can lead to \n\ | |
| compromised credentials. \n\nThe password transmitted in the JWT payload is not\ | |
| \ encrypted and therefore \nvisible to anyone who intercepts the token. It is\ | |
| \ recommended to avoid storing \nsensitive information like passwords in JWTs.\ | |
| \ Instead, reference user identifiers \nthat map to credentials stored securely\ | |
| \ on the server.This helps to mitigate the \nrisk of exposing passwords through\ | |
| \ JWT tokens that could be intercepted or leaked.\n\nSecure code example of secure\ | |
| \ JWT signing:\n```\nrouter.route(\"/jsonwebtoken/1\").get((req, res) => {\n \ | |
| \ // any payload without passwords or any other sensitive data will be secure\n\ | |
| \ const payload = { user_id: 123, username: 'john_doe' };\n const token = jwt.sign(payload,\ | |
| \ secretKey, { algorithm: 'HS256' });\n console.log('Generated Token:', token);\n\ | |
| \ res.send({ token })\n})\n```" | |
| - id: rules_lgpl_javascript_jwt_rule-jwt-exposed-data | |
| patterns: | |
| - pattern-inside: 'require(''jose'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: function (...,$INPUT,...) {...} | |
| - pattern-either: | |
| - pattern: $JOSE.JWT.sign($INPUT,...) | |
| - pattern: $JWT.sign($INPUT,...) | |
| - patterns: | |
| - pattern-inside: function $F(...,$INPUT,...) {...} | |
| - pattern-either: | |
| - pattern: $JOSE.JWT.sign($INPUT,...) | |
| - pattern: $JWT.sign($INPUT,...) | |
| message: 'The object is passed strictly to jose.JWT.sign(...). Make sure that sensitive | |
| information is not exposed through JWT token payload. | |
| ' | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-522 | |
| shortDescription: Insufficiently protected credentials | |
| security-severity: HIGH | |
| category: security | |
| languages: | |
| - javascript | |
| - id: rules_lgpl_javascript_jwt_rule-jwt-not-revoked | |
| patterns: | |
| - pattern-inside: '$JWT = require(''express-jwt'') | |
| ... | |
| ' | |
| - pattern: $JWT(...) | |
| - pattern-not-inside: $JWT(<... {isRevoked:...} ...>,...) | |
| - pattern-not-inside: '$OPTS = <... {isRevoked:...} ...>; | |
| ... | |
| $JWT($OPTS,...)' | |
| message: 'No token revoking configured for `express-jwt`. A leaked token could still | |
| be used and unable to be revoked. Consider using function as the `isRevoked` option. | |
| ' | |
| severity: WARNING | |
| languages: | |
| - javascript | |
| metadata: | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-522 | |
| shortDescription: Insufficiently protected credentials | |
| security-severity: HIGH | |
| category: security | |
| - id: rules_lgpl_javascript_jwt_rule-node-jwt-none-algorithm | |
| mode: taint | |
| pattern-sources: | |
| - pattern: $JWT = require("jsonwebtoken") | |
| - pattern: import $JWT from "jsonwebtoken" | |
| pattern-sinks: | |
| - pattern: $JWT.verify($P, $X, {...,algorithms:[...,'none',...],...},...) | |
| - pattern: $JWT.sign($P, $X, {...,algorithm:'none',...},...) | |
| message: "Use of `{algorithm:'none'}` detected with `jsonwebtoken`. \nUsing none\ | |
| \ as the algorithm for jsonwebtoken can directly impact the integrity of the information\ | |
| \ transfer through the JWT token.\nConsider using a secure algorithm to sign your\ | |
| \ JWT token such as HMAC or RSA.\nSome safe usage examples:\n```\nlet token =\ | |
| \ jwt.sign({user:\"user1\"}, 'secret', {algorithm: 'HS256'}); \n```\nUsing a\ | |
| \ secure algorithm can protect the integrity of the token information. \nAvoid\ | |
| \ using none as the algorithm when signing jwt tokens since it can violate the\ | |
| \ integrity of the JWT information.\n" | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-327 | |
| shortDescription: Use of a broken or risky cryptographic algorithm | |
| security-severity: CRITICAL | |
| category: security | |
| - id: rules_lgpl_javascript_jwt_rule-jwt-express-hardcoded | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: 'import { ..., $JWT,... } from ''express-jwt''; | |
| ... | |
| ' | |
| - pattern-inside: 'var {..., expressjwt: $JWT,... } = require(''express-jwt''); | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: $JWT(<...{...,secret:"...",...}...>) | |
| - patterns: | |
| - pattern-inside: '$OPTS = <... {secret: "..."} ...>; | |
| ... | |
| ' | |
| - pattern: $JWT(<... $OPTS ...>,...) | |
| - patterns: | |
| - pattern-inside: '$OPTS = <... {secret: "..."} ...>; | |
| ... | |
| $OPTS2 = <... $OPTS ...>; | |
| ... | |
| ' | |
| - pattern: $JWT(<... $OPTS2 ...>,...) | |
| message: "Hardcoded JWT secret or private key was found. Hardcoding secrets like\ | |
| \ JWT signing keys poses a significant security risk. \nIf the source code ends\ | |
| \ up in a public repository or is compromised, the secret is exposed. Attackers\ | |
| \ could then use the secret to \ngenerate forged tokens and access the system.\ | |
| \ Store it properly in an environment variable.\n\nHere are some recommended safe\ | |
| \ ways to access JWT secrets:\n - Use environment variables to store the secret\ | |
| \ and access it in code instead of hardcoding. This keeps it out of source control.\n\ | |
| \ - Use a secrets management service to securely store and tightly control access\ | |
| \ to the secret. Applications can request the secret at runtime.\n - For local\ | |
| \ development, use a .env file that is gitignored and access the secret from process.env.\n\ | |
| \nsample code snippet of accessing JWT secret from env variables\n```\nrouter.route(\"\ | |
| /auth-route-1\").get(\n jwt({ secret: process.env.secret, algorithms: ['HS256']\ | |
| \ }),\n (req, res) => {\n res.send('Token is valid');\n }\n);\n```\n" | |
| severity: ERROR | |
| languages: | |
| - javascript | |
| metadata: | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-522 | |
| shortDescription: Insufficiently protected credentials | |
| security-severity: CRITICAL | |
| category: security | |
| - id: rules_lgpl_javascript_ssrf_rule-wkhtmltoimage-ssrf | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern: "function($REQ, $RES, ...){\n ...\n}\n" | |
| - focus-metavariable: $REQ | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: '$W = require(''wkhtmltoimage'') | |
| ... | |
| ' | |
| - pattern-inside: 'import $W from ''wkhtmltoimage'' | |
| ... | |
| ' | |
| - pattern: '$W.generate(...) | |
| ' | |
| pattern-sanitizers: | |
| - patterns: | |
| - pattern-inside: "if($ALLOWED.includes($URL)){\n ...\n}\n" | |
| message: "This rule detects instances where user-controlled URLs are passed directly\n\ | |
| to the `generate` function of `wkhtmltoimage` library. This practice can\nlead\ | |
| \ to Server Side Request Forgery (SSRF) vulnerabilities, where an\nattacker can\ | |
| \ induce the server to make requests to arbitrary URLs. This\ncan potentially\ | |
| \ expose internal services within the network or lead to\ninformation disclosure.\n\ | |
| \nTo mitigate this vulnerability, ensure that URLs are safe and intended for \n\ | |
| public access. Implementing allowlists for acceptable domains or schemes can \n\ | |
| significantly reduce the risk of SSRF. Additionally, consider using server-side\ | |
| \ \nproxy services that restrict the outgoing requests to trusted domains and\ | |
| \ \nresources.\n\nSecure Code Example:\n```\nconst wkhtmltoimage = require('wkhtmltoimage');\n\ | |
| \n// Define an allowlist of domains\nconst allowedDomains = ['example.com', 'trusted-source.com'];\n\ | |
| \napp.post('/generate-image', (req, res) => {\n const userInputUrl = req.body.url;\ | |
| \ \n const parsedUrl = new URL(userInputUrl);\n\n // Check if the domain is\ | |
| \ in the allowlist\n if (allowedDomains.includes(parsedUrl.hostname)) {\n \ | |
| \ wkhtmltoimage.generate(userInputUrl, { output: 'output.jpg' }, \n function\ | |
| \ (err, stream) {\n if (err) {\n return res.status(500).send('Error\ | |
| \ generating image');\n }\n // Send a success response or the\ | |
| \ image itself\n res.status(200).send('Image generated successfully');\n\ | |
| \ });\n } else {\n res.status(400).send('URL is not allowed due to\ | |
| \ security policies.');\n }\n});\n```\n" | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A1:2017-Injection | |
| - A10:2021-Server-Side Request Forgery | |
| cwe: CWE-918 | |
| shortDescription: Server-side request forgery (SSRF) | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_ssrf_rule-playwright-ssrf | |
| patterns: | |
| - pattern-inside: 'require(''playwright'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: $PAGE.goto(<... $REQ.$QUERY.$FOO ...>, ...) | |
| - pattern: $PAGE.goto(<... $REQ.$BODY ...>, ...) | |
| - pattern: $PAGE.setContent(<... $REQ.$QUERY.$FOO ...>, ...) | |
| - pattern: $PAGE.setContent(<... $REQ.$BODY ...>, ...) | |
| - pattern: $PAGE.evaluate(<... $REQ.$QUERY.$FOO ...>, ...) | |
| - pattern: $PAGE.evaluate(<... $REQ.$BODY ...>, ...) | |
| - pattern: $PAGE.evaluate($CODE,..., <... $REQ.$QUERY.$FOO ...>, ...) | |
| - pattern: $PAGE.evaluate($CODE,..., <... $REQ.$BODY ...>, ...) | |
| - pattern: $PAGE.evaluateHandle(<... $REQ.$QUERY.$FOO ...>, ...) | |
| - pattern: $PAGE.evaluateHandle(<... $REQ.$BODY ...>, ...) | |
| - pattern: $PAGE.evaluateHandle($CODE,..., <... $REQ.$QUERY.$FOO ...>, ...) | |
| - pattern: $PAGE.evaluateHandle($CODE,..., <... $REQ.$BODY ...>, ...) | |
| - pattern: $PAGE.evaluateOnNewDocument(<... $REQ.$BODY ...>, ...) | |
| - pattern: $PAGE.evaluateOnNewDocument(<... $REQ.$BODY.$FOO ...>, ...) | |
| - pattern: $CONTEXT.addInitScript(<... $REQ.$BODY ...>,...) | |
| - pattern: $CONTEXT.addInitScript(<... $REQ.$BODY.$FOO ...>,...) | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.goto(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.goto(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.setContent(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.setContent(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.evaluate($CODE,..., <... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.evaluate($CODE,..., <... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.evaluate(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.evaluate(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.evaluateHandle(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.evaluateHandle(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.evaluateHandle($CODE,..., <... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.evaluateHandle($CODE,..., <... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.evaluateOnNewDocument(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.evaluateOnNewDocument(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $CONTEXT.addInitScript($INPUT,...) | |
| ' | |
| message: 'If unverified user data can reach the `puppeteer` methods it can result | |
| in Server-Side Request Forgery vulnerabilities. | |
| ' | |
| metadata: | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-918 | |
| shortDescription: Server-side request forgery (SSRF) | |
| security-severity: CRITICAL | |
| category: security | |
| severity: ERROR | |
| languages: | |
| - javascript | |
| - id: rules_lgpl_javascript_ssrf_rule-phantom-ssrf | |
| patterns: | |
| - pattern-inside: 'require(''phantom'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: $PAGE.open(<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $PAGE.setContent(<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $PAGE.open(<... $REQ.$BODY ...>,...) | |
| - pattern: $PAGE.setContent(<... $REQ.$BODY ...>,...) | |
| - pattern: $PAGE.openUrl(<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $PAGE.openUrl(<... $REQ.$BODY ...>,...) | |
| - pattern: $PAGE.evaluateJavaScript(<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $PAGE.evaluateJavaScript(<... $REQ.$BODY ...>,...) | |
| - pattern: $PAGE.property("content",<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $PAGE.property("content",<... $REQ.$BODY ...>,...) | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.open(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.open(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.setContent(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.setContent(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.openUrl(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.openUrl(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.evaluateJavaScript(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.evaluateJavaScript(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.property("content",<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.property("content",<... $INPUT ...>,...)' | |
| message: '''If unverified user data can reach the `phantom` methods it can result | |
| in Server-Side Request Forgery vulnerabilities. | |
| '' | |
| ' | |
| metadata: | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-918 | |
| shortDescription: Server-side request forgery (SSRF) | |
| security-severity: CRITICAL | |
| category: security | |
| severity: ERROR | |
| languages: | |
| - javascript | |
| - id: rules_lgpl_javascript_ssrf_rule-node-ssrf | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - focus-metavariable: $REQ | |
| - pattern: function ($REQ, $RES, ...) {...} | |
| - patterns: | |
| - focus-metavariable: $REQ | |
| - pattern: function $FUNC($REQ, $RES, ...) {...} | |
| pattern-sanitizers: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: "if($VALIDATION){\n...\n} \n" | |
| - pattern: '$A = $VALIDATION | |
| ... | |
| if($A){ | |
| ... | |
| } | |
| ' | |
| - metavariable-pattern: | |
| metavariable: $VALIDATION | |
| pattern-either: | |
| - pattern: "$AL.includes(...) \n" | |
| - pattern: '$AL.indexOf(...) !== -1 | |
| ' | |
| - pattern: '$AL.find(...) !== undefined | |
| ' | |
| - pattern: '$ALS.has(...) | |
| ' | |
| pattern-sinks: | |
| - patterns: | |
| - focus-metavariable: $REQ | |
| - pattern-either: | |
| - pattern-inside: '$NEEDLE = require(''needle''); | |
| ... | |
| ' | |
| - pattern-inside: 'import $NEEDLE from ''needle'' | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: $NEEDLE('$VERB', $REQ, ...) | |
| - pattern: $NEEDLE.$VERB($REQ, ...) | |
| - metavariable-regex: | |
| metavariable: $VERB | |
| regex: ^(get|put|post|patch|delete|head)$ | |
| - patterns: | |
| - focus-metavariable: $REQ | |
| - pattern-either: | |
| - pattern-inside: '$AXIOS = require(''axios''); | |
| ... | |
| ' | |
| - pattern-inside: 'import $AXIOS from ''axios'' | |
| ... | |
| ' | |
| - pattern-either: | |
| - patterns: | |
| - metavariable-regex: | |
| metavariable: $URL | |
| regex: ^(url|baseURL)$ | |
| - pattern-either: | |
| - pattern: '$AXIOS({ ..., $URL: $REQ, ...}) | |
| ' | |
| - pattern: '$AXIOS.create({ ..., $URL: $REQ, ...}) | |
| ' | |
| - patterns: | |
| - pattern: $AXIOS.$VERB($REQ, ...) | |
| - metavariable-regex: | |
| metavariable: $VERB | |
| regex: ^(get|put|post|patch|delete|head)$ | |
| - patterns: | |
| - pattern: axios($REQ) | |
| - pattern-not-inside: axios({...}) | |
| - pattern: 'axios.defaults.baseURL = $REQ | |
| ' | |
| - patterns: | |
| - focus-metavariable: $URL | |
| - pattern-either: | |
| - pattern-inside: '{..., request, ... } = require(''urllib''); | |
| ... | |
| ' | |
| - pattern-inside: 'import {..., request, ... } from ''urllib'' | |
| ... | |
| ' | |
| - pattern: request($URL, ...) | |
| - patterns: | |
| - focus-metavariable: $URL | |
| - pattern-either: | |
| - pattern-inside: '{..., HttpClient, ... } = require(''urllib''); | |
| ... | |
| ' | |
| - pattern-inside: 'import {..., HttpClient, ... } from ''urllib'' | |
| ... | |
| ' | |
| - pattern: "$HTTPCLIENT = new HttpClient({\n allowH2: true,\n\ | |
| \ });\n...\n$HTTPCLIENT.request($URL, ...)\n" | |
| - patterns: | |
| - focus-metavariable: $URL | |
| - pattern-either: | |
| - pattern-inside: '$URLLIIB = require(''urllib''); | |
| ... | |
| ' | |
| - pattern-inside: 'import $URLLIIB from ''urllib'' | |
| ... | |
| ' | |
| - pattern: $URLLIIB.request($URL, ...) | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: "$SA = require('superagent');\n ...\n" | |
| - pattern-inside: 'import $SA from ''superagent'' | |
| ... | |
| ' | |
| - patterns: | |
| - pattern: $SA.$VERB(...) | |
| - metavariable-regex: | |
| metavariable: $VERB | |
| regex: ^(get|put|post|patch|delete|head)$ | |
| - patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern: fetch($REQ,...) | |
| - focus-metavariable: $REQ | |
| - pattern-not: fetch(new Request(...)) | |
| - patterns: | |
| - pattern: fetch(new Request($REQ,...)) | |
| - focus-metavariable: $REQ | |
| - pattern-not-inside: '$REQUEST_OBJ = new Request(...) | |
| ... | |
| fetch($REQUEST_OBJ) | |
| ' | |
| - patterns: | |
| - pattern: new Request($REQ,...) | |
| - focus-metavariable: $REQ | |
| - pattern-inside: '$REQUEST_OBJ = new Request($REQ,...) | |
| ... | |
| fetch($REQUEST_OBJ) | |
| ' | |
| - patterns: | |
| - focus-metavariable: $REQ | |
| - pattern-either: | |
| - pattern-inside: '$HTTP = require(''$PKG''); | |
| ... | |
| ' | |
| - pattern-inside: 'import $HTTP from $PKG | |
| ... | |
| ' | |
| - metavariable-regex: | |
| metavariable: $PKG | |
| regex: ^(http|https)$ | |
| - metavariable-regex: | |
| metavariable: $METHOD | |
| regex: ^(get|request)$ | |
| - pattern-either: | |
| - patterns: | |
| - pattern: $HTTP.$METHOD($REQ, ...) | |
| - pattern-not-inside: '$HTTP.$METHOD({...}, ...) | |
| ' | |
| - pattern-not-inside: '$OPTS = {...} | |
| ... | |
| $HTTP.$METHOD($OPTS, ...) | |
| ' | |
| - pattern: '$HTTP.$METHOD({..., hostname: $REQ}, ...) | |
| ' | |
| - pattern: '$OPTS = {..., hostname: $REQ, ...} | |
| ... | |
| $HTTP.$METHOD($OPTS, ...) | |
| ' | |
| - patterns: | |
| - focus-metavariable: $REQ | |
| - pattern-either: | |
| - pattern-inside: '{ ..., io, ... } = require(''socket.io-client''); | |
| ... | |
| ' | |
| - pattern-inside: 'import { ..., io, ... } from ''socket.io-client'' | |
| ... | |
| ' | |
| - pattern: io($REQ, ...) | |
| - patterns: | |
| - focus-metavariable: $HOST | |
| - pattern-either: | |
| - pattern-inside: '$NET = require(''net''); | |
| ... | |
| ' | |
| - pattern-inside: 'import $NET from ''net'' | |
| ... | |
| ' | |
| - metavariable-regex: | |
| metavariable: $METHOD | |
| regex: ^(connect|createConnection)$ | |
| - pattern-either: | |
| - pattern: $NET.$METHOD($PORT, $HOST, ...) | |
| - pattern: '$NET.$METHOD({..., host: $HOST, ...}, ...) | |
| ' | |
| - pattern: '$OPTS = {..., host: $HOST, ...} | |
| ... | |
| $NET.$METHOD($OPTS, ...) | |
| ' | |
| - pattern: '$CLIENT = new $NET.Socket() | |
| ... | |
| $CLIENT.$METHOD($PORT, $HOST, ...) | |
| ' | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: '$BENT = require(''bent''); | |
| ... | |
| ' | |
| - pattern-inside: 'import $BENT from ''bent''; | |
| ... | |
| ' | |
| - pattern: $BENT(...) | |
| - patterns: | |
| - focus-metavariable: $REQ | |
| - pattern-either: | |
| - pattern-inside: '$BENT = require(''bent''); | |
| ... | |
| $MTD = $BENT(...) | |
| ' | |
| - pattern-inside: 'import $BENT from ''bent''; | |
| ... | |
| $MTD = $BENT(...) | |
| ' | |
| - pattern: $MTD($REQ, ...) | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: '$BENT = require(''bent''); | |
| ... | |
| $GETBENT = $BENT(''$PKG'') | |
| ... | |
| ' | |
| - pattern-inside: 'import $BENT from ''bent''; | |
| ... | |
| $GETBENT = $BENT(''$PKG'') | |
| ... | |
| ' | |
| - pattern: $GETBENT(...) | |
| - metavariable-regex: | |
| metavariable: $PKG | |
| regex: ^(json|buffer)$ | |
| - patterns: | |
| - focus-metavariable: $REQ | |
| - pattern-either: | |
| - pattern-inside: 'import $GOT from ''got''; | |
| ... | |
| ' | |
| - pattern: $GOT.$VERB($REQ, ...) | |
| - metavariable-regex: | |
| metavariable: $VERB | |
| regex: ^(get|put|post|patch|delete|head)$ | |
| - patterns: | |
| - focus-metavariable: $URL | |
| - pattern-either: | |
| - pattern-inside: '$REQUEST = require(''request''); | |
| ... | |
| ' | |
| - pattern-inside: 'import $REQUEST from ''request''; | |
| ... | |
| ' | |
| - pattern: $REQUEST($URL, ...) | |
| message: "This application allows user-controlled URLs to be passed directly to\ | |
| \ HTTP client libraries. \nThis can result in Server-Side Request Forgery (SSRF).\n\ | |
| SSRF refers to an attack where the attacker can abuse functionality on \nthe server\ | |
| \ to force it to make requests to other internal systems within your \ninfrastructure\ | |
| \ that are not directly exposed to the internet. \nThis allows the attacker to\ | |
| \ access internal resources they do not have direct access to.\n\nSome risks of\ | |
| \ SSRF are:\n\n- Access and manipulation of internal databases, APIs, or administrative\ | |
| \ panels\n- Ability to scan internal network architecture and services\n- Can\ | |
| \ be used to pivot attacks into the internal network\n- Circumvent network segregation\ | |
| \ and firewall rules\n\nTo avoid this, try using hardcoded HTTP request calls\ | |
| \ or a whitelisting object to \ncheck whether the user input is trying to access\ | |
| \ allowed resources or not.\n\nHere is an example:\n```\nvar whitelist = [\n \ | |
| \ \"https://example.com\", \n \"https://example.com/sample\"\n]\n\napp.get('/ssrf/node-ssrf/axios/safe/3',\ | |
| \ function (req, res) {\n if(whitelist.includes(req.query.url)){\n axios.get(url,\ | |
| \ {})\n .then(function (response) {\n console.log(response);\n\ | |
| \ })\n .catch(function (response) {\n console.log(response);\ | |
| \ \n })\n }\n});\n``` \nFor more information on SSRF see OWASP:\nhttps://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html\n" | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-918 | |
| shortDescription: Server-side request forgery (SSRF) | |
| security-severity: HIGH | |
| category: security | |
| - id: rules_lgpl_javascript_ssrf_rule-wkhtmltopdf-ssrf | |
| patterns: | |
| - pattern-inside: 'require(''wkhtmltopdf'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: '$INP = <... $REQ.$VAR ...>; | |
| ... | |
| wkhtmltopdf(<... $INP ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$VAR.$FOO ...>; | |
| ... | |
| wkhtmltopdf(<... $INP ...>, ...) | |
| ' | |
| - pattern: 'wkhtmltopdf(<... $REQ.$VAR ...>, ...) | |
| ' | |
| - pattern: 'wkhtmltopdf(<... $REQ.$VAR.$FOO ...>, ...) | |
| ' | |
| message: 'User controlled URL reached to `wkhtmltopdf` can result in Server Side | |
| Request Forgery (SSRF). | |
| ' | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-918 | |
| shortDescription: Server-side request forgery (SSRF) | |
| security-severity: CRITICAL | |
| category: security | |
| - id: rules_lgpl_javascript_ssrf_rule-puppeteer-ssrf | |
| patterns: | |
| - pattern-inside: 'require(''puppeteer'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: $PAGE.goto(<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $PAGE.goto(<... $REQ.$BODY ...>,...) | |
| - pattern: $PAGE.setContent(<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $PAGE.setContent(<... $REQ.$BODY ...>,...) | |
| - pattern: $PAGE.evaluate(<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $PAGE.evaluate(<... $REQ.$BODY ...>,...) | |
| - pattern: $PAGE.evaluateHandle(<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $PAGE.evaluateHandle(<... $REQ.$BODY ...>,...) | |
| - pattern: $PAGE.evaluateOnNewDocument(<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $PAGE.evaluateOnNewDocument(<... $REQ.$BODY ...>,...) | |
| - pattern: $PAGE.evaluate($CODE,<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $PAGE.evaluate($CODE,<... $REQ.$BODY ...>,...) | |
| - pattern: $PAGE.evaluateHandle($CODE,<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $PAGE.evaluateHandle($CODE,<... $REQ.$BODY ...>,...) | |
| - pattern: $PAGE.evaluateOnNewDocument($CODE,<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $PAGE.evaluateOnNewDocument($CODE,<... $REQ.$BODY ...>,...) | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.goto(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.goto(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.setContent(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.setContent(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.evaluate(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.evaluate(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.evaluateHandle(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.evaluateHandle(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.evaluateOnNewDocument(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.evaluateOnNewDocument(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.evaluate($CODE,<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.evaluate($CODE,<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.evaluateHandle($CODE,<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.evaluateHandle($CODE,<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PAGE.evaluateOnNewDocument($CODE,<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PAGE.evaluateOnNewDocument($CODE,<... $INPUT ...>,...) | |
| ' | |
| message: 'If unverified user data can reach the `puppeteer` methods it can result | |
| in Server-Side Request Forgery vulnerabilities. | |
| ' | |
| metadata: | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-918 | |
| shortDescription: Server-side request forgery (SSRF) | |
| security-severity: CRITICAL | |
| category: security | |
| severity: ERROR | |
| languages: | |
| - javascript | |
| - id: rules_lgpl_javascript_database_rule-node-nosqli-injection | |
| patterns: | |
| - pattern-not-inside: '$SANITIZE = require(''mongo-sanitize'') | |
| ... | |
| $SANITIZE(...) | |
| ... | |
| ' | |
| - pattern-not-inside: 'import $SANITIZE from ''mongo-sanitize'' | |
| ... | |
| $SANITIZE(...) | |
| ... | |
| ' | |
| - pattern-not: '$OBJ.findOne({$KEY : String(...).$FUNC()}, ...) | |
| ' | |
| - pattern-not: '$OBJ.findOne({$KEY : String(...).$FUNC}, ...) | |
| ' | |
| - pattern-not: '$OBJ.findOne({$KEY : String(...)}, ...) | |
| ' | |
| - pattern-either: | |
| - pattern: '$OBJ.findOne({$KEY : <... $REQ.$FOO.$BAR ...> }, ...) | |
| ' | |
| - pattern: '$OBJ.findOne({$KEY: <... $REQ.$FOO ...> }, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$FOO.$BAR ...>; | |
| ... | |
| $OBJ.findOne({$KEY : <... $INP ...> }, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$FOO ...>; | |
| ... | |
| $OBJ.findOne({$KEY: <... $INP ...> }, ...) | |
| ' | |
| - pattern: '$QUERY = {$KEY: <... $REQ.$FOO.$BAR ...>}; | |
| ... | |
| $OBJ.findOne($QUERY, ...) | |
| ' | |
| - pattern: '$QUERY = {$KEY: <... $REQ.$FOO ...>}; | |
| ... | |
| $OBJ.findOne($QUERY, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$FOO.$BAR ...>; | |
| ... | |
| $QUERY = {$KEY : <... $INP ...> }; | |
| ... | |
| $OBJ.findOne(<... $QUERY ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$FOO ...>; | |
| ... | |
| $QUERY = {$KEY : <... $INP ...> }; | |
| ... | |
| $OBJ.findOne(<... $QUERY ...>, ...) | |
| ' | |
| - pattern: '$QUERY[$KEY] = <... $REQ.$FOO.$BAR ...>; | |
| ... | |
| $OBJ.findOne($QUERY, ...) | |
| ' | |
| - pattern: '$QUERY[$KEY] = <... $REQ.$FOO ...>; | |
| ... | |
| $OBJ.findOne($QUERY, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$FOO.$BAR ...>; | |
| ... | |
| $QUERY[$KEY] = <... $INP ...>; | |
| ... | |
| $OBJ.findOne(<... $QUERY ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$FOO ...>; | |
| ... | |
| $QUERY[$KEY] = <... $INP ...>; | |
| ... | |
| $OBJ.findOne(<... $QUERY ...>, ...) | |
| ' | |
| message: 'Untrusted user input in findOne() function can result in NoSQL Injection. | |
| ' | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-943 | |
| shortDescription: Improper neutralization of special elements in data query logic | |
| security-severity: CRITICAL | |
| category: security | |
| - id: rules_lgpl_javascript_database_rule-node-knex-sqli-injection | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: '$KNEX = require(''knex'') | |
| ... | |
| ' | |
| - pattern-inside: '$KNEX = require(''knex'')(...) | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: '$K.raw(<... $REQ.$QUERY.$VAR ...>, ...) | |
| ' | |
| - pattern: '$K.raw(<... $REQ.$QUERY ...>, ...) | |
| ' | |
| - pattern: '$SQL = <... $REQ.$QUERY.$VAR ...>; | |
| ... | |
| $K.raw(<... $SQL ...>, ...) | |
| ' | |
| - pattern: '$SQL = <... $REQ.$QUERY ...>; | |
| ... | |
| $K.raw(<... $SQL ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY.$VAR ...>; | |
| ... | |
| $SQL = <... $INP ...>; | |
| ... | |
| $K.raw(<... $SQL ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY ...>; | |
| ... | |
| $SQL = <... $INP ...>; | |
| ... | |
| $K.raw(<... $SQL ...>, ...) | |
| ' | |
| - pattern: '$K.whereRaw(<... $REQ.$QUERY.$VAR ...>, ...) | |
| ' | |
| - pattern: '$K.whereRaw(<... $REQ.$QUERY ...>, ...) | |
| ' | |
| - pattern: '$SQL = <... $REQ.$QUERY.$VAR ...>; | |
| ... | |
| $K.whereRaw(<... $SQL ...>, ...) | |
| ' | |
| - pattern: '$SQL = <... $REQ.$QUERY ...>; | |
| ... | |
| $K.whereRaw(<... $SQL ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY.$VAR ...>; | |
| ... | |
| $SQL = <... $INP ...>; | |
| ... | |
| $K.whereRaw(<... $SQL ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY ...>; | |
| ... | |
| $SQL = <... $INP ...>; | |
| ... | |
| $K.whereRaw(<... $SQL ...>, ...) | |
| ' | |
| message: 'Untrusted input concatinated with raw SQL query using knex raw() or whereRaw() | |
| functions can result in SQL Injection. | |
| ' | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-89 | |
| shortDescription: Improper neutralization of special elements used in an SQL command | |
| (SQL Injection) | |
| security-severity: CRITICAL | |
| category: security | |
| - id: rules_lgpl_javascript_database_rule-sequelize-tls | |
| message: '''The Sequelize connection string indicates that database server does | |
| not use TLS. Non TLS connections are susceptible to man in the middle (MITM) attacks.'' | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-319 | |
| shortDescription: Cleartext transmission of sensitive information | |
| security-severity: MEDIUM | |
| category: security | |
| patterns: | |
| - pattern: "{\n host: $HOST,\n database: $DATABASE,\n dialect: $DIALECT\n }\n" | |
| - pattern-not: "{\n host: $HOST,\n database: $DATABASE,\n dialect: \"postgres\"\ | |
| ,\n dialectOptions: {\n ssl: true\n }\n}\n" | |
| - pattern-not: "{\n host: $HOST,\n database: $DATABASE,\n dialect: $DIALECT,\n\ | |
| \ dialectOptions: {\n ssl: { ... }\n }\n}\n" | |
| - metavariable-regex: | |
| metavariable: $DIALECT | |
| regex: '[''"](mariadb|mysql|postgres|oracle)[''"]' | |
| - id: rules_lgpl_javascript_database_rule-node-nosqli-js-injection | |
| patterns: | |
| - pattern-either: | |
| - pattern: '$OBJ.$FUNC({$where: <... $REQ.$FOO.$BAR ...>}, ...) | |
| ' | |
| - pattern: '$OBJ.$FUNC({$where: <... $REQ.$QUERY ...>}, ...) | |
| ' | |
| - pattern: '$NSQL = <... $REQ.$QUERY.$...>; | |
| ... | |
| $OBJ.$FUNC({$where: <... $NSQL ...>}, ...) | |
| ' | |
| - pattern: '$NSQL = <... $REQ.$QUERY ...>; | |
| ... | |
| $OBJ.$FUNC({$where: <... $NSQL ...>}, ...) | |
| ' | |
| - pattern: '$INP = $REQ.$FOO.$BAR; | |
| ... | |
| $QRY = {$where: <... $INP ...>}; | |
| ... | |
| $OBJ.$FUNC(<... $QRY ...>, ...) | |
| ' | |
| - pattern: '$INP = $REQ.$FOO; | |
| ... | |
| $QRY = {$where: <... $INP ...>}; | |
| ... | |
| $OBJ.$FUNC(<... $QRY ...>, ...) | |
| ' | |
| - pattern: '$QRY["$where"] = <... $REQ.$FOO ...>; | |
| ... | |
| $OBJ.$FUNC(<... $QRY ...>, ...) | |
| ' | |
| - pattern: '$QRY["$where"] = <... $REQ.$FOO.$BAR ...>; | |
| ... | |
| $OBJ.$FUNC(<... $QRY ...>, ...) | |
| ' | |
| - pattern: '$INP = $REQ.$FOO; | |
| ... | |
| $QRY["$where"] = <... $INP ...>; | |
| ... | |
| $OBJ.$FUNC(<... $QRY ...>, ...) | |
| ' | |
| - pattern: '$INP = $REQ.$FOO.$BAR; | |
| ... | |
| $QRY["$where"] = <... $INP ...>; | |
| ... | |
| $OBJ.$FUNC(<... $QRY ...>, ...) | |
| ' | |
| message: 'Untrusted user input in MongoDB $where operator can result in NoSQL JavaScript | |
| Injection. | |
| ' | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-943 | |
| shortDescription: Improper neutralization of special elements in data query logic | |
| security-severity: CRITICAL | |
| category: security | |
| - id: rules_lgpl_javascript_database_rule-sequelize-weak-tls | |
| message: '''The Sequelize connection string indicates that an older version of TLS | |
| is in use. TLS1.0 and TLS1.1 are deprecated and should be used. By default, Sequelize | |
| use TLSv1.2 but it''''s recommended to use TLS1.3. Not applicable to SQLite database.'' | |
| ' | |
| metadata: | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-757 | |
| shortDescription: Selection of Less-Secure Algorithm During Negotiation (Algorithm | |
| Downgrade) | |
| security-severity: CRITICAL | |
| category: security | |
| severity: ERROR | |
| languages: | |
| - javascript | |
| patterns: | |
| - pattern-inside: "{\n host: $HOST,\n database: $DATABASE,\n dialect: $DIALECT,\n\ | |
| \ dialectOptions:\n { ssl: ... }\n }\n" | |
| - pattern-either: | |
| - pattern: "{\n minVersion: 'TLSv1'\n}\n" | |
| - pattern: "{\n minVersion: 'TLSv1.1'\n}\n" | |
| - metavariable-regex: | |
| metavariable: $DIALECT | |
| regex: '[''"](mariadb|mysql|postgres)[''"]' | |
| - id: rules_lgpl_javascript_database_rule-node-sqli-injection | |
| patterns: | |
| - pattern-inside: 'require(''$LIB'') | |
| ... | |
| ' | |
| - metavariable-regex: | |
| metavariable: $LIB | |
| regex: \b(sql-client|mysql|pg|mssql|oracledb|sequelize)\b | |
| - pattern-not: '$CON.query("..." + "...", ...) | |
| ' | |
| - pattern-not: '$SQL = "..."; | |
| ... | |
| $CON.query(<... $SQL ...>, ...) | |
| ' | |
| - pattern-either: | |
| - pattern: '$CON.query(<... $REQ.$QUERY ...>, ...) | |
| ' | |
| - pattern: '$SQL = <... $REQ.$QUERY ...>; | |
| ... | |
| $CON.query(<... $SQL ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY ...>; | |
| ... | |
| $SQL = <... $INP ...>; | |
| ... | |
| $CON.query(<... $SQL ...>, ...) | |
| ' | |
| - pattern: '$CON.query(`...${...}...`, ...) | |
| ' | |
| - pattern: '$CON.query("..."+...+"...", ...) | |
| ' | |
| - pattern: '$SQL = <... $INP ...>; | |
| ... | |
| $CON.query(<... $SQL ...>, ...) | |
| ' | |
| message: 'Untrusted input concatinated with raw SQL query can result in SQL Injection. | |
| ' | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-89 | |
| shortDescription: Improper neutralization of special elements used in an SQL command | |
| (SQL Injection) | |
| security-severity: CRITICAL | |
| category: security | |
| - id: rules_lgpl_javascript_database_rule-sequelize-tls-cert-validation | |
| message: "The Sequelize connection string indicates that TLS certificate validation\ | |
| \ \nof database server is disabled. This is equivalent to not having TLS. An \n\ | |
| attacker can present any invalid certificate and Sequelize will make database\ | |
| \ \nconnection ignoring certificate errors. This setting make the connection\n\ | |
| susceptible to man in the middle (MITM) attacks. Not applicable to SQLite database.\n" | |
| severity: ERROR | |
| languages: | |
| - javascript | |
| metadata: | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-295 | |
| shortDescription: Improper certificate validation | |
| security-severity: HIGH | |
| category: security | |
| patterns: | |
| - pattern: "{\n host: $HOST,\n database: $DATABASE,\n dialect: $DIALECT,\n dialectOptions:\ | |
| \ {\n ssl: {\n rejectUnauthorized: false\n }\n }\n }\n" | |
| - metavariable-regex: | |
| metavariable: $DIALECT | |
| regex: '[''"](mariadb|mysql|postgres)[''"]' | |
| - id: rules_lgpl_javascript_crypto_rule-node-weak-crypto | |
| patterns: | |
| - pattern-either: | |
| - pattern: '$X.createCipher(''des'', ...) | |
| ' | |
| message: 'A weak or broken cryptographic algorithm was identified. Using these functions | |
| will introduce vulnerabilities or downgrade the security of your application. | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-327 | |
| shortDescription: Use of a broken or risky cryptographic algorithm | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_crypto_rule-node-tls-reject | |
| patterns: | |
| - pattern-either: | |
| - pattern: '$X.env.NODE_TLS_REJECT_UNAUTHORIZED = $VAL | |
| ' | |
| - pattern: '$X.env[''NODE_TLS_REJECT_UNAUTHORIZED'']= $VAL | |
| ' | |
| - metavariable-pattern: | |
| metavariable: $VAL | |
| pattern-either: | |
| - pattern: '''0'' | |
| ' | |
| - pattern: '0 | |
| ' | |
| message: "The application sets NODE_TLS_REJECT_UNAUTHORIZED to '0', which instructs\ | |
| \ Node.js to disable TLS/SSL certificate validation. \nThis configuration allows\ | |
| \ the application to accept self-signed certificates or certificates from untrusted\ | |
| \ authorities, \nundermining the TLS security model. Disabling TLS/SSL certificate\ | |
| \ validation compromises the integrity and confidentiality \nof data in transit\ | |
| \ between the client and server. It makes the application vulnerable to man-in-the-middle\ | |
| \ (MITM) attacks, \nwhere an attacker could intercept or alter the data being\ | |
| \ exchanged.\n\nMitigation Strategy:\nDo not disable TLS/SSL certificate validation\ | |
| \ in production environments. Ensure that NODE_TLS_REJECT_UNAUTHORIZED is \nset\ | |
| \ to '1' or is removed entirely from the production configuration (as the default\ | |
| \ configuration of validating SSL \ncertificate is safe).\n\nSecure Code Example:\n\ | |
| ```\nconst https = require('https')\nprocess.env['NODE_TLS_REJECT_UNAUTHORIZED']\ | |
| \ = '1'\nconst req = https.request(options, res => {\n let data = ''\n res.on('data',\ | |
| \ chunk => {\n data += chunk\n })\n res.on('end', () => {\n console.log('Response\ | |
| \ Body:', data)\n })\n})\nreq.end()\n```\n" | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-295 | |
| shortDescription: Improper Certificate Validation | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_crypto_rule-node-aes-noiv | |
| patterns: | |
| - pattern-either: | |
| - pattern: '$X.createCipheriv("=~/^aes-/i", $KEY, "", ...) | |
| ' | |
| message: 'AES algorithms requires an initialization vector (IV). Providing no or | |
| null IV in some implementation results to a 0 IV. Use of a deterministic IV makes | |
| dictionary attacks easier. | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-327 | |
| shortDescription: Use of a broken or risky cryptographic algorithm | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_crypto_rule-node-timing-attack | |
| patterns: | |
| - pattern-not: if ($Z == null) { ... }; | |
| - pattern-not: if ($Z === null) { ... }; | |
| - pattern-not: if ($Z != null) { ... }; | |
| - pattern-not: if ($Z !== null) { ... }; | |
| - pattern-not: if ($Q != undefined) { ... }; | |
| - pattern-not: if ($Q !== undefined) { ... }; | |
| - pattern-not: if ($Q == undefined) { ... }; | |
| - pattern-not: if ($Q === undefined) { ... }; | |
| - pattern-not: return $Y == null; | |
| - pattern-not: return $Y === null; | |
| - pattern-not: return $Y != null; | |
| - pattern-not: return $Y !== null; | |
| - pattern-not: return $Y == undefined; | |
| - pattern-not: return $Y === undefined; | |
| - pattern-not: return $Y != undefined; | |
| - pattern-not: return $Y !== undefined; | |
| - pattern-either: | |
| - pattern: "if (password == $X) {\n ...\n}\n" | |
| - pattern: "if ($X == password) {\n ...\n}\n" | |
| - pattern: "if (password === $X) {\n ...\n}\n" | |
| - pattern: "if ($X === password) {\n ...\n}\n" | |
| - pattern: "if (pass == $X) {\n ...\n}\n" | |
| - pattern: "if ($X == pass) {\n ...\n}\n" | |
| - pattern: "if (pass === $X) {\n ...\n}\n" | |
| - pattern: "if ($X === pass) {\n ...\n}\n" | |
| - pattern: "if (secret == $X) {\n ...\n}\n" | |
| - pattern: "if ($X == secret) {\n ...\n}\n" | |
| - pattern: "if (secret === $X) {\n ...\n}\n" | |
| - pattern: "if ($X === secret) {\n ...\n}\n" | |
| - pattern: "if (api == $X) {\n ...\n}\n" | |
| - pattern: "if ($X == api) {\n ...\n}\n" | |
| - pattern: "if (api === $X) {\n ...\n}\n" | |
| - pattern: "if ($X === api) {\n ...\n}\n" | |
| - pattern: "if (apiKey == $X) {\n ...\n}\n" | |
| - pattern: "if ($X == apiKey) {\n ...\n}\n" | |
| - pattern: "if (apiKey === $X) {\n ...\n}\n" | |
| - pattern: "if ($X === apiKey) {\n ...\n}\n" | |
| - pattern: "if (apiSecret == $X) {\n ...\n}\n" | |
| - pattern: "if ($X == apiSecret) {\n ...\n}\n" | |
| - pattern: "if (apiSecret === $X) {\n ...\n}\n" | |
| - pattern: "if ($X === apiSecret) {\n ...\n}\n" | |
| - pattern: "if (token == $X) {\n ...\n}\n" | |
| - pattern: "if ($X == token) {\n ...\n}\n" | |
| - pattern: "if (token === $X) {\n ...\n}\n" | |
| - pattern: "if ($X === token) {\n ...\n}\n" | |
| - pattern: "if (hash == $X) {\n ...\n}\n" | |
| - pattern: "if ($X == hash) {\n ...\n}\n" | |
| - pattern: "if (hash === $X) {\n ...\n}\n" | |
| - pattern: "if ($X === hash) {\n ...\n}\n" | |
| - pattern: "if (auth_token == $X) {\n ...\n}\n" | |
| - pattern: "if ($X == auth_token) {\n ...\n}\n" | |
| - pattern: "if (auth_token === $X) {\n ...\n}\n" | |
| - pattern: "if ($X === auth_token) {\n ...\n}\n" | |
| - pattern: "if (password != $X) {\n ...\n}\n" | |
| - pattern: "if ($X != password) {\n ...\n}\n" | |
| - pattern: "if (password !== $X) {\n ...\n}\n" | |
| - pattern: "if ($X !== password) {\n ...\n}\n" | |
| - pattern: "if (pass != $X) {\n ...\n}\n" | |
| - pattern: "if ($X != pass) {\n ...\n}\n" | |
| - pattern: "if (pass !== $X) {\n ...\n}\n" | |
| - pattern: "if ($X !== pass) {\n ...\n}\n" | |
| - pattern: "if (secret != $X) {\n ...\n}\n" | |
| - pattern: "if ($X != secret) {\n ...\n}\n" | |
| - pattern: "if (secret !== $X) {\n ...\n}\n" | |
| - pattern: "if ($X !== secret) {\n ...\n}\n" | |
| - pattern: "if (api != $X) {\n ...\n}\n" | |
| - pattern: "if ($X != api) {\n ...\n}\n" | |
| - pattern: "if (api !== $X) {\n ...\n}\n" | |
| - pattern: "if ($X !== api) {\n ...\n}\n" | |
| - pattern: "if (apiKey != $X) {\n ...\n}\n" | |
| - pattern: "if ($X != apiKey) {\n ...\n}\n" | |
| - pattern: "if (apiKey !== $X) {\n ...\n}\n" | |
| - pattern: "if ($X !== apiKey) {\n ...\n}\n" | |
| - pattern: "if (apiSecret != $X) {\n ...\n}\n" | |
| - pattern: "if ($X != apiSecret) {\n ...\n}\n" | |
| - pattern: "if (apiSecret !== $X) {\n ...\n}\n" | |
| - pattern: "if ($X !== apiSecret) {\n ...\n}\n" | |
| - pattern: "if (token != $X) {\n ...\n}\n" | |
| - pattern: "if ($X != token) {\n ...\n}\n" | |
| - pattern: "if (token !== $X) {\n ...\n}\n" | |
| - pattern: "if ($X !== token) {\n ...\n}\n" | |
| - pattern: "if (hash != $X) {\n ...\n}\n" | |
| - pattern: "if ($X != hash) {\n ...\n}\n" | |
| - pattern: "if (hash !== $X) {\n ...\n}\n" | |
| - pattern: "if ($X !== hash) {\n ...\n}\n" | |
| - pattern: "if (auth_token != $X) {\n ...\n}\n" | |
| - pattern: "if ($X != auth_token) {\n ...\n}\n" | |
| - pattern: "if (auth_token !== $X) {\n ...\n}\n" | |
| - pattern: "if ($X !== auth_token) {\n ...\n}\n" | |
| - pattern: 'return $X === auth_token; | |
| ' | |
| - pattern: 'return auth_token === $X; | |
| ' | |
| - pattern: 'return $X === token; | |
| ' | |
| - pattern: 'return token === $X; | |
| ' | |
| - pattern: 'return $X === hash; | |
| ' | |
| - pattern: 'return hash === $X; | |
| ' | |
| - pattern: 'return $X === password; | |
| ' | |
| - pattern: 'return password === $X; | |
| ' | |
| - pattern: 'return $X === pass; | |
| ' | |
| - pattern: 'return pass === $X; | |
| ' | |
| - pattern: 'return $X === apiKey; | |
| ' | |
| - pattern: 'return apiKey === $X; | |
| ' | |
| - pattern: 'return $X === apiSecret; | |
| ' | |
| - pattern: 'return apiSecret === $X; | |
| ' | |
| - pattern: 'return $X === api_key; | |
| ' | |
| - pattern: 'return api_key === $X; | |
| ' | |
| - pattern: 'return $X === api_secret; | |
| ' | |
| - pattern: 'return api_secret === $X; | |
| ' | |
| - pattern: 'return $X === secret; | |
| ' | |
| - pattern: 'return secret === $X; | |
| ' | |
| - pattern: 'return $X === api; | |
| ' | |
| - pattern: 'return api === $X; | |
| ' | |
| - pattern: 'return $X == auth_token; | |
| ' | |
| - pattern: 'return auth_token == $X; | |
| ' | |
| - pattern: 'return $X == token; | |
| ' | |
| - pattern: 'return token == $X; | |
| ' | |
| - pattern: 'return $X == hash; | |
| ' | |
| - pattern: 'return hash == $X; | |
| ' | |
| - pattern: 'return $X == password; | |
| ' | |
| - pattern: 'return password == $X; | |
| ' | |
| - pattern: 'return $X == pass; | |
| ' | |
| - pattern: 'return pass == $X; | |
| ' | |
| - pattern: 'return $X == apiKey; | |
| ' | |
| - pattern: 'return apiKey == $X; | |
| ' | |
| - pattern: 'return $X == apiSecret; | |
| ' | |
| - pattern: 'return apiSecret == $X; | |
| ' | |
| - pattern: 'return $X == api_key; | |
| ' | |
| - pattern: 'return api_key == $X; | |
| ' | |
| - pattern: 'return $X == api_secret; | |
| ' | |
| - pattern: 'return api_secret == $X; | |
| ' | |
| - pattern: 'return $X == secret; | |
| ' | |
| - pattern: 'return secret == $X; | |
| ' | |
| - pattern: 'return $X == api; | |
| ' | |
| - pattern: 'return api == $X; | |
| ' | |
| - pattern: 'return $X !== auth_token; | |
| ' | |
| - pattern: 'return auth_token !== $X; | |
| ' | |
| - pattern: 'return $X !== token; | |
| ' | |
| - pattern: 'return token !== $X; | |
| ' | |
| - pattern: 'return $X !== hash; | |
| ' | |
| - pattern: 'return hash !== $X; | |
| ' | |
| - pattern: 'return $X !== password; | |
| ' | |
| - pattern: 'return password !== $X; | |
| ' | |
| - pattern: 'return $X !== pass; | |
| ' | |
| - pattern: 'return pass !== $X; | |
| ' | |
| - pattern: 'return $X !== apiKey; | |
| ' | |
| - pattern: 'return apiKey !== $X; | |
| ' | |
| - pattern: 'return $X !== apiSecret; | |
| ' | |
| - pattern: 'return apiSecret !== $X; | |
| ' | |
| - pattern: 'return $X !== api_key; | |
| ' | |
| - pattern: 'return api_key !== $X; | |
| ' | |
| - pattern: 'return $X !== api_secret; | |
| ' | |
| - pattern: 'return api_secret !== $X; | |
| ' | |
| - pattern: 'return $X !== secret; | |
| ' | |
| - pattern: 'return secret !== $X; | |
| ' | |
| - pattern: 'return $X !== api; | |
| ' | |
| - pattern: 'return api !== $X; | |
| ' | |
| - pattern: 'return $X != auth_token; | |
| ' | |
| - pattern: 'return auth_token != $X; | |
| ' | |
| - pattern: 'return $X != token; | |
| ' | |
| - pattern: 'return token != $X; | |
| ' | |
| - pattern: 'return $X != hash; | |
| ' | |
| - pattern: 'return hash != $X; | |
| ' | |
| - pattern: 'return $X != password; | |
| ' | |
| - pattern: 'return password != $X; | |
| ' | |
| - pattern: 'return $X != pass; | |
| ' | |
| - pattern: 'return pass != $X; | |
| ' | |
| - pattern: 'return $X != apiKey; | |
| ' | |
| - pattern: 'return apiKey != $X; | |
| ' | |
| - pattern: 'return $X != apiSecret; | |
| ' | |
| - pattern: 'return apiSecret != $X; | |
| ' | |
| - pattern: 'return $X != api_key; | |
| ' | |
| - pattern: 'return api_key != $X; | |
| ' | |
| - pattern: 'return $X != api_secret; | |
| ' | |
| - pattern: 'return api_secret != $X; | |
| ' | |
| - pattern: 'return $X != secret; | |
| ' | |
| - pattern: 'return secret != $X; | |
| ' | |
| - pattern: 'return $X != api; | |
| ' | |
| - pattern: 'return api != $X; | |
| ' | |
| message: '''String comparisons using ''''==='''', ''''!=='''', ''''!='''' and ''''=='''' | |
| is vulnerable to timing attacks. More info: https://snyk.io/blog/node-js-timing-attack-ccc-ctf/'' | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| cwe: CWE-208 | |
| shortDescription: Observable timing discrepancy | |
| category: security | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| - id: rules_lgpl_javascript_crypto_rule-node-aes-ecb | |
| patterns: | |
| - pattern-either: | |
| - pattern: '$X.createCipheriv("=~/^aes-([0-9]+)-ecb$/i", ...) | |
| ' | |
| - pattern: '$X.createDecipheriv("=~/^aes-([0-9]+)-ecb$/i", ...) | |
| ' | |
| message: 'AES with ECB mode is deterministic in nature and not suitable for encrypting | |
| large amount of repetitive data. | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-327 | |
| shortDescription: Use of a broken or risky cryptographic algorithm | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_crypto_rule-node-insecure-random-generator | |
| pattern-either: | |
| - patterns: | |
| - pattern-inside: 'require(''crypto'') | |
| ... | |
| ' | |
| - pattern: '$X.pseudoRandomBytes(...) | |
| ' | |
| - pattern: 'Math.random(...) | |
| ' | |
| message: "This rule identifies use of cryptographically weak random number generators.\n\ | |
| Using cryptographically weak random number generators like `crypto.pseudoRandomBytes()`\ | |
| \ \nand `Math.random()` for security-critical tasks can expose systems to significant\ | |
| \ \nvulnerabilities. Attackers might predict the generated random numbers, compromising\ | |
| \ \nthe integrity and confidentiality of cryptographic operations. This could\ | |
| \ lead to \nbreaches where sensitive data is accessed or manipulated, authentication\ | |
| \ mechanisms \nare bypassed, or secure communications are intercepted, ultimately\ | |
| \ undermining the \nsecurity of the entire system or application.\n\nMitigation\ | |
| \ strategy:\nReplace the use of these cryptographically weak random number generators\ | |
| \ with \n`crypto.randomBytes()`, a method provided by Node.js's `crypto` module\ | |
| \ that \ngenerates cryptographically secure random numbers. This method should\ | |
| \ be used \nfor all operations requiring secure randomness, such as generating\ | |
| \ keys, tokens, \nor any cryptographic material.\n\nSecure Code Example:\n```\n\ | |
| const crypto = require('crypto');\nconst secureBytes = crypto.randomBytes(256);\n\ | |
| console.log(`Secure random bytes: ${secureBytes.toString('hex')}`);\n```\n" | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-338 | |
| shortDescription: Use of cryptographically weak pseudo-random number generator | |
| (PRNG) | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_crypto_rule-node-sha1 | |
| pattern-either: | |
| - patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: '$Y = $X.createHash(''sha1'') | |
| ... | |
| ' | |
| - pattern: '$Y.update("...") | |
| ' | |
| - pattern: '$X.createHash(''sha1'').update("...") | |
| ' | |
| - patterns: | |
| - pattern-inside: 'require(''crypto-js'') | |
| ... | |
| ' | |
| - pattern: '$X.SHA1("...") | |
| ' | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: '$M = require(''sha1'') | |
| ... | |
| ' | |
| - pattern-inside: '$M = require(''js-sha1'') | |
| ... | |
| ' | |
| - pattern: '$M("...") | |
| ' | |
| - patterns: | |
| - pattern-inside: 'require(''node-forge'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: '$Y = $X.md.sha1.create() | |
| ... | |
| ' | |
| - pattern: '$Y.update("...") | |
| ' | |
| - pattern: '$X.md.sha1.create().update("...") | |
| ' | |
| - patterns: | |
| - pattern-inside: '$X = require(''jshashes'') | |
| ... | |
| $Y = new $X.SHA1() | |
| ... | |
| ' | |
| - pattern: '$Y.$METHOD("...") | |
| ' | |
| - patterns: | |
| - pattern-inside: 'require(''hash.js'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: '$Y = $X.sha1() | |
| ... | |
| ' | |
| - pattern: '$Y.update("...") | |
| ' | |
| - pattern: '$X.sha1().update("...") | |
| ' | |
| - patterns: | |
| - pattern-inside: '$X = require(''jssha'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: 'new $X(''SHA-1'', ...).update("...") | |
| ' | |
| - patterns: | |
| - pattern-inside: '$Y = new $X(''SHA-1'', ...) | |
| ... | |
| ' | |
| - pattern: '$Y.update("...") | |
| ' | |
| - patterns: | |
| - pattern-either: | |
| - pattern: '$X(''sha1'').update("...") | |
| ' | |
| - patterns: | |
| - pattern-inside: '$Y = $X(''sha1'') | |
| ... | |
| ' | |
| - pattern: '$Y.update("...") | |
| ' | |
| - pattern: '$X.subtle.digest(''SHA-1'', ...) | |
| ' | |
| - patterns: | |
| - pattern-either: | |
| - pattern: '$X.SHA1.digest(...) | |
| ' | |
| - patterns: | |
| - pattern-inside: '$Y = $X.SHA1 | |
| ... | |
| ' | |
| - pattern: "$Y.digest(...) \n" | |
| - patterns: | |
| - pattern-either: | |
| - pattern: '$X.codec.hex.fromBits($SJCL) | |
| ' | |
| - patterns: | |
| - pattern-inside: '$Y = $SJCL | |
| ... | |
| ' | |
| - pattern: '$X.codec.hex.fromBits($Y) | |
| ' | |
| - metavariable-pattern: | |
| metavariable: $SJCL | |
| pattern: '$K.hash.sha1.hash("...") | |
| ' | |
| message: "The SHA-1 hashing algorithm is no longer considered secure for\ncryptographic\ | |
| \ applications due to its vulnerability to collision attacks,\nwhere two different\ | |
| \ inputs produce the same output hash. SHA-1's\nsusceptibility to collision attacks\ | |
| \ undermines the security of\ncryptographic operations, allowing attackers to\ | |
| \ forge signatures or\nmanipulate data without detection. This poses significant\ | |
| \ risks in\nauthentication systems, data integrity validations, and secure\ncommunications.\ | |
| \ \n\nRemediation: To mitigate this vulnerability, replace the SHA1 hashing \n\ | |
| algorithm with stronger cryptographic hash functions, such as SHA-256 \nor SHA-3.\ | |
| \ These algorithms offer significantly improved security and \nare resistant\ | |
| \ to collision attacks, making them suitable for cryptographic \npurposes in\ | |
| \ modern applications.\n\nSecure Code example: \n``` \nconst crypto = require('crypto');\ | |
| \ \nconst hash = crypto.createHash('sha256').update('sensitive data').digest('hex');\ | |
| \ \nconsole.log(hash); \n```\n" | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Use of weak hash | |
| category: security | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-328 | |
| security-severity: MEDIUM | |
| - id: rules_lgpl_javascript_crypto_rule-node-md5 | |
| pattern-either: | |
| - patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: '$Y = $X.createHash(''md5'') | |
| ... | |
| ' | |
| - pattern: '$Y.update("...") | |
| ' | |
| - pattern: '$X.createHash(''md5'').update("...") | |
| ' | |
| - patterns: | |
| - pattern-inside: 'require(''crypto-js'') | |
| ... | |
| ' | |
| - pattern: '$X.MD5("...") | |
| ' | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: '$M = require(''md5'') | |
| ... | |
| ' | |
| - pattern-inside: '$M = require(''blueimp-md5'') | |
| ... | |
| ' | |
| - pattern-inside: '$M = require(''js-md5'') | |
| ... | |
| ' | |
| - pattern: '$M("...") | |
| ' | |
| - patterns: | |
| - pattern-inside: 'require(''node-forge'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: '$Y = $X.md.md5.create() | |
| ... | |
| ' | |
| - pattern: '$Y.update("...") | |
| ' | |
| - pattern: '$X.md.md5.create().update("...") | |
| ' | |
| - patterns: | |
| - pattern-inside: '$X = require(''jshashes'') | |
| ... | |
| $Y = new $X.MD5() | |
| ... | |
| ' | |
| - pattern: '$Y.$METHOD("...") | |
| ' | |
| - patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: '$X = require(''create-hash'') | |
| ... | |
| $Y = $X(''md5'') | |
| ... | |
| ' | |
| - pattern: '$Y.update("...") | |
| ' | |
| - patterns: | |
| - pattern-inside: '$X = require(''create-hash'') | |
| ... | |
| ' | |
| - pattern: "$X('md5').update(\"...\") \n" | |
| message: "The MD5 hashing algorithm is considered cryptographically weak and \n\ | |
| vulnerable to collision attacks, where two different inputs generate \nthe same\ | |
| \ output hash. When used for hashing sensitive data, attackers \ncan exploit this\ | |
| \ weakness to generate collisions, allowing them to bypass \nsecurity checks or\ | |
| \ masquerade malicious data as legitimate. This \nvulnerability is particularly\ | |
| \ critical in authentication mechanisms, \ndigital signatures, SSL/TLS certificates,\ | |
| \ and data integrity checks.\n\nRemediation:\nTo mitigate this vulnerability,\ | |
| \ replace the MD5 hashing algorithm with \nstronger cryptographic hash functions,\ | |
| \ such as SHA-256 or SHA-3. These \nalgorithms offer significantly improved security\ | |
| \ and are resistant to \ncollision attacks, making them suitable for cryptographic\ | |
| \ purposes in \nmodern applications.\n\nSecure Code example :\n```\nconst crypto\ | |
| \ = require('crypto');\nconst hash = crypto.createHash('sha256').update('sensitive\ | |
| \ data').digest('hex');\nconsole.log(hash); \n```\n" | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Use of weak hash | |
| category: security | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-328 | |
| security-severity: MEDIUM | |
| - id: rules_lgpl_javascript_dos_rule-layer7-object-dos | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern: $REQ.$FUNC. ... | |
| - metavariable-regex: | |
| metavariable: $FUNC | |
| regex: ^(body|params|query|baseUrl|cookies|hostname|subdomains|ip|ips|originalUrl|path)$ | |
| pattern-sanitizers: | |
| - patterns: | |
| - pattern: $OBJ.slice($X, $Y) | |
| - pattern-not: $OBJ.slice($X) | |
| - pattern-not: $OBJ.slice(..., $OBJ.length) | |
| - pattern-not: $OBJ.slice(..., Object.keys($OBJ).length) | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: 'for(...; $COND; ...){...} | |
| ' | |
| - focus-metavariable: $COND | |
| - metavariable-pattern: | |
| metavariable: $COND | |
| pattern-either: | |
| - pattern: 'Object.Keys($VAR).length | |
| ' | |
| - pattern: $VAR.length | |
| - patterns: | |
| - pattern-either: | |
| - pattern: $OBJ.forEach | |
| - pattern: $OBJ.map | |
| - pattern: Object.keys($OBJ).map | |
| - pattern: $OBJ.filter | |
| - pattern: $OBJ.reduce | |
| - pattern: $OBJ.reduceRight | |
| - focus-metavariable: $OBJ | |
| message: "This application is looping over user controlled objects, which can lead\ | |
| \ to a layer 7 denial of service vulnerability.\n\nA layer 7 denial of service\ | |
| \ attack refers to overloading the application layer of the OSI model, typically\ | |
| \ layer 7. \nThis can happen when user-controlled input such as objects, arrays,\ | |
| \ strings, etc. are iterated or looped over without proper validation or limits\ | |
| \ in place.\n\nFor example, if a user can control the size of an array or object\ | |
| \ passed into the application, \nthey could create an extremely large input that\ | |
| \ gets looped over. This would consume excessive CPU cycles or memory, \npotentially\ | |
| \ crashing or slowing down the application.\n\nTo prevent this, limits should\ | |
| \ be set on the number of iterations, input sizes, recursion depth, etc.\n\nSample\ | |
| \ case of secure array looped over with user-controlled input\n```\n// Potential\ | |
| \ DoS if req.body.list.length is large.\napp.post('/dos/layer7-object-dos/for-loop/1',\ | |
| \ function (req, res) {\n var list = req.body.list;\n for (let i = 0; i\ | |
| \ <= 10; i++) {\n if(!list[i]){\n // return;\n } \n \ | |
| \ }\n res.send(\"res\")\n});\n```\n\nImplementing protections against layer\ | |
| \ 7 denial of service attacks is important for securing modern web applications\ | |
| \ and APIs.\n" | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-606 | |
| shortDescription: Unchecked input for loop condition | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_dos_rule-regex-dos | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: '$REGEX.test(<... $REQ ...>) | |
| ' | |
| - pattern: '$REGEX.test(<... $REQ.$QUERY ...>) | |
| ' | |
| - pattern: '$REGEX.test(<... $REQ.$BODY.$PARAM ...>) | |
| ' | |
| - pattern: '$INP = <... $REQ ...>; | |
| ... | |
| $REGEX.test(<... $INP ...>) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY ...>; | |
| ... | |
| $REGEX.test(<... $INP ...>) | |
| ' | |
| - pattern: '$INP = <... $REQ.$BODY.$PARAM ...>; | |
| ... | |
| $REGEX.test(<... $INP ...>) | |
| ' | |
| - pattern: '/.../g.exec(<... $REQ ...>) | |
| ' | |
| - pattern: '/.../g.exec(<... $REQ.$QUERY ...>) | |
| ' | |
| - pattern: '/.../.exec(<... $REQ.$BODY.$PARAM ...>) | |
| ' | |
| - pattern: '$INP = <... $REQ ...>; | |
| ... | |
| /.../.exec(<... $INP ...>) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY ...>; | |
| ... | |
| /.../.exec(<... $INP ...>) | |
| ' | |
| - pattern: '$INP = <... $REQ.$BODY.$PARAM ...>; | |
| ... | |
| /.../.exec(<... $INP ...>) | |
| ' | |
| - pattern: '$RE = /.../; | |
| ... | |
| $RE.exec(<... $REQ ...>) | |
| ' | |
| - pattern: '$RE = /.../; | |
| ... | |
| $RE.exec(<... $REQ.$QUERY ...>) | |
| ' | |
| - pattern: '$RE = /.../; | |
| ... | |
| $RE.exec(<... $REQ.$BODY.$PARAM ...>) | |
| ' | |
| message: 'Ensure that the regex used to compare with user supplied input is safe | |
| from regular expression denial of service. | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-185 | |
| shortDescription: Incorrect regular expression | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_xss_rule-handlebars-noescape | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - focus-metavariable: $REQ | |
| - pattern: function ($REQ, $RES, ...) {...} | |
| - pattern-either: | |
| - pattern-inside: '$HB = require(''handlebars''); | |
| ... | |
| ' | |
| - pattern-inside: 'import $HB from "handlebars"; | |
| ' | |
| pattern-sinks: | |
| - pattern: '$HB.compile(..., {noEscape: true,...}, ...)(...)' | |
| - pattern: 'var $METHOD = $HB.compile(..., {noEscape: true,...}, ...) | |
| ... | |
| $METHOD(...) | |
| ' | |
| message: "This application is compiling strings with `Handlebars.compile` using\ | |
| \ an insecure\noption of `{noEscape: true}`. This configuration bypasses the default\ | |
| \ behavior of \nHandlebars, which is to escape input values to prevent Cross-Site\ | |
| \ Scripting (XSS) \nattacks. \nXSS attacks are a type of security breach that\ | |
| \ occurs when an attacker manages to \ninject malicious scripts into web pages\ | |
| \ viewed by other users. These scripts can then \nexecute in the context of the\ | |
| \ victim's session, allowing the attacker to bypass access \ncontrols and potentially\ | |
| \ access sensitive information or perform actions on behalf of the \nuser.\ | |
| \ It is important to encode the data depending on the specific context it is used\ | |
| \ in. \n\nBy default, `Handlebars.compile` escapes input values to prevent XSS\ | |
| \ attacks. \nConsider using `Handlebars.compile` with default settings or set\ | |
| \ `{noEscape: false}` \nto force encoding of input data.\n\nExample of using Handlebars.compile\ | |
| \ safely:\n```\nvar template = \"This is {{target}}\";\nvar out = Handlebars.compile(template)({target:\ | |
| \ req.query.message});\nres.send(out);\n``` \n" | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A7:2017-Cross-Site Scripting (XSS) | |
| - A03:2021-Injection | |
| shortDescription: Improper neutralization of script-related HTML tags in a web | |
| page (basic XSS) | |
| cwe: CWE-80 | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_xss_rule-xss-disable-mustache-escape | |
| pattern: $OBJ.escapeMarkup = false | |
| severity: WARNING | |
| languages: | |
| - javascript | |
| metadata: | |
| owasp: | |
| - A7:2017-Cross-Site Scripting (XSS) | |
| - A03:2021-Injection | |
| cwe: CWE-116 | |
| shortDescription: Improper encoding or escaping of output | |
| security-severity: MEDIUM | |
| category: security | |
| message: 'Markup escaping disabled. This can be used with some template engines | |
| to escape disabling of HTML entities, which can lead to XSS attacks. | |
| ' | |
| - id: rules_lgpl_javascript_xss_rule-handlebars-safestring | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - focus-metavariable: $REQ | |
| - pattern: function ($REQ, $RES, ...) {...} | |
| pattern-sinks: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: '$HB = require(''handlebars'') | |
| ... | |
| ' | |
| - pattern: new $HB.SafeString(...) | |
| - patterns: | |
| - pattern-inside: 'import $HB from "handlebars"; | |
| ... | |
| ' | |
| - pattern: new $HB.SafeString(...) | |
| pattern-sanitizers: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: '$HB = require(''handlebars'') | |
| ... | |
| ' | |
| - pattern: $HB.escapeExpression(...) | |
| - patterns: | |
| - pattern-inside: 'import $HB from "handlebars"; | |
| ... | |
| ' | |
| - pattern: $HB.escapeExpression(...) | |
| message: "This application is using a vulnerable method `Handlebars.SafeString(...)`.\n\ | |
| Handlebars SafeString method does not escape the data passed through it. \nUntrusted\ | |
| \ user input passing through SafeString method can make the application \nvulnerable\ | |
| \ to Cross-Site Scripting (XSS) attacks.\n\nXSS attacks are a type of security\ | |
| \ breach that occurs when an attacker manages to \ninject malicious scripts into\ | |
| \ web pages viewed by other users. These scripts can then \nexecute in the context\ | |
| \ of the victim's session, allowing the attacker to bypass access \ncontrols and\ | |
| \ potentially access sensitive information or perform actions on behalf of the\ | |
| \ \nuser. It is important to encode the data depending on the specific context\ | |
| \ it is used in. \n\nConsider using the `Handlebars.escapeExpression` method to\ | |
| \ escape user input while \nconstructing SafeString to avoid potential security\ | |
| \ concerns. Following is a secure code \nexample.\n```\n var returnObj = new\ | |
| \ Handlebars.SafeString(\"<h1>Handlebars safe string</h1>\" + Handlebars.escapeExpression(req.query.message))\n\ | |
| \ res.send(returnObj.string)\n```\n" | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A7:2017-Cross-Site Scripting (XSS) | |
| - A03:2021-Injection | |
| cwe: CWE-79 | |
| shortDescription: Improper neutralization of input during web page generation | |
| (Cross-site Scripting) | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_xss_rule-express-xss | |
| mode: taint | |
| options: | |
| taint_unify_mvars: true | |
| pattern-sources: | |
| - patterns: | |
| - patterns: | |
| - metavariable-regex: | |
| metavariable: $LIB | |
| regex: (?<!\s)\bexpress(?:\/.*)?\b | |
| - pattern-either: | |
| - pattern-inside: 'import { ... } from ''$LIB'' | |
| ... | |
| ' | |
| - pattern-inside: 'import $IMPORT from ''$LIB'' | |
| ... | |
| ' | |
| - pattern-inside: 'require(''$LIB'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - patterns: | |
| - focus-metavariable: $REQ | |
| - pattern: function ($REQ, $RES, ...) {...} | |
| - patterns: | |
| - focus-metavariable: $REQ | |
| - pattern: function $FUNC($REQ, $RES, ...) {...} | |
| pattern-propagators: | |
| - pattern: $ARR.push($IN) | |
| from: $IN | |
| to: $ARR | |
| pattern-sanitizers: | |
| - pattern: encodeURI(...) | |
| - pattern: encodeURIComponent(...) | |
| pattern-sinks: | |
| - patterns: | |
| - focus-metavariable: $INPUT | |
| - pattern-either: | |
| - pattern: $RES. ... .send($INPUT) | |
| - pattern: $RES. ... .write($INPUT) | |
| message: "This application accepts user input directly from the client side without\ | |
| \ validation. \nThis could lead to Cross Site Scripting (XSS) if the input contains\ | |
| \ malicious script code and \nthe application server does not properly escape\ | |
| \ or sanitize the output. \nConsider encoding input data before sending it to\ | |
| \ the client side. \n\n```\n// safe method of sending user input data\nrouter.get('/safe/1',\ | |
| \ (req, res) => {\n var name = encodeURI(req.query.name); \n res.send(name);\n\ | |
| })\n```\n\nXSS is an attack that exploits a web application or system to treat\ | |
| \ user input as markup or script code. \nIt is important to encode the data depending\ | |
| \ on the specific context in which it is used. \n" | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Improper neutralization of input during web page generation | |
| ('Cross-site Scripting') | |
| category: security | |
| cwe: CWE-79 | |
| owasp: | |
| - A7:2017-Cross-Site Scripting (XSS) | |
| - A03:2021-Injection | |
| security-severity: MEDIUM | |
| - id: rules_lgpl_javascript_xss_rule-xss-serialize-javascript | |
| pattern-either: | |
| - patterns: | |
| - pattern-inside: '$S = require(''serialize-javascript'') | |
| ... | |
| ' | |
| - pattern: '$S(..., {...,unsafe: true,...})' | |
| - patterns: | |
| - pattern-inside: 'import serialize from "serialize-javascript"; | |
| ... | |
| ' | |
| - pattern: 'serialize(..., {...,unsafe: true,...})' | |
| message: "This application is serializing Javascript objects with vulnerable \n\ | |
| configurations by setting `{unsafe: true}` in serialize-javascript. \n\nThis could\ | |
| \ lead to Cross Site Scripting (XSS) if the input was malicious \nscript code\ | |
| \ and the application server is not properly validating the output.\n\n```\n//\ | |
| \ safe use of serialize-javascript\nconst jsObj = serialize({\n foo: htmlResponse\n\ | |
| \ }\n);\n```\n\nXSS is an attack which exploits a web application or system to\ | |
| \ treat user input as markup or script code. \nIt is important to encode the data\ | |
| \ depending on the specific context it is used in. \n\nBy default, serialize-javascript\ | |
| \ encodes input values to prevent XSS attacks. \nConsider using serialize-javascript\ | |
| \ with default settings or set `{unsafe: false}` to encode\ninput data.\n" | |
| severity: WARNING | |
| languages: | |
| - javascript | |
| metadata: | |
| owasp: | |
| - A7:2017-Cross-Site Scripting (XSS) | |
| - A03:2021-Injection | |
| shortDescription: Improper neutralization of script-related HTML tags in a web | |
| page (basic XSS) | |
| cwe: CWE-80 | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_xss_rule-squirrelly-autoescape | |
| pattern-either: | |
| - patterns: | |
| - pattern-inside: '$SQLY = require(''squirrelly'') | |
| ... | |
| ' | |
| - pattern: $SQLY.autoEscaping(false) | |
| - patterns: | |
| - pattern-inside: 'import $SQLY from ''squirrelly''; | |
| ... | |
| ' | |
| - pattern: $SQLY.autoEscaping(false) | |
| message: "This application is rendering HTML with vulnerable \nconfigurations by\ | |
| \ setting Sqrl.autoEscaping(false) in squirrelly.\n\nThis could lead to Cross\ | |
| \ Site Scripting (XSS) if the input is malicious \nscript code and the application\ | |
| \ server is not properly validating the output.\n\n```\n// safe use of squirrelly\ | |
| \ render\nvar myTemplate = \"<p>My Message is: {{message}}</p>\"\nSqrl.Render(myTemplate,\ | |
| \ {message: req.query.message})\n```\n\nXSS is an attack that exploits a web application\ | |
| \ or system to treat user input as markup or script code. \nIt is important to\ | |
| \ encode the data depending on the specific context it is used in.\n\nBy default,\ | |
| \ squirrelly autoEscaping(true) escapes input values to prevent XSS attacks. \n\ | |
| Consider using squirrelly with default autoEscaping settings.\n" | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Improper neutralization of input during web page generation | |
| ('Cross-site Scripting') | |
| category: security | |
| cwe: CWE-79 | |
| owasp: | |
| - A7:2017-Cross-Site Scripting (XSS) | |
| - A03:2021-Injection | |
| security-severity: MEDIUM | |
| - id: rules_lgpl_javascript_xml_rule-node-entity-expansion | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: '$PARSER = new expat.Parser() | |
| ... | |
| $PARSER.write(..., <... $REQ.$QUERY ...>, ...) | |
| ' | |
| - pattern: '$PARSER = new expat.Parser() | |
| ... | |
| $PARSER.write(..., <... $REQ.$QUERY.$FOO ...>, ...) | |
| ' | |
| - pattern: '$PARSER = new expat.Parser() | |
| ... | |
| $PARSER.write(..., <... $REQ.$QUERY.$FOO.$FILE ...>, ...) | |
| ' | |
| message: 'User controlled data in XML Parsers can result in XML Internal Entity | |
| Processing vulnerabilities like in DoS. | |
| ' | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A4:2017-XML External Entities (XXE) | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-776 | |
| shortDescription: Improper restriction of recursive entity references in DTDs | |
| (XML Entity Expansion) | |
| security-severity: CRITICAL | |
| category: security | |
| - id: rules_lgpl_javascript_xml_rule-xxe-expat | |
| patterns: | |
| - pattern-inside: 'require(''node-expat'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern-inside: '$PARSER = new $EXPAT.Parser(...) | |
| ... | |
| ' | |
| - pattern-inside: '$PARSER = new Parser(...) | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: $PARSER.parse(<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $PARSER.parse(<... $REQ.$BODY ...>,...) | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PARSER.parse(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PARSER.parse(<... $INPUT ...>,...) | |
| ' | |
| - pattern: $PARSER.write(<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $PARSER.write(<... $REQ.$BODY ...>,...) | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PARSER.write(<... $INPUT ...>,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $PARSER.write(<... $INPUT ...>,...)' | |
| message: 'Make sure that unverified user data can not reach the XML Parser, as it | |
| can result in XML External or Internal Entity (XXE) Processing vulnerabilities. | |
| ' | |
| metadata: | |
| owasp: | |
| - A4:2017-XML External Entities (XXE) | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-611 | |
| shortDescription: Improper restriction of XML external entity reference | |
| security-severity: CRITICAL | |
| category: security | |
| severity: ERROR | |
| languages: | |
| - javascript | |
| - id: rules_lgpl_javascript_xml_rule-node-xpath-injection | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: 'function ($REQ, $RES, ...) {...} | |
| ' | |
| - pattern: 'function $FUNC($REQ, $RES, ...) {...} | |
| ' | |
| - focus-metavariable: $REQ | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: '$XPATH = require(''xpath'') | |
| ... | |
| ' | |
| - pattern-inside: 'import { $XPATH } from ''xpath'' | |
| ... | |
| ' | |
| - pattern-inside: 'import { $K as $XPATH } from ''xpath'' | |
| ... | |
| ' | |
| - pattern: "$XPATH.parse($REQ, ...) \n" | |
| - focus-metavariable: $REQ | |
| pattern-sanitizers: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: "if($VALIDATION){\n...\n$XPATH.parse($REQ, ...) \n...\n} \n" | |
| - pattern: "$A = $VALIDATION\n...\nif($A){\n...\n$XPATH.parse($REQ, ...) \n\ | |
| ...\n}\n" | |
| - metavariable-pattern: | |
| metavariable: $VALIDATION | |
| pattern-either: | |
| - pattern: "$AL.includes(...) \n" | |
| - pattern: '$AL.indexOf(...) !== -1 | |
| ' | |
| - pattern: '$AL.find(...) !== undefined | |
| ' | |
| - pattern: '$ALS.has(...) | |
| ' | |
| message: "Passing untrusted user input in `xpath.parse()` can result in XPATH injection\n\ | |
| vulnerability. This could be abused by malicious actors to execute expressions\ | |
| \ on\non XML files to capture unauthorized information.\nTo prevent XPATH injection\ | |
| \ vulnerabilities:\n\n- Always validate and sanitize user inputs, especially parameters\n\ | |
| or query strings that may influence the flow of the application.\n- Avoid directly\ | |
| \ using user input for parsing. If unavoidable, ensure\nstrict validation against\ | |
| \ an allowlist. \n- Use allowlists (lists of permitted expressions) to validate\ | |
| \ user input \nagainst known, trusted expressions before performing the parse.\n\ | |
| \n\nFollowing is an example of secure validation against allowlist to prevent\ | |
| \ the vulnerability:\n```\n// Define a list of explicitly allowed expressions\ | |
| \ for parsing\nconst allowedExpr = [\n 'expression1',\n 'expression2',\n\ | |
| \ 'expression3'\n];\n\napp.get('/xml/xpath/1', (req, res) => {\n var expression\ | |
| \ = req.params.exp;\n var isAllowed = allowedExpr.includes(expression);\n \ | |
| \ let xml_string = fs.readFileSync(\"books.xml\", \"utf8\");\n var doc =\ | |
| \ new dom().parseFromString(xml_string, 'text/xml');\n if (isAllowed) {\n \ | |
| \ // If the expression is allowed, proceed with the parsing\n var\ | |
| \ evaluator = xpath.parse(\"//\"+expression);\n var nodes = evaluator.select({\ | |
| \ node: doc }); \n res.send(nodes[0].firstChild.data);\n \ | |
| \ } else {\n res.status(400).send('Invalid expression');\n }\n});\n\ | |
| ```\n" | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-643 | |
| shortDescription: Improper neutralization of data within XPath expressions (XPath | |
| Injection) | |
| security-severity: CRITICAL | |
| category: security | |
| - id: rules_lgpl_javascript_xml_rule-node-xxe | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: '$LIBXML.parseXmlString(..., <... $REQ.$QUERY.$VAR.$FILE ...>, ...) | |
| ' | |
| - pattern: '$LIBXML.parseXmlString(..., <... $REQ.$QUERY.$VAR ...>, ...) | |
| ' | |
| - pattern: '$LIBXML.parseXmlString(..., <... $REQ.$QUERY ...>, ...) | |
| ' | |
| - pattern: '$FOO = <... $REQ.$QUERY.$VAR.$FILE ...>; ... $LIBXML.parseXmlString(..., | |
| <... $FOO ...>, ...) | |
| ' | |
| - pattern: '$FOO = <... $REQ.$QUERY.$VAR ...>; ... $LIBXML.parseXmlString(..., | |
| <... $FOO ...>, ...) | |
| ' | |
| - pattern: '$FOO = <... $REQ.$QUERY ...>; ... $LIBXML.parseXmlString(..., <... | |
| $FOO ...>, ...) | |
| ' | |
| - pattern: '$LIBXML.parseXml(..., <... $REQ.$QUERY.$VAR.$FILE ...>, ...) | |
| ' | |
| - pattern: '$LIBXML.parseXml(..., <... $REQ.$QUERY.$VAR ...>, ...) | |
| ' | |
| - pattern: '$LIBXML.parseXml(..., <... $REQ.$QUERY ...>, ...) | |
| ' | |
| - pattern: '$FOO = <... $REQ.$QUERY.$VAR.$FILE ...>; ... $LIBXML.parseXml(..., | |
| <... $FOO ...>, ...) | |
| ' | |
| - pattern: '$FOO = <... $REQ.$QUERY.$VAR ...>; ... $LIBXML.parseXml(..., <... | |
| $FOO ...>, ...) | |
| ' | |
| - pattern: '$FOO = <... $REQ.$QUERY ...>; | |
| ... | |
| $LIBXML.parseXml(..., <... $FOO ...>, ...) | |
| ' | |
| - pattern: '$PARSER = new libxmljs.SaxParser() | |
| ... | |
| $PARSER.parseString(..., <... $REQ.$QUERY ...>, ...) | |
| ' | |
| - pattern: '$PARSER = new libxmljs.SaxParser() | |
| ... | |
| $PARSER.parseString(..., <... $REQ.$QUERY.$BAR ...>, ...) | |
| ' | |
| - pattern: '$PARSER = new libxmljs.SaxParser() | |
| ... | |
| $PARSER.parseString(..., <... $REQ.$QUERY.$BAR.$FILE ...>, ...) | |
| ' | |
| - pattern: '$PARSER = new libxmljs.SaxPushParser() | |
| ... | |
| $PARSER.push(..., <... $REQ.$QUERY ...>, ...) | |
| ' | |
| - pattern: '$PARSER = new libxmljs.SaxPushParser() | |
| ... | |
| $PARSER.push(..., <... $REQ.$QUERY.$FOO ...> , ...) | |
| ' | |
| - pattern: '$PARSER = new libxmljs.SaxPushParser() | |
| ... | |
| $PARSER.push(..., <... $REQ.$QUERY.$FOO.$FILE ...> , ...) | |
| ' | |
| - pattern: '$PARSER = new libxmljs.SaxParser() | |
| ... | |
| $FOO = <... $REQ.$QUERY ...>; | |
| ... | |
| $PARSER.parseString(..., <... $FOO ...>, ...) | |
| ' | |
| - pattern: '$PARSER = new libxmljs.SaxParser() | |
| ... | |
| $FOO = <... $REQ.$QUERY.$BAR ...>; | |
| ... | |
| $PARSER.parseString(..., <... $FOO ...>, ...) | |
| ' | |
| - pattern: '$PARSER = new libxmljs.SaxParser() | |
| ... | |
| $FOO = <... $REQ.$QUERY.$BAR.$FILE ...>; | |
| ... | |
| $PARSER.parseString(..., <... $FOO ...>, ...) | |
| ' | |
| - pattern: '$PARSER = new libxmljs.SaxPushParser() | |
| ... | |
| $FOO = <... $REQ.$QUERY ...>; | |
| ... | |
| $PARSER.push(..., <... $FOO ...>, ...) | |
| ' | |
| - pattern: '$PARSER = new libxmljs.SaxPushParser() | |
| ... | |
| $FOO = <... $REQ.$QUERY.$BAR ...>; | |
| ... | |
| $PARSER.push(..., <... $FOO ...> , ...) | |
| ' | |
| - pattern: '$PARSER = new libxmljs.SaxPushParser() | |
| ... | |
| $FOO = <... $REQ.$QUERY.$BAR.$FILE ...>; | |
| ... | |
| $PARSER.push(..., <... $FOO ...> , ...) | |
| ' | |
| message: 'User controlled data in XML parsers can result in XML External or Internal | |
| Entity (XXE) Processing vulnerabilities | |
| ' | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A4:2017-XML External Entities (XXE) | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-611 | |
| shortDescription: Improper restriction of XML external entity reference | |
| security-severity: CRITICAL | |
| category: security | |
| - id: rules_lgpl_javascript_headers_rule-generic-cors | |
| patterns: | |
| - pattern: '$APP.options(''*'', cors(...)) | |
| ' | |
| message: 'Access-Control-Allow-Origin response header is set to "*". This will disable | |
| CORS Same Origin Policy restrictions. | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-346 | |
| shortDescription: Origin validation error | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_headers_rule-helmet-feature-disabled | |
| patterns: | |
| - pattern-either: | |
| - pattern: '$HELMET(..., {frameguard: false}, ...) | |
| ' | |
| - pattern: '$HELMET(..., {contentSecurityPolicy: false}, ...) | |
| ' | |
| - pattern: '$HELMET(..., {permittedCrossDomainPolicies: false}, ...) | |
| ' | |
| - pattern: '$HELMET(..., {dnsPrefetchControl: false}, ...) | |
| ' | |
| - pattern: '$HELMET(..., {expectCt: false}, ...) | |
| ' | |
| - pattern: '$HELMET(..., {featurePolicy: false}, ...) | |
| ' | |
| - pattern: '$HELMET(..., {hsts: false}, ...) | |
| ' | |
| - pattern: '$HELMET(..., {ieNoOpen: false}, ...) | |
| ' | |
| - pattern: '$HELMET(..., {noSniff: false}, ...) | |
| ' | |
| - pattern: '$HELMET(..., {hidePoweredBy: false}, ...) | |
| ' | |
| - pattern: '$HELMET(..., {referrerPolicy: false}, ...) | |
| ' | |
| - pattern: '$HELMET(..., {xssFilter: false}, ...) | |
| ' | |
| message: 'One or more Security Response header is explicitly disabled in Helmet. | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-358 | |
| shortDescription: Improperly implemented security check for standard | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_headers_rule-cookie-session-no-domain | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: '$SESSION = require(''cookie-session'') | |
| ... | |
| ' | |
| - pattern-inside: '$SESSION = require(''express-session'') | |
| ... | |
| ' | |
| - pattern: $SESSION(...) | |
| - pattern-not-inside: $SESSION(<... {cookie:{domain:...}} ...>,...) | |
| - pattern-not-inside: '$OPTS = <... {cookie:{domain:...}} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $COOKIE = <... {domain:...} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $OPTS.cookie = <... {domain:...} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $COOKIE.domain = ...; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $OPTS.cookie.domain = ...; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| message: '''Default session middleware settings: `domain` not set. It indicates | |
| the domain of the cookie; use it to compare against the domain of the server in | |
| which the URL is being requested. If they match, then check the path attribute | |
| next.'' | |
| ' | |
| severity: INFO | |
| languages: | |
| - javascript | |
| metadata: | |
| owasp: | |
| - A2:2017-Broken Authentication | |
| - A07:2021-Identification and Authentication Failures | |
| cwe: CWE-522 | |
| shortDescription: Insufficiently protected credentials | |
| security-severity: INFO | |
| category: security | |
| - id: rules_lgpl_javascript_headers_rule-cookie-session-no-samesite | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: '$SESSION = require(''cookie-session'') | |
| ... | |
| ' | |
| - pattern-inside: '$SESSION = require(''express-session'') | |
| ... | |
| ' | |
| - pattern: $SESSION(...) | |
| - pattern-not-inside: $SESSION(<... {cookie:{sameSite:true}} ...>,...) | |
| - pattern-not-inside: $SESSION(<... {cookie:{sameSite:'lax'}} ...>,...) | |
| - pattern-not-inside: $SESSION(<... {cookie:{sameSite:'strict'}} ...>,...) | |
| - pattern-not-inside: '$OPTS = <... {cookie:{sameSite:true}} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $COOKIE = <... {sameSite:true} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $OPTS.cookie = <... {sameSite:true} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $COOKIE.sameSite = true; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $OPTS.cookie.sameSite = true; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = <... {cookie:{sameSite:''strict''}} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $COOKIE = <... {sameSite:''strict''} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $OPTS.cookie = <... {sameSite:''strict''} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $COOKIE.sameSite = ''strict''; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $OPTS.cookie.sameSite = ''strict''; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| message: '''Default session middleware settings: `sameSite` attribute is not configured | |
| to strict or lax. These configurations provides protection against Cross Site | |
| Request Forgery attacks.'' | |
| ' | |
| severity: WARNING | |
| languages: | |
| - javascript | |
| metadata: | |
| owasp: | |
| - A2:2017-Broken Authentication | |
| - A07:2021-Identification and Authentication Failures | |
| cwe: CWE-1275 | |
| shortDescription: Sensitive cookie with improper SameSite attribute | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_headers_rule-header-xss-lusca | |
| patterns: | |
| - pattern-inside: '$X = require(''lusca'') | |
| ... | |
| ' | |
| - pattern-not: '$X.use(helmet()) | |
| ' | |
| - pattern-either: | |
| - pattern: '$X.xssProtection(false) | |
| ' | |
| - pattern: '$X({ xssProtection: false}) | |
| ' | |
| message: 'X-XSS-Protection header is set to 0. This will disable the browser''s | |
| XSS Filter. | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-358 | |
| shortDescription: Improperly implemented security check for standard | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_headers_rule-header-xss-generic | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: '$RES.header("=~/x-xss-protection/i", 0, ...) | |
| ' | |
| - pattern: '$RES.set("=~/x-xss-protection/i", 0, ...) | |
| ' | |
| - pattern: '$RES.set(..., { "=~/x-xss-protection/i" : 0 }, ...) | |
| ' | |
| - pattern: '$RES.writeHead(..., {"=~/x-xss-protection/i": 0 }, ...) | |
| ' | |
| message: 'X-XSS-Protection header is set to 0. This will disable the browser''s | |
| XSS Filter. | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-358 | |
| shortDescription: Improperly implemented security check for standard | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_headers_rule-cookie-session-no-path | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: '$SESSION = require(''cookie-session'') | |
| ... | |
| ' | |
| - pattern-inside: '$SESSION = require(''express-session'') | |
| ... | |
| ' | |
| - pattern: $SESSION(...) | |
| - pattern-not-inside: $SESSION(<... {cookie:{path:...}} ...>,...) | |
| - pattern-not-inside: '$OPTS = <... {cookie:{path:...}} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $COOKIE = <... {path:...} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $OPTS.cookie = <... {path:...} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $COOKIE.path = ...; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $OPTS.cookie.path = ...; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| message: '''Default session middleware settings: `path` not set. It indicates the | |
| path of the cookie; use it to compare against the request path. If this and domain | |
| match, then send the cookie in the request.'' | |
| ' | |
| severity: INFO | |
| languages: | |
| - javascript | |
| metadata: | |
| owasp: | |
| - A2:2017-Broken Authentication | |
| - A07:2021-Identification and Authentication Failures | |
| cwe: CWE-522 | |
| shortDescription: Insufficiently protected credentials | |
| security-severity: INFO | |
| category: security | |
| - id: rules_lgpl_javascript_headers_rule-cookie-session-no-secure | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: '$SESSION = require(''cookie-session'') | |
| ... | |
| ' | |
| - pattern-inside: '$SESSION = require(''express-session'') | |
| ... | |
| ' | |
| - pattern: $SESSION(...) | |
| - pattern-not-inside: $SESSION(<... {cookie:{secure:true}} ...>,...) | |
| - pattern-not-inside: '$OPTS = <... {cookie:{secure:true}} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $COOKIE = <... {secure:true} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $OPTS.cookie = <... {secure:true} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $COOKIE.secure = true; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $OPTS.cookie.secure = true; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| message: '''Default session middleware settings: `secure` not set. It ensures the | |
| browser only sends the cookie over HTTPS.'' | |
| ' | |
| severity: WARNING | |
| languages: | |
| - javascript | |
| metadata: | |
| owasp: | |
| - A2:2017-Broken Authentication | |
| - A07:2021-Identification and Authentication Failures | |
| cwe: CWE-614 | |
| shortDescription: Sensitive cookie in HTTPS session without 'Secure' attribute | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_headers_rule-cookie-session-no-maxage | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: '$SESSION = require(''cookie-session'') | |
| ... | |
| ' | |
| - pattern-inside: '$SESSION = require(''express-session'') | |
| ... | |
| ' | |
| - pattern: $SESSION(...) | |
| - pattern-not-inside: $SESSION(<... {cookie:{maxAge:...}} ...>,...) | |
| - pattern-not-inside: '$OPTS = <... {cookie:{maxAge:...}} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $COOKIE = <... {maxAge:...} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $OPTS.cookie = <... {maxAge:...} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $COOKIE.maxAge = ...; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $OPTS.cookie.maxAge = ...; | |
| ... | |
| $SESSION($OPTS,...)' | |
| message: '''Session middleware settings: `maxAge` not set. Use it to set expiration | |
| date for cookies.'' | |
| ' | |
| severity: INFO | |
| languages: | |
| - javascript | |
| metadata: | |
| owasp: | |
| - A2:2017-Broken Authentication | |
| - A07:2021-Identification and Authentication Failures | |
| cwe: CWE-613 | |
| shortDescription: Insufficient session expiration | |
| security-severity: INFO | |
| category: security | |
| - id: rules_lgpl_javascript_headers_rule-cookie-session-default | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: '$SESSION = require(''cookie-session'') | |
| ... | |
| ' | |
| - pattern-inside: '$SESSION = require(''express-session'') | |
| ... | |
| ' | |
| - pattern: $SESSION(...) | |
| - pattern-not-inside: $SESSION(<... {name:...} ...>,...) | |
| - pattern-not-inside: '$OPTS = <... {name:...} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-not-inside: '$OPTS = ...; | |
| ... | |
| $OPTS.name = ...; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| message: 'Consider changing the default session cookie name. An attacker can use | |
| it to fingerprint the server and target attacks accordingly. | |
| ' | |
| severity: INFO | |
| languages: | |
| - javascript | |
| metadata: | |
| owasp: | |
| - A2:2017-Broken Authentication | |
| - A07:2021-Identification and Authentication Failures | |
| cwe: CWE-522 | |
| shortDescription: Insufficiently protected credentials | |
| security-severity: INFO | |
| category: security | |
| - id: rules_lgpl_javascript_headers_rule-cookie-session-no-httponly | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: '$SESSION = require(''cookie-session'') | |
| ... | |
| ' | |
| - pattern-inside: '$SESSION = require(''express-session'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: $SESSION(<... {cookie:{httpOnly:false}} ...>,...) | |
| - pattern-inside: '$OPTS = <... {cookie:{httpOnly:false}} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-inside: '$OPTS = ...; | |
| ... | |
| $COOKIE = <... {httpOnly:false} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-inside: '$OPTS = ...; | |
| ... | |
| $OPTS.cookie = <... {httpOnly:false} ...>; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-inside: '$OPTS = ...; | |
| ... | |
| $COOKIE.httpOnly = false; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| - pattern-inside: '$OPTS = ...; | |
| ... | |
| $OPTS.cookie.httpOnly = false; | |
| ... | |
| $SESSION($OPTS,...) | |
| ' | |
| message: '''Session middleware settings: `httpOnly` is explicitly set to false. It | |
| ensures that sensitive cookies cannot be accessed by client side JavaScript and | |
| helps to protect against cross-site scripting attacks.'' | |
| ' | |
| severity: WARNING | |
| languages: | |
| - javascript | |
| metadata: | |
| owasp: | |
| - A2:2017-Broken Authentication | |
| - A07:2021-Identification and Authentication Failures | |
| cwe: CWE-1004 | |
| shortDescription: Sensitive cookie without 'HttpOnly' flag | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_headers_rule-express-cors | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: '$APP.options(''*'', cors(...)) | |
| ' | |
| - pattern: '$RES.set("=~/access-control-allow-origin/i", ''*'', ...) | |
| ' | |
| - pattern: '$RES.set(..., { "=~/access-control-allow-origin/i" : ''*'' }, ...) | |
| ' | |
| - pattern: '$RES.header("=~/access-control-allow-origin/i", ''*'', ...) | |
| ' | |
| - pattern: '$RES.writeHead(..., {"=~/access-control-allow-origin/i": ''*'' }, | |
| ...) | |
| ' | |
| message: 'Access-Control-Allow-Origin response header is set to "*". This will disable | |
| CORS Same Origin Policy restrictions. | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-346 | |
| shortDescription: Origin validation error | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_headers_rule-generic-header-injection | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: '$INP = $REQ.$QUERY; | |
| ... | |
| $RES.set(..., <... $INP ...>, ...) | |
| ' | |
| - pattern: '$INP = $REQ.$QUERY.$VAR; | |
| ... | |
| $RES.set(..., <... $INP ...>, ...) | |
| ' | |
| - pattern: '$INP = $REQ.$VAR; | |
| ... | |
| $RES.set(..., { $X: <... $INP ...>}, ...) | |
| ' | |
| - pattern: '$INP = $REQ.$QUERY.$FOO; | |
| ... | |
| $RES.set(..., { $X: <... $INP ...>}, ...) | |
| ' | |
| - pattern: '$INP = $REQ.$VAR; | |
| ... | |
| $RES.writeHead(..., { $X: <... $INP ...> }, ...) | |
| ' | |
| - pattern: '$INP = $REQ.$QUERY.$FOO; | |
| ... | |
| $RES.writeHead(..., { $X: <... $INP ...> }, ...) | |
| ' | |
| - pattern: '$RES.set(..., <... $REQ.$QUERY ...>, ...) | |
| ' | |
| - pattern: '$RES.set(..., <... $REQ.$QUERY.$VAR ...>, ...) | |
| ' | |
| - pattern: '$RES.set(..., { $X: <... $REQ.$VAR ...>}, ...) | |
| ' | |
| - pattern: '$RES.set(..., { $X: <... $REQ.$QUERY.$FOO ...>}, ...) | |
| ' | |
| - pattern: '$RES.writeHead(..., { $X: <... $REQ.$VAR ...> }, ...) | |
| ' | |
| - pattern: '$RES.writeHead(..., { $X: <... $REQ.$QUERY.$FOO ...> }, ...) | |
| ' | |
| message: 'Untrusted user input in response header will result in HTTP Header Injection | |
| or Response Splitting Attacks. | |
| ' | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-644 | |
| shortDescription: Improper neutralization of HTTP headers for scripting syntax | |
| security-severity: CRITICAL | |
| category: security | |
| - id: rules_lgpl_javascript_headers_rule-host-header-injection | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: '$X = <... "=~/.*http[s]*:///i" + $REQ.host ...>; | |
| ' | |
| - pattern: '$X = <... "=~/.*http[s]*:///i" + $REQ["host"] ...>; | |
| ' | |
| - pattern: '$X = <... "=~/.*http[s]*:///i" + $REQ("host") ...>; | |
| ' | |
| - pattern: '$X = { $Y: <... "=~/.*http[s]*:///i" + $REQ.host ...>}; | |
| ' | |
| - pattern: '$X = { $Y: <... "=~/.*http[s]*:///i" + $REQ["host"] ...>}; | |
| ' | |
| - pattern: '$X = { $Y: <... "=~/.*http[s]*:///i" + $REQ("host") ...>}; | |
| ' | |
| - pattern: '$Z = $REQ.host; | |
| ... | |
| $X = <... "=~/.*http[s]*:///i" + $Z ...>; | |
| ' | |
| - pattern: '$Z = $REQ["host"]; | |
| ... | |
| $X = <... "=~/.*http[s]*:///i" + $Z ...>; | |
| ' | |
| - pattern: '$Z = $REQ("host") | |
| ... | |
| $X = <... "=~/.*http[s]*:///i" + $Z ...>; | |
| ' | |
| - pattern: '$Z = $REQ.host; | |
| ... | |
| $X = { $Y: <... "=~/.*http[s]*:///i" + $REQ.host ...>}; | |
| ' | |
| - pattern: '$Z = $REQ["host"]; | |
| ... | |
| $X = { $Y: <... "=~/.*http[s]*:///i" + $Z ...>}; | |
| ' | |
| - pattern: '$Z = $REQ("host") | |
| ... | |
| $X = { $Y: <... "=~/.*http[s]*:///i" + $REQ("host") ...>}; | |
| ' | |
| message: 'Using untrusted Host header for generating dynamic URLs can result in | |
| web cache and or password reset poisoning. | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-348 | |
| shortDescription: Use of less trusted source | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_traversal_rule-admzip-path-overwrite | |
| patterns: | |
| - pattern-inside: '$X = require(''adm-zip'') | |
| ... | |
| ' | |
| - pattern-not: 'if ($FILENAME.indexOf(''..'')) | |
| ' | |
| - pattern-not: '$FS.createWriteStream($PATH.join(..., $PATH.basename($FILENAME, | |
| ...))) | |
| ' | |
| - pattern-not: '$FS.writeFile($PATH.join(..., $PATH.basename($FILENAME, ...))) | |
| ' | |
| - pattern-not: '$FS.writeFileSync($PATH.join(..., $PATH.basename($FILENAME, ...))) | |
| ' | |
| - pattern-either: | |
| - pattern: $ZIPENTZ.forEach(function $FUNC($ENTRY, ...) { $FS.createWriteStream(...) | |
| }, ...) | |
| - pattern: $ZIPENTZ.forEach(function $FUNC($ENTRY, ...) { $FS.writeFile(...) }, | |
| ...) | |
| - pattern: $ZIPENTZ.forEach(function $FUNC($ENTRY, ...) { $FS.writeFileSync(...) | |
| }, ...) | |
| message: 'Insecure ZIP archive extraction using adm-zip can result in arbitrary | |
| path over write and can result in code injection. | |
| ' | |
| languages: | |
| - javascript | |
| metadata: | |
| shortDescription: Improper limitation of a pathname to a restricted directory | |
| ('Path Traversal') | |
| cwe: CWE-22 | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| security-severity: MEDIUM | |
| category: security | |
| severity: WARNING | |
| - id: rules_lgpl_javascript_traversal_rule-join-resolve-path-traversal | |
| patterns: | |
| - pattern-inside: 'require(''path'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: $PATH.join(...,<... $REQ.$BODY ...>,...) | |
| - pattern: $PATH.join(...,<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: '$VAR = <... $REQ.$BODY ...>; | |
| ... | |
| $PATH.join(...,<... $VAR ...>,...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PATH.join(...,<... $VAR ...>,...) | |
| ' | |
| - pattern: $PATH.resolve(...,<... $REQ.$BODY ...>,...) | |
| - pattern: $PATH.resolve(...,<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: '$VAR = <... $REQ.$BODY ...>; | |
| ... | |
| $PATH.resolve(...,<... $VAR ...>,...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $PATH.resolve(...,<... $VAR ...>,...)' | |
| message: '''Path constructed with user input can result in Path Traversal. Ensure | |
| that user input does not reach `join()` or `resolve()`. '' | |
| ' | |
| languages: | |
| - javascript | |
| metadata: | |
| shortDescription: Improper limitation of a pathname to a restricted directory | |
| ('Path Traversal') | |
| cwe: CWE-22 | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| security-severity: MEDIUM | |
| category: security | |
| severity: WARNING | |
| - id: rules_lgpl_javascript_traversal_rule-zip-path-overwrite | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: 'import $X from ''unzipper'' | |
| ... | |
| ' | |
| - pattern-inside: '$X = require(''unzipper'') | |
| ... | |
| ' | |
| - pattern-inside: "$Y.pipe($X.Parse(...)).on('entry', function $FUNC(...) {\n \ | |
| \ ...\n}, ...)\n" | |
| - pattern-not-inside: "if (<... $FILENAME.indexOf(...) ...>){ \n...\n}\n" | |
| - pattern-not-inside: '$BASE = $PATH.basename($FILENAME, ...) | |
| ... | |
| $JOIN = $PATH.join(..., $BASE) | |
| ... | |
| ' | |
| - pattern-not: '$FS.$MTD($PATH.join(..., $PATH.basename($FILENAME, ...))) | |
| ' | |
| - pattern: '$FS.$MTD($FIL, ...) | |
| ' | |
| - metavariable-regex: | |
| metavariable: $MTD | |
| regex: ^(writeFileSync|writeFile|createWriteStream)$ | |
| message: "This application is extracting ZIP archives without sanitizing paths or\ | |
| \ writing files to a dedicated extraction directory. \nThis allows attackers to\ | |
| \ overwrite sensitive files or inject malicious code by manipulating TAR archive\ | |
| \ contents.\n\nTo fix, sanitize all paths from ZIP archives before writing extracted\ | |
| \ files using path.basename and path.join.\n\nExample of extracting tar files\ | |
| \ safely:\n```\napp.get(\"/extract\", async (req, res) => {\n fs.createReadStream(zipPath)\n\ | |
| \ .pipe(unzipper.Parse())\n .on('entry', entry => {\n \ | |
| \ const directory = 'assets/tar/extracted/';\n const filename = entry.path;\n\ | |
| \ entry.pipe(fs.createWriteStream(path.join(directory, filename)));\n\ | |
| \ });\n});\n```\n\nWrite extracted files only to a dedicated extraction\ | |
| \ directory, not the global filesystem. Limit extracts to allowed file type.\n\ | |
| \nSee OWASP Path Traversal (https://owasp.org/www-community/attacks/Path_Traversal)\ | |
| \ and Unrestricted Upload of File with \nDangerous Type (https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload)\ | |
| \ for more details.\n" | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Improper limitation of a pathname to a restricted directory | |
| ('Path Traversal') | |
| cwe: CWE-22 | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_traversal_rule-tar-path-overwrite | |
| patterns: | |
| - pattern-inside: '$X = require(''tar-stream'') | |
| ... | |
| ' | |
| - pattern-not-inside: "$Y.pipe($UNZIP.Parse(...)).on('entry', function $FUNC(...)\ | |
| \ {\n ...\n}, ...)\n" | |
| - pattern-inside: "$EXTRACT.on('entry', function $FUNC(...) {\n ...\n}, ...)\n" | |
| - pattern-not: 'if ($FILENAME.indexOf(''..'')) | |
| ' | |
| - pattern-not: '$FS.createWriteStream($PATH.join(..., $PATH.basename($FILENAME, | |
| ...))) | |
| ' | |
| - pattern-not: '$FS.writeFile($PATH.join(..., $PATH.basename($FILENAME, ...))) | |
| ' | |
| - pattern-not: '$FS.writeFileSync($PATH.join(..., $PATH.basename($FILENAME, ...))) | |
| ' | |
| - pattern-either: | |
| - pattern: '$FS.createWriteStream($FIL, ...) | |
| ' | |
| - pattern: '$FS.writeFile($FIL, ...) | |
| ' | |
| - pattern: '$FS.writeFileSync($FIL, ...) | |
| ' | |
| message: 'Insecure TAR archive extraction can result in arbitrary path over write | |
| and can result in code injection. | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Improper limitation of a pathname to a restricted directory | |
| ('Path Traversal') | |
| cwe: CWE-22 | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_traversal_rule-generic-path-traversal | |
| mode: taint | |
| languages: | |
| - javascript | |
| pattern-sources: | |
| - patterns: | |
| - focus-metavariable: $REQ | |
| - pattern: function ($REQ, $RES, ...) {...} | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: '$FS = require(''fs'') | |
| ... | |
| ' | |
| - pattern-inside: 'import $FS from ''fs'' | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: $FS.createReadStream(...) | |
| - patterns: | |
| - pattern: $FS.readFile($REQ, ...) | |
| - focus-metavariable: $REQ | |
| - patterns: | |
| - pattern: $FS.readFileSync($REQ,...) | |
| - focus-metavariable: $REQ | |
| - patterns: | |
| - pattern: $FS.readFileAsync($REQ,...) | |
| - focus-metavariable: $REQ | |
| message: "This application is using untrusted user input with the readFile() and\n\ | |
| readFileSync() functions. \nThis can lead to directory traversal attacks, as reading\ | |
| \ files with untrusted input enables arbitrary file access.\nAn attacker could\ | |
| \ craft malicious input that traverses the file system and exposes sensitive files.\ | |
| \ \nPlease consider sanitizing and validating all user input before passing it\ | |
| \ to readFile() or readFileSync() to prevent unwanted file reads.\nHere is an\ | |
| \ example of a safer usage in readFileAsync():\n```\napp.get('/foo', function\ | |
| \ (req, res) {\n var fileName = config.dirName + '/' + data;\n fs.readFileAsync(\"\ | |
| fileName\")\n .then(function (data) {\n res.download(fileName,\ | |
| \ downloadFileName);\n })\n })\n```\nFor more details see: \nhttps://owasp.org/www-community/attacks/Path_Traversal\n" | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| cwe: CWE-23 | |
| shortDescription: Relative path traversal | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_traversal_rule-express-lfr | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern: $REQ.$FUNC. ... | |
| - metavariable-regex: | |
| metavariable: $FUNC | |
| regex: ^(body|params|query|cookies|hostname|subdomains|ip|ips|originalUrl|path)$ | |
| pattern-sinks: | |
| - pattern: $RES.render(..., $VAR) | |
| message: "This application is using untrusted user input in express render() function.\n\ | |
| Rendering templates with untrusted user input enables arbitrary file read \nvulnerabilities\ | |
| \ when using templating engines like Handlebars (hbs). \n\nAn attacker can craft\ | |
| \ malicious input that traverses the filesystem and exposes sensitive files. \n\ | |
| Consider sanitizing and validating all user input before passing it to render()\ | |
| \ to prevent arbitrary file reads. \n\nSample safe use of express.render function\n\ | |
| ```\napp.get(\"/traversal/2\", async (req, res) => {\n var indexPath = \"index\"\ | |
| ;\n res.render(indexPath, { title: \"Index Page\" })\n});\n```\n\nFor more\ | |
| \ details see: \nhttps://owasp.org/www-community/attacks/Path_Traversal\n" | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| cwe: CWE-23 | |
| shortDescription: Relative path traversal | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_traversal_rule-express-lfr-warning | |
| patterns: | |
| - pattern-not-inside: 'require(''hbs'') | |
| ... | |
| ' | |
| - pattern-inside: 'require(''express'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: '$INP = <... $REQ.$QUERY ...>; | |
| ... | |
| $RES.render($VIEW, <... $INP ...>) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $RES.render($VIEW, <... $INP ...>) | |
| ' | |
| - pattern: $RES.render($VIEW, <... $REQ.$QUERY.$FOO ...>) | |
| - pattern: $RES.render($VIEW, <... $REQ.$BODY ...>) | |
| message: 'Untrusted user input in express render() function can result in arbitrary | |
| file read if hbs templating is used. | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| cwe: CWE-23 | |
| shortDescription: Relative path traversal | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_redirect_rule-express-open-redirect | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-inside: 'function ($REQ, $RES, ...) {...} | |
| ' | |
| - focus-metavariable: $REQ | |
| pattern-sinks: | |
| - pattern: '$RES.redirect(...) | |
| ' | |
| pattern-sanitizers: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: "if($VALIDATION){\n ...\n $RES.redirect(...)\n ...\n} \n" | |
| - pattern: "$A = $VALIDATION\n...\nif($A){\n ...\n $RES.redirect(...)\n\ | |
| \ ...\n}\n" | |
| - metavariable-pattern: | |
| metavariable: $VALIDATION | |
| pattern-either: | |
| - pattern: "$AL.includes(...) \n" | |
| - pattern: '$AL.indexOf(...) !== -1 | |
| ' | |
| - pattern: '$AL.find(...) !== undefined | |
| ' | |
| - pattern: '$ALS.has(...) | |
| ' | |
| - patterns: | |
| - pattern: '$RES.redirect("$DOM" + ...) | |
| ' | |
| - metavariable-regex: | |
| metavariable: $DOM | |
| regex: (http(s)?:\/\/.*\/) | |
| message: "Passing untrusted user input in `redirect()` can result in an open redirect\n\ | |
| vulnerability. This could be abused by malicious actors to trick users into \n\ | |
| being redirected to websites under their control to capture authentication\ninformation.\ | |
| \ \nTo prevent open redirect vulnerabilities:\n\n- Always validate and sanitize\ | |
| \ user inputs, especially URL parameters\n or query strings that may influence\ | |
| \ the flow of the application.\n- Use allowlists (lists of permitted URLs) to\ | |
| \ validate redirect targets \n against known, trusted URLs before performing the\ | |
| \ redirect.\n- Avoid directly using user input for redirecting. If unavoidable,\ | |
| \ ensure\n strict validation against an allowlist.\n\nFollowing is an example\ | |
| \ of secure validation against allowlist to prevent the vulnerability:\n ```\n\ | |
| \ // Define a list of explicitly allowed URLs for redirection\n const allowedUrls\ | |
| \ = [\n 'https://www.example.com/page1',\n 'https://www.example.com/page2',\n\ | |
| \ 'https://secure.example.com/page3'\n ];\n\n app.get('/redirect/:url', (req,\ | |
| \ res) => {\n const url = decodeURIComponent(req.params.url);\n const\ | |
| \ isAllowed = allowedUrls.includes(url);\n if (isAllowed) {\n // If\ | |
| \ the URL is allowed, proceed with the redirect\n res.redirect(url);\n\ | |
| \ } else {\n res.status(400).send('Invalid redirect URL');\n }\n\ | |
| \ });\n ```\n" | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| shortDescription: URL redirection to untrusted site 'open redirect' | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-601 | |
| security-severity: CRITICAL | |
| - id: rules_lgpl_javascript_redirect_rule-express-open-redirect2 | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-inside: 'function ($REQ, $RES, ...) {...} | |
| ' | |
| - focus-metavariable: $REQ | |
| pattern-sinks: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-not: '$RES.$METHOD("=~/location/i", "=~/http(s)?:\/\/.*\//" + ...) | |
| ' | |
| - pattern-not-inside: '$VAR = "=~/http(s)?:\/\/.*\//" + ...; | |
| ... | |
| ' | |
| - pattern: '$RES.$METHOD("=~/location/i", $VAR) | |
| ' | |
| - metavariable-regex: | |
| metavariable: $METHOD | |
| regex: (header|set|append|setHeader) | |
| - patterns: | |
| - pattern-not-inside: '$V = "=~/http(s)?:\/\/.*\//" + ...; | |
| ... | |
| ' | |
| - pattern-not: | |
| patterns: | |
| - pattern: "$RES.writeHead(..., { \n ..., \n location: $V,\n ...\n\ | |
| })\n" | |
| - metavariable-pattern: | |
| metavariable: $V | |
| patterns: | |
| - pattern: '"=~/http(s)?:\/\/.*\//" + ... | |
| ' | |
| - pattern: "$RES.writeHead(..., { \n ..., \n location:\ | |
| \ $V,\n ...\n })\n" | |
| - focus-metavariable: $V | |
| - patterns: | |
| - pattern-not: '$RES.location("=~/http(s)?:\/\/.*\//" + ...) | |
| ' | |
| - pattern-not-inside: '$VAR = "=~/http(s)?:\/\/.*\//" + ...; | |
| ... | |
| ' | |
| - pattern: '$RES.location($VAR) | |
| ' | |
| pattern-sanitizers: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: "if($VALIDATION){\n ...\n} \n" | |
| - pattern: "$A = $VALIDATION\n...\nif($A){\n ...\n}\n" | |
| - metavariable-pattern: | |
| metavariable: $VALIDATION | |
| pattern-either: | |
| - pattern: "$AL.includes(...) \n" | |
| - pattern: '$AL.indexOf(...) !== -1 | |
| ' | |
| - pattern: '$AL.find(...) !== undefined | |
| ' | |
| - pattern: '$ALS.has(...) | |
| ' | |
| message: "Passing untrusted user input in `redirect()` can result in an open redirect\n\ | |
| vulnerability. This could be abused by malicious actors to trick users into \n\ | |
| being redirected to websites under their control to capture authentication\ninformation.\ | |
| \ \nTo prevent open redirect vulnerabilities:\n\n- Always validate and sanitize\ | |
| \ user inputs, especially URL parameters\n or query strings that may influence\ | |
| \ the flow of the application.\n- Use allowlists (lists of permitted URLs) to\ | |
| \ validate redirect targets \n against known, trusted URLs before performing the\ | |
| \ redirect.\n- Avoid directly using user input for redirecting. If unavoidable,\ | |
| \ ensure\n strict validation against an allowlist.\n\nFollowing is an example\ | |
| \ of secure validation against allowlist to prevent the vulnerability:\n ```\n\ | |
| \ // Define a list of explicitly allowed URLs for redirection\n const allowedUrls\ | |
| \ = [\n 'https://www.example.com/page1',\n 'https://www.example.com/page2',\n\ | |
| \ 'https://secure.example.com/page3'\n ];\n\n app.get('/redirect/:url', (req,\ | |
| \ res) => {\n const url = decodeURIComponent(req.params.url);\n const\ | |
| \ isAllowed = allowedUrls.includes(url);\n if (isAllowed) {\n // If\ | |
| \ the URL is allowed, proceed with the redirect\n res.location(url).status(302).end();\n\ | |
| \ } else {\n res.status(400).send('Invalid redirect URL');\n }\n\ | |
| \ });\n ```\n" | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| shortDescription: URL redirection to untrusted site 'open redirect' | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-601 | |
| security-severity: CRITICAL | |
| - id: javascript_exec_rule-child-process | |
| message: "OS command injection is a critical vulnerability that can lead to a full\ | |
| \ system\ncompromise as it may allow an adversary to pass in arbitrary commands\ | |
| \ or arguments\nto be executed.\n\nUser input should never be used in constructing\ | |
| \ commands or command arguments\nto functions which execute OS commands. This\ | |
| \ includes filenames supplied by\nuser uploads or downloads.\n\nEnsure your application\ | |
| \ does not:\n\n- Use user-supplied information in the process name to execute.\n\ | |
| - Use user-supplied information in an OS command execution function which does\n\ | |
| not escape shell meta-characters.\n- Use user-supplied information in arguments\ | |
| \ to OS commands.\n\nThe application should have a hardcoded set of arguments\ | |
| \ that are to be passed\nto OS commands. If filenames are being passed to these\ | |
| \ functions, it is\nrecommended that a hash of the filename be used instead, or\ | |
| \ some other unique\nidentifier. It is strongly recommended that a native library\ | |
| \ that implements\nthe same functionality be used instead of using OS system commands,\ | |
| \ due to the\nrisk of unknown attacks against third-party commands.\n\nWhen specifying\ | |
| \ the OS command, ensure the application uses the full path\ninformation, otherwise\ | |
| \ the OS may attempt to look up which process to execute\nand could be vulnerable\ | |
| \ to untrusted search path vulnerabilities (CWE-426).\n\nExample of safely executing\ | |
| \ an OS command:\n```\nconst child_process = require('child_process');\nconst\ | |
| \ fs = require('fs');\nconst crypto = require('node:crypto');\nconst { mkdtempSync\ | |
| \ } = require('node:fs');\n\nfunction executeCommand(userFileData) {\n // Create\ | |
| \ a temporary directory, preferably in an application directory\n // that only\ | |
| \ the application has access to.\n const fileDir = mkdtempSync('/tmp/tmpdir-');\n\ | |
| \ // Generate a random filename, do not use user input\n const filePath\ | |
| \ = fileDir + path.sep + crypto.randomUUID();\n // Write the user-supplied\ | |
| \ data to the temporary file.\n fs.writeFileSync(filePath, userFileData);\n\ | |
| \ // Execute a program with a hardcoded path to the binary\n child_process.exec(`/bin/cat\ | |
| \ ${filePath}`, (error, stdout, stderr) => {\n // Delete the temporary\ | |
| \ directory and file if no longer needed\n fs.rmSync(fileDir, { recursive:\ | |
| \ true, force: true });\n if (error) {\n console.error(`exec error:\ | |
| \ ${error}`);\n return;\n }\n console.log(`stdout: ${stdout}`);\n\ | |
| \ console.error(`stderr: ${stderr}`);\n });\n}\n```\n\nFor more information\ | |
| \ on OS command injection, see OWASP's guide:\nhttps://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html\n\ | |
| \nDetected non-literal calls to child_process.exec(). This could lead to a command\n\ | |
| injection vulnerability.\n" | |
| metadata: | |
| cwe: CWE-78 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| shortDescription: Improper neutralization of special elements used in an OS command | |
| ('OS Command Injection') | |
| references: | |
| - https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions | |
| source-rule-url: https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js | |
| category: security | |
| technology: | |
| - javascript | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| cwe2022-top25: true | |
| cwe2021-top25: true | |
| subcategory: | |
| - audit | |
| vulnerability_class: | |
| - Command Injection | |
| security-severity: HIGH | |
| languages: | |
| - javascript | |
| - typescript | |
| severity: ERROR | |
| options: | |
| taint_unify_mvars: true | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-inside: "function ... (...,$ARG,...) {\n ...\n}\n" | |
| - focus-metavariable: $ARG | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: '$CP = require(''child_process'') | |
| ... | |
| ' | |
| - pattern-inside: 'import * as $CP from ''child_process'' | |
| ... | |
| ' | |
| - pattern-inside: 'import $CP from ''child_process'' | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: $CP.exec($CMD,...) | |
| - pattern: $CP.execSync($CMD,...) | |
| - pattern: $CP.spawn($CMD,...) | |
| - pattern: $CP.spawnSync($CMD,...) | |
| - focus-metavariable: $CMD | |
| pattern-sanitizers: | |
| - pattern: '$CMD = "..." | |
| ' | |
| - pattern: '$CMD = ["...",...] | |
| ' | |
| - id: rules_lgpl_javascript_exec_rule-shelljs-os-command-exec | |
| patterns: | |
| - pattern-inside: 'require(''shelljs'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: '$EXEC.exec(<... $REQ.$QUERY.$VAR ...>, ...) | |
| ' | |
| - pattern: '$EXEC.exec( <... $REQ.$QUERY ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY.$VAR ...>; | |
| ... | |
| $EXEC.exec(<... $INP ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY ...>; | |
| ... | |
| $EXEC.exec(<... $INP ...>, ...) | |
| ' | |
| message: 'User controlled data in ''shelljs.exec()'' can result in Remote OS Command | |
| Execution. | |
| ' | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Improper neutralization of special elements used in an OS command | |
| ('OS Command Injection') | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-78 | |
| security-severity: CRITICAL | |
| - id: rules_lgpl_javascript_eval_rule-eval-nodejs | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: 'new Function(..., <... $REQ.$QUERY.$VAR ...>, ...) | |
| ' | |
| - pattern: 'new Function(..., <... $REQ.$QUERY ...>, ...) | |
| ' | |
| - pattern: 'eval(..., <... $REQ.$QUERY.$VAR ...>, ...) | |
| ' | |
| - pattern: 'eval(..., <... $REQ.$QUERY ...>, ...) | |
| ' | |
| - pattern: 'setTimeout(..., <... $REQ.$QUERY.$VAR ...>, ...) | |
| ' | |
| - pattern: 'setTimeout(..., <... $REQ.$QUERY ...>, ...) | |
| ' | |
| - pattern: 'setInterval(..., <... $REQ.$QUERY.$VAR ...>, ...) | |
| ' | |
| - pattern: 'setInterval(..., <... $REQ.$QUERY ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY.$VAR ...>; | |
| ... | |
| new Function(..., <... $INP ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY ...>; | |
| ... | |
| new Function(..., <... $INP ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY.$VAR ...>; | |
| ... | |
| eval(..., <... $INP ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY ...>; | |
| ... | |
| eval(..., <... $INP ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY.$VAR ...>; | |
| ... | |
| setTimeout(..., <... $INP ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY ...>; | |
| ... | |
| setTimeout(..., <... $INP ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY.$VAR ...>; | |
| ... | |
| setInterval(..., <... $INP ...>, ...) | |
| ' | |
| - pattern: '$INP = <... $REQ.$QUERY ...>; | |
| ... | |
| setInterval(..., <... $INP ...>, ...) | |
| ' | |
| message: 'User controlled data in eval() or similar functions may result in Server | |
| Side Injection or Remote Code Injection | |
| ' | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| cwe: CWE-95 | |
| shortDescription: Improper neutralization of directives in dynamically evaluated | |
| code ('Eval Injection') | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: HIGH | |
| - id: rules_lgpl_javascript_eval_rule-vm-runinnewcontext-injection | |
| patterns: | |
| - pattern-inside: 'require(''vm'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: '$VM.runInNewContext($CODE,<... $REQ.$QUERY.$FOO ...>,...) | |
| ' | |
| - pattern: '$CONTEXT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $VM.runInNewContext($CODE,<... $CONTEXT ...>,...) | |
| ' | |
| - pattern: '$CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>}; | |
| ... | |
| $VM.runInNewContext($CODE,<... $CONTEXT ...>,...) | |
| ' | |
| - pattern: '$CONTEXT = <... {$NAME:$REQ.$QUERY.$FOO} ...>; | |
| ... | |
| $VM.runInNewContext($CODE,<... $CONTEXT ...>,...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $CONTEXT = {$NAME: <... $VAR ...>}; | |
| ... | |
| $VM.runInNewContext($CODE,<... $CONTEXT ...>,...) | |
| ' | |
| - pattern: '$VM.runInNewContext($CODE,<... $REQ.$BODY ...>,...) | |
| ' | |
| - pattern: '$CONTEXT = <... $REQ.$BODY ...>; | |
| ... | |
| $VM.runInNewContext($CODE,<... $CONTEXT ...>,...) | |
| ' | |
| - pattern: '$CONTEXT = {$NAME: <... $REQ.$BODY ...>}; | |
| ... | |
| $VM.runInNewContext($CODE,<... $CONTEXT ...>,...) | |
| ' | |
| - pattern: '$CONTEXT = <... {$NAME:$REQ.$BODY} ...>; | |
| ... | |
| $VM.runInNewContext($CODE,<... $CONTEXT ...>,...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$BODY ...>; | |
| ... | |
| $CONTEXT = {$NAME: <... $VAR ...>}; | |
| ... | |
| $VM.runInNewContext($CODE,<... $CONTEXT ...>,...) | |
| ' | |
| message: 'Untrusted user input in `vm.runInNewContext()` can result in code injection. | |
| ' | |
| severity: ERROR | |
| languages: | |
| - javascript | |
| metadata: | |
| cwe: CWE-94 | |
| shortDescription: Improper control of generation of code (Code Injection) | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| - id: rules_lgpl_javascript_eval_rule-vm-code-injection | |
| patterns: | |
| - pattern-inside: '$VM = require(''vm'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: $VM.runInContext(<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $VM.runInContext(<... $REQ.$BODY ...>,...) | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $VM.runInContext($INPUT,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $VM.runInContext($INPUT,...) | |
| ' | |
| - pattern: $VM.runInNewContext(<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $VM.runInNewContext(<... $REQ.$BODY ...>,...) | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $VM.runInNewContext($INPUT,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $VM.runInNewContext($INPUT,...) | |
| ' | |
| - pattern: $VM.runInThisContext(<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $VM.runInThisContext(<... $REQ.$BODY ...>,...) | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $VM.runInThisContext($INPUT,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $VM.runInThisContext($INPUT,...) | |
| ' | |
| - pattern: $VM.compileFunction(<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: $VM.compileFunction(<... $REQ.$BODY ...>,...) | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $VM.compileFunction($INPUT,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| $VM.compileFunction($INPUT,...) | |
| ' | |
| - pattern: new $VM.Script(<... $REQ.$QUERY.$FOO ...>,...) | |
| - pattern: new $VM.Script(<... $REQ.$BODY ...>,...) | |
| - pattern: '$INPUT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| new $VM.Script($INPUT,...) | |
| ' | |
| - pattern: '$INPUT = <... $REQ.$BODY ...>; | |
| ... | |
| new $VM.Script($INPUT,...) | |
| ' | |
| message: 'Untrusted user input reaching `vm` can result in code injection. | |
| ' | |
| severity: ERROR | |
| languages: | |
| - javascript | |
| metadata: | |
| cwe: CWE-94 | |
| shortDescription: Improper control of generation of code (Code Injection) | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| - id: rules_lgpl_javascript_eval_rule-yaml-deserialize | |
| patterns: | |
| - pattern-either: | |
| - pattern: 'require(''js-yaml'').load(...) | |
| ' | |
| - pattern-inside: '$MOD = require(''js-yaml'') | |
| ... | |
| ' | |
| - pattern-inside: 'import $MOD from ''js-yaml'' | |
| ... | |
| ' | |
| - pattern: '$MOD.load(...) | |
| ' | |
| message: 'User controlled data in ''yaml.load()'' function can result in Remote | |
| Code Injection. | |
| ' | |
| languages: | |
| - javascript | |
| - typescript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A8:2017-Insecure Deserialization | |
| - A08:2021-Software and Data Integrity Failures | |
| cwe: CWE-502 | |
| shortDescription: Deserialization of Untrusted Data | |
| security-severity: CRITICAL | |
| category: security | |
| - id: rules_lgpl_javascript_eval_rule-vm2-context-injection | |
| patterns: | |
| - pattern-inside: 'require(''vm2'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: 'new VM({sandbox: <... $REQ.$QUERY.$FOO ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| new VM({sandbox: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = <... {$NAME:$REQ.$QUERY.$FOO} ...>; | |
| ... | |
| new VM({sandbox: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>}; | |
| ... | |
| new VM({sandbox: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $CONTEXT = {$NAME: <... $VAR ...>}; | |
| ... | |
| new VM({sandbox: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$OPTS = {sandbox: <... $REQ.$QUERY.$FOO ...>}; | |
| ... | |
| new VM($OPTS,...) | |
| ' | |
| - pattern: '$CONTEXT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $OPTS = {sandbox: <... $CONTEXT ...>}; | |
| ... | |
| new VM($OPTS,...) | |
| ' | |
| - pattern: '$CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>}; | |
| ... | |
| $OPTS = {sandbox: <... $CONTEXT ...>}; | |
| ... | |
| new VM($OPTS,...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $CONTEXT = {$NAME: <... $VAR ...>}; | |
| ... | |
| $OPTS = {sandbox: <... $CONTEXT ...>}; | |
| ... | |
| new VM($OPTS,...) | |
| ' | |
| - pattern: 'new NodeVM({sandbox: <... $REQ.$QUERY.$FOO ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| new NodeVM({sandbox: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = <... {$NAME:$REQ.$QUERY.$FOO} ...>; | |
| ... | |
| new NodeVM({sandbox: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>}; | |
| ... | |
| new NodeVM({sandbox: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $CONTEXT = {$NAME: <... $VAR ...>}; | |
| ... | |
| new NodeVM({sandbox: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$OPTS = {sandbox: <... $REQ.$QUERY.$FOO ...>}; | |
| ... | |
| new NodeVM($OPTS,...) | |
| ' | |
| - pattern: '$CONTEXT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $OPTS = {sandbox: <... $CONTEXT ...>}; | |
| ... | |
| new NodeVM($OPTS,...) | |
| ' | |
| - pattern: '$CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>}; | |
| ... | |
| $OPTS = {sandbox: <... $CONTEXT ...>}; | |
| ... | |
| new NodeVM($OPTS,...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $CONTEXT = {$NAME: <... $VAR ...>}; | |
| ... | |
| $OPTS = {sandbox: <... $CONTEXT ...>}; | |
| ... | |
| new NodeVM($OPTS,...) | |
| ' | |
| - pattern: 'new VM({sandbox: <... $REQ.$BODY ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = <... $REQ.$BODY ...>; | |
| ... | |
| new VM({sandbox: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = <... {$NAME:$REQ.$BODY} ...>; | |
| ... | |
| new VM({sandbox: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = {$NAME: <... $REQ.$BODY ...>}; | |
| ... | |
| new VM({sandbox: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$BODY ...>; | |
| ... | |
| $CONTEXT = {$NAME: <... $VAR ...>}; | |
| ... | |
| new VM({sandbox: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$OPTS = {sandbox: <... $REQ.$BODY ...>}; | |
| ... | |
| new VM($OPTS,...) | |
| ' | |
| - pattern: '$CONTEXT = <... $REQ.$BODY ...>; | |
| ... | |
| $OPTS = {sandbox: <... $CONTEXT ...>}; | |
| ... | |
| new VM($OPTS,...) | |
| ' | |
| - pattern: '$CONTEXT = {$NAME: <... $REQ.$BODY ...>}; | |
| ... | |
| $OPTS = {sandbox: <... $CONTEXT ...>}; | |
| ... | |
| new VM($OPTS,...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$BODY ...>; | |
| ... | |
| $CONTEXT = {$NAME: <... $VAR ...>}; | |
| ... | |
| $OPTS = {sandbox: <... $CONTEXT ...>}; | |
| ... | |
| new VM($OPTS,...) | |
| ' | |
| - pattern: 'new NodeVM({sandbox: <... $REQ.$BODY ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = <... $REQ.$BODY ...>; | |
| ... | |
| new NodeVM({sandbox: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = <... {$NAME:$REQ.$BODY} ...>; | |
| ... | |
| new NodeVM({sandbox: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = {$NAME: <... $REQ.$BODY ...>}; | |
| ... | |
| new NodeVM({sandbox: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$BODY ...>; | |
| ... | |
| $CONTEXT = {$NAME: <... $VAR ...>}; | |
| ... | |
| new NodeVM({sandbox: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$OPTS = {sandbox: <... $REQ.$BODY ...>}; | |
| ... | |
| new NodeVM($OPTS,...) | |
| ' | |
| - pattern: '$CONTEXT = <... $REQ.$BODY ...>; | |
| ... | |
| $OPTS = {sandbox: <... $CONTEXT ...>}; | |
| ... | |
| new NodeVM($OPTS,...) | |
| ' | |
| - pattern: '$CONTEXT = {$NAME: <... $REQ.$BODY ...>}; | |
| ... | |
| $OPTS = {sandbox: <... $CONTEXT ...>}; | |
| ... | |
| new NodeVM($OPTS,...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$BODY ...>; | |
| ... | |
| $CONTEXT = {$NAME: <... $VAR ...>}; | |
| ... | |
| $OPTS = {sandbox: <... $CONTEXT ...>}; | |
| ... | |
| new NodeVM($OPTS,...)' | |
| message: 'Untrusted user input reaching `vm2` sandbox can result in context injection. | |
| ' | |
| severity: ERROR | |
| languages: | |
| - javascript | |
| metadata: | |
| cwe: CWE-94 | |
| shortDescription: Improper control of generation of code (Code Injection) | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| - id: rules_lgpl_javascript_eval_rule-vm-runincontext-injection | |
| patterns: | |
| - pattern-inside: 'require(''vm'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: '$CONTEXT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $VM.runInContext($CODE,<... $CONTEXT ...>,...) | |
| ' | |
| - pattern: '$CONTEXT = <... {$NAME:$REQ.$QUERY.$FOO} ...>; | |
| ... | |
| $VM.runInContext($CODE,<... $CONTEXT ...>,...) | |
| ' | |
| - pattern: '$CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>}; | |
| ... | |
| $VM.runInContext($CODE,<... $CONTEXT ...>,...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $CONTEXT = {$NAME: <... $VAR ...>}; | |
| ... | |
| $VM.runInContext($CODE,<... $CONTEXT ...>,...) | |
| ' | |
| - pattern: '$CONTEXT = <... $REQ.$BODY ...>; | |
| ... | |
| $VM.runInContext($CODE,<... $CONTEXT ...>,...) | |
| ' | |
| - pattern: '$CONTEXT = <... {$NAME:$REQ.$BODY} ...>; | |
| ... | |
| $VM.runInContext($CODE,<... $CONTEXT ...>,...) | |
| ' | |
| - pattern: '$CONTEXT = {$NAME: <... $REQ.$BODY ...>}; | |
| ... | |
| $VM.runInContext($CODE,<... $CONTEXT ...>,...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$BODY ...>; | |
| ... | |
| $CONTEXT = {$NAME: <... $VAR ...>}; | |
| ... | |
| $VM.runInContext($CODE,<... $CONTEXT ...>,...) | |
| ' | |
| message: 'Untrusted user input in `vm.runInContext()` can result in code injection. | |
| ' | |
| severity: ERROR | |
| languages: | |
| - javascript | |
| metadata: | |
| cwe: CWE-94 | |
| shortDescription: Improper control of generation of code (Code Injection) | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| - id: rules_lgpl_javascript_eval_rule-serializetojs-deserialize | |
| patterns: | |
| - pattern-either: | |
| - pattern: 'require(''serialize-to-js'').deserialize(...) | |
| ' | |
| - pattern-inside: '$MOD = require(''serialize-to-js'') | |
| ... | |
| ' | |
| - pattern-inside: 'import $MOD from ''serialize-to-js'' | |
| ... | |
| ' | |
| - pattern: '$MOD.deserialize(...) | |
| ' | |
| message: 'User controlled data in ''unserialize()'' or ''deserialize()'' function | |
| can result in Object Injection or Remote Code Injection. | |
| ' | |
| languages: | |
| - javascript | |
| - typescript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A8:2017-Insecure Deserialization | |
| - A08:2021-Software and Data Integrity Failures | |
| cwe: CWE-502 | |
| shortDescription: Deserialization of Untrusted Data | |
| security-severity: CRITICAL | |
| category: security | |
| - id: rules_lgpl_javascript_eval_rule-sandbox-code-injection | |
| patterns: | |
| - pattern-inside: 'require(''sandbox'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: '$S.run(<... $REQ.$QUERY.$FOO ...>,...) | |
| ' | |
| - pattern: '$CODE = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $S.run(<... $CODE ...>,...) | |
| ' | |
| - pattern: 'new $SANDBOX(...).run(<... $REQ.$QUERY.$FOO ...>,...) | |
| ' | |
| - pattern: '$CODE = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| new $SANDBOX(...).run(<... $CODE ...>,...) | |
| ' | |
| - pattern: '$S.run(<... $REQ.$BODY ...>,...) | |
| ' | |
| - pattern: '$CODE = <... $REQ.$BODY ...>; | |
| ... | |
| $S.run(<... $CODE ...>,...) | |
| ' | |
| - pattern: 'new $SANDBOX(...).run(<... $REQ.$BODY ...>,...) | |
| ' | |
| - pattern: '$CODE = <... $REQ.$BODY ...>; | |
| ... | |
| new $SANDBOX(...).run(<... $CODE ...>,...)' | |
| message: 'Unrusted data in `sandbox` can result in code injection. | |
| ' | |
| severity: ERROR | |
| languages: | |
| - javascript | |
| metadata: | |
| cwe: CWE-94 | |
| shortDescription: Improper control of generation of code (Code Injection) | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| - id: rules_lgpl_javascript_eval_rule-node-deserialize | |
| patterns: | |
| - pattern-either: | |
| - pattern: 'require(''node-serialize'').unserialize(...) | |
| ' | |
| - pattern-inside: '$MOD = require(''node-serialize'') | |
| ... | |
| ' | |
| - pattern-inside: 'import $MOD from ''node-serialize'' | |
| ... | |
| ' | |
| - pattern: '$MOD.unserialize(...) | |
| ' | |
| message: 'User controlled data in ''unserialize()'' or ''deserialize()'' function | |
| can result in Object Injection or Remote Code Injection. | |
| ' | |
| languages: | |
| - javascript | |
| - typescript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A8:2017-Insecure Deserialization | |
| - A08:2021-Software and Data Integrity Failures | |
| cwe: CWE-502 | |
| shortDescription: Deserialization of Untrusted Data | |
| security-severity: CRITICAL | |
| category: security | |
| - id: rules_lgpl_javascript_eval_rule-eval-require | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-inside: 'function ($REQ, $RES, ...) {...} | |
| ' | |
| - focus-metavariable: $REQ | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: 'require($REQ, ...) | |
| ' | |
| - focus-metavariable: $REQ | |
| pattern-sanitizers: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: "if($VALIDATION){\n...\nrequire($REQ, ...) \n...\n} \n" | |
| - pattern: '$A = $VALIDATION | |
| ... | |
| if($A){ | |
| ... | |
| require($REQ, ...) | |
| ... | |
| } | |
| ' | |
| - metavariable-pattern: | |
| metavariable: $VALIDATION | |
| pattern-either: | |
| - pattern: "$AL.includes(...) \n" | |
| - pattern: '$AL.indexOf(...) !== -1 | |
| ' | |
| - pattern: '$AL.find(...) !== undefined | |
| ' | |
| - pattern: '$ALS.has(...) | |
| ' | |
| message: "Passing untrusted user input directly into the require() function without\ | |
| \ proper \nvalidation or sanitization can possibly cause a vulnerability known\ | |
| \ as remote code execution (RCE). \nAn attacker could manipulate the input to\ | |
| \ load and execute arbitrary code from external sources, \npotentially leading\ | |
| \ to severe security breaches such as data theft, system compromise, \nor unauthorized\ | |
| \ access.\nTo mitigate this risk, it's crucial to validate and sanitize user input\n\ | |
| thoroughly before passing it to functions like require(), ensuring that only trusted\ | |
| \ and safe inputs are utilized.\n\nFollowing is an example of secure validation\ | |
| \ against allowlist to prevent the vulnerability:\n```\n// Define a list of explicitly\ | |
| \ allowed packages for require\nconst allowedPkgs = [\n 'package1',\n 'package2',\n\ | |
| \ 'package3'\n];\n\napp.get(\"/eval/require/7\", async (req, res) => {\n \ | |
| \ var isAllowed = allowedPkgs.includes(req.query.name); \n if (isAllowed)\ | |
| \ {\n // ok: rules_lgpl_javascript_eval_rule-eval-require\n var\ | |
| \ cp = require(req.query.name);\n cp.exec('ls', (error, stdout, stderr)\ | |
| \ => {\n console.log(\"exec output : \\n\", stdout)\n }); \ | |
| \ \n }\n res.send(\"Please check console logs.\");\n});\n```\n" | |
| severity: ERROR | |
| languages: | |
| - javascript | |
| metadata: | |
| cwe: CWE-706 | |
| shortDescription: Use of incorrectly-resolved name or reference | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| - id: rules_lgpl_javascript_eval_rule-vm-compilefunction-injection | |
| patterns: | |
| - pattern-inside: 'require(''vm'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: '$VM.compileFunction($CODE,$PARAMS,{parsingContext: <... $REQ.$QUERY.$FOO | |
| ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = <... $REQ.$QUERY.$FOO ...>; ... $VM.compileFunction($CODE,$PARAMS,{parsingContext: | |
| <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = <... {$NAME:$REQ.$QUERY.$FOO} ...>; ... $VM.compileFunction($CODE,$PARAMS,{parsingContext: | |
| <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>}; ... $VM.compileFunction($CODE,$PARAMS,{parsingContext: | |
| <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$QUERY.$FOO ...>; ... $CONTEXT = {$NAME: <... $VAR | |
| ...>}; ... $VM.compileFunction($CODE,$PARAMS,{parsingContext: <... $CONTEXT | |
| ...>},...) | |
| ' | |
| - pattern: '$OPTS = {parsingContext: <... $REQ.$QUERY.$FOO ...>}; | |
| ... | |
| $VM.compileFunction($CODE,$PARAMS,$OPTS,...) | |
| ' | |
| - pattern: '$CONTEXT = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $OPTS = {parsingContext: <... $CONTEXT ...>}; | |
| ... | |
| $VM.compileFunction($CODE,$PARAMS,$OPTS,...) | |
| ' | |
| - pattern: '$CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>}; | |
| ... | |
| $OPTS = {parsingContext: <... $CONTEXT ...>}; | |
| ... | |
| $VM.compileFunction($CODE,$PARAMS,$OPTS,...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $CONTEXT = {$NAME: <... $VAR ...>}; | |
| ... | |
| $OPTS = {parsingContext: <... $CONTEXT ...>}; | |
| ... | |
| $VM.compileFunction($CODE,$PARAMS,$OPTS,...) | |
| ' | |
| - pattern: '$VM.compileFunction($CODE,$PARAMS,{parsingContext: <... $REQ.$BODY | |
| ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = <... $REQ.$BODY ...>; ... $VM.compileFunction($CODE,$PARAMS,{parsingContext: | |
| <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = <... {$NAME:$REQ.$BODY} ...>; ... $VM.compileFunction($CODE,$PARAMS,{parsingContext: | |
| <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$CONTEXT = {$NAME: <... $REQ.$BODY ...>}; ... $VM.compileFunction($CODE,$PARAMS,{parsingContext: | |
| <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$BODY ...>; ... $CONTEXT = {$NAME: <... $VAR ...>}; | |
| ... $VM.compileFunction($CODE,$PARAMS,{parsingContext: <... $CONTEXT ...>},...) | |
| ' | |
| - pattern: '$OPTS = {parsingContext: <... $REQ.$BODY ...>}; | |
| ... | |
| $VM.compileFunction($CODE,$PARAMS,$OPTS,...) | |
| ' | |
| - pattern: '$CONTEXT = <... $REQ.$BODY ...>; | |
| ... | |
| $OPTS = {parsingContext: <... $CONTEXT ...>}; | |
| ... | |
| $VM.compileFunction($CODE,$PARAMS,$OPTS,...) | |
| ' | |
| - pattern: '$CONTEXT = {$NAME: <... $REQ.$BODY ...>}; | |
| ... | |
| $OPTS = {parsingContext: <... $CONTEXT ...>}; | |
| ... | |
| $VM.compileFunction($CODE,$PARAMS,$OPTS,...) | |
| ' | |
| - pattern: '$VAR = <... $REQ.$BODY ...>; | |
| ... | |
| $CONTEXT = {$NAME: <... $VAR ...>}; | |
| ... | |
| $OPTS = {parsingContext: <... $CONTEXT ...>}; | |
| ... | |
| $VM.compileFunction($CODE,$PARAMS,$OPTS,...) | |
| ' | |
| message: 'Untrusted user input in `vm.compileFunction()` can result in code injection. | |
| ' | |
| severity: ERROR | |
| languages: | |
| - javascript | |
| metadata: | |
| cwe: CWE-94 | |
| shortDescription: Improper control of generation of code (Code Injection) | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| - id: rules_lgpl_javascript_eval_rule-vm2-code-injection | |
| patterns: | |
| - pattern-inside: 'require(''vm2'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: '$VM.run(<... $REQ.$QUERY.$FOO ...>,...) | |
| ' | |
| - pattern: '$CODE = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| $VM.run(<... $CODE ...>,...) | |
| ' | |
| - pattern: 'new VM(...).run(<... $REQ.$QUERY.$FOO ...>,...) | |
| ' | |
| - pattern: 'new NodeVM(...).run(<... $REQ.$QUERY.$FOO ...>,...) | |
| ' | |
| - pattern: '$CODE = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| new NodeVM(...).run(<... $CODE ...>,...) | |
| ' | |
| - pattern: '$CODE = <... $REQ.$QUERY.$FOO ...>; | |
| ... | |
| new VMScript(<... $CODE ...>,...) | |
| ' | |
| - pattern: '$VM.run(<... $REQ.$BODY ...>,...) | |
| ' | |
| - pattern: '$CODE = <... $REQ.$BODY ...>; | |
| ... | |
| $VM.run(<... $CODE ...>,...) | |
| ' | |
| - pattern: 'new VM(...).run(<... $REQ.$BODY ...>,...) | |
| ' | |
| - pattern: '$CODE = <... $REQ.$BODY ...>; | |
| ... | |
| new VM(...).run($CODE,...) | |
| ' | |
| - pattern: 'new NodeVM(...).run(<... $REQ.$BODY ...>,...) | |
| ' | |
| - pattern: '$CODE = <... $REQ.$BODY ...>; | |
| ... | |
| new NodeVM(...).run(<... $CODE ...>,...) | |
| ' | |
| - pattern: '$CODE = <... $REQ.$BODY ...>; | |
| ... | |
| new VMScript(<... $CODE ...>,...) | |
| ' | |
| message: 'Untrusted user input reaching `vm2` can result in code injection. | |
| ' | |
| severity: WARNING | |
| languages: | |
| - javascript | |
| metadata: | |
| cwe: CWE-94 | |
| shortDescription: Improper control of generation of code (Code Injection) | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| - id: rules_lgpl_javascript_eval_rule-server-side-template-injection | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: 'require(''handlebars'') | |
| ... | |
| ' | |
| - pattern-inside: 'require(''pug'') | |
| ... | |
| ' | |
| - pattern-inside: 'require(''hamljs'') | |
| ... | |
| ' | |
| - pattern-inside: 'require(''ejs'') | |
| ... | |
| ' | |
| - pattern-inside: 'require(''squirrelly'') | |
| ... | |
| ' | |
| - pattern-inside: 'require(''eta'') | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: function ($REQ, $RES, ...) {...} | |
| - pattern-inside: function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...} | |
| - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...}; | |
| - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) | |
| - pattern-either: | |
| - pattern: '$HB.compile(..., <... $REQ.$FOO ...>, ...) | |
| ' | |
| - pattern: '$HB.compile(..., <... $REQ.$FOO.$BAR ...>, ...) | |
| ' | |
| - pattern: '$X = <... $REQ.$FOO ...>; | |
| ... | |
| $HB.compile(..., <... $X ...>, ...) | |
| ' | |
| - pattern: '$X = <... $REQ.$FOO.$BAR ...>; | |
| ... | |
| $HB.compile(..., <... $X ...>, ...) | |
| ' | |
| - pattern: '$X = $SOURCE.replace(''...'', <... $REQ.$FOO ...>, ...) | |
| ... | |
| $HB.compile(..., <... $X ...>, ...) | |
| ' | |
| - pattern: '$X = $SOURCE.replace(''...'', <... $REQ.$FOO.$BAR ...>, ...) | |
| ... | |
| $HB.compile(..., <... $X ...>, ...) | |
| ' | |
| - pattern: '$HB.Compile(..., <... $REQ.$FOO ...>, ...) | |
| ' | |
| - pattern: '$HB.Compile(..., <... $REQ.$FOO.$BAR ...>, ...) | |
| ' | |
| - pattern: '$X = <... $REQ.$FOO ...>; | |
| ... | |
| $HB.Compile(..., <... $X ...>, ...) | |
| ' | |
| - pattern: '$X = <... $REQ.$FOO.$BAR ...>; | |
| ... | |
| $HB.Compile(..., <... $X ...>, ...) | |
| ' | |
| - pattern: '$X = $SOURCE.replace(''...'', <... $REQ.$FOO ...>, ...) | |
| ... | |
| $HB.Compile(..., <... $X ...>, ...) | |
| ' | |
| - pattern: '$X = $SOURCE.replace(''...'', <... $REQ.$FOO.$BAR ...>, ...) | |
| ... | |
| $HB.Compile(..., <... $X ...>, ...) | |
| ' | |
| message: 'Untrusted user input in templating engine''s compile() function can result | |
| in Remote Code Execution via server side template injection. | |
| ' | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| cwe: CWE-94 | |
| shortDescription: Improper control of generation of code (Code Injection) | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| - id: rules_lgpl_javascript_eval_rule-grpc-insecure-connection | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: 'require(''grpc'') | |
| ... | |
| ' | |
| - pattern-inside: 'import $MOD from ''grpc'' | |
| ... | |
| ' | |
| - pattern: $CREDENTIALS.createInsecure() | |
| message: 'Found an insecure gRPC connection. This creates a connection without encryption | |
| to a gRPC client/server. A malicious attacker could tamper with the gRPC message, | |
| which could compromise the machine. | |
| ' | |
| metadata: | |
| owasp: | |
| - A8:2017-Insecure Deserialization | |
| - A08:2021-Software and Data Integrity Failures | |
| cwe: CWE-502 | |
| shortDescription: Deserialization of Untrusted Data | |
| security-severity: CRITICAL | |
| category: security | |
| severity: ERROR | |
| languages: | |
| - javascript | |
| - typescript | |
| - id: rules_lgpl_javascript_electronjs_rule-electron-context-isolation | |
| patterns: | |
| - pattern-either: | |
| - pattern: 'new BrowserWindow({webPreferences: {contextIsolation: false}}) | |
| ' | |
| - pattern: 'var $X = {webPreferences: {contextIsolation: false}}; | |
| ' | |
| message: 'Disabling context isolation can introduce Prototype Pollution vulnerabilities. | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-1321 | |
| shortDescription: Improperly controlled modification of object prototype attributes | |
| ('Prototype Pollution') | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_electronjs_rule-electron-allow-http | |
| patterns: | |
| - pattern-either: | |
| - pattern: 'new BrowserWindow({webPreferences: {allowRunningInsecureContent: true}}) | |
| ' | |
| - pattern: 'var $X = {webPreferences: {allowRunningInsecureContent: true}}; | |
| ' | |
| message: 'Application can load content over HTTP and that makes the app vulnerable | |
| to Man in the middle attacks. | |
| ' | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-319 | |
| shortDescription: Cleartext Transmission of Sensitive Information | |
| security-severity: CRITICAL | |
| category: security | |
| - id: rules_lgpl_javascript_electronjs_rule-electron-blink-integration | |
| patterns: | |
| - pattern-either: | |
| - pattern: 'new BrowserWindow({webPreferences: {enableBlinkFeatures: ''...''}}) | |
| ' | |
| - pattern: 'var $X = {webPreferences: {enableBlinkFeatures: ''...''}}; | |
| ' | |
| message: 'Blink''s expirimental features are enabled in this application. Some of | |
| the features may affect the security of the application. | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-272 | |
| shortDescription: Least privilege violation | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_electronjs_rule-electron-experimental-features | |
| patterns: | |
| - pattern-either: | |
| - pattern: 'new BrowserWindow({webPreferences: {experimentalFeatures: true}}) | |
| ' | |
| - pattern: 'var $X = {webPreferences: {experimentalFeatures: true}}; | |
| ' | |
| message: 'Experimental features are not expected to be in production ready applications. | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-272 | |
| shortDescription: Least privilege violation | |
| security-severity: CRITICAL | |
| category: security | |
| - id: rules_lgpl_javascript_electronjs_rule-electron-nodejs-integration | |
| patterns: | |
| - pattern-either: | |
| - pattern: 'new BrowserWindow({webPreferences: {nodeIntegration: true}}) | |
| ' | |
| - pattern: 'var $X = {webPreferences: {nodeIntegration: true}}; | |
| ' | |
| message: 'Node integration exposes node.js APIs to the electron app and this can | |
| introduce remote code execution vulnerabilities to the application if the app | |
| is vulnerable to Cross Site Scripting (XSS). | |
| ' | |
| languages: | |
| - javascript | |
| severity: WARNING | |
| metadata: | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-272 | |
| shortDescription: Least privilege violation | |
| security-severity: MEDIUM | |
| category: security | |
| - id: rules_lgpl_javascript_electronjs_rule-electron-disable-websecurity | |
| patterns: | |
| - pattern-either: | |
| - pattern: 'new BrowserWindow({webPreferences: {webSecurity: false}}) | |
| ' | |
| - pattern: 'var $X = {webPreferences: {webSecurity: false}}; | |
| ' | |
| message: 'Disabling webSecurity will disable the same-origin policy and allows the | |
| execution of insecure code from any domain. | |
| ' | |
| languages: | |
| - javascript | |
| severity: ERROR | |
| metadata: | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-346 | |
| shortDescription: Origin validation error | |
| security-severity: CRITICAL | |
| category: security | |
| - id: yaml_spring_rule-SpringActuatorFullyEnabled | |
| languages: | |
| - yaml | |
| severity: WARNING | |
| message: "Spring Boot Actuator is fully enabled. This exposes sensitive endpoints\n\ | |
| such as /actuator/env, /actuator/logfile, /actuator/heapdump and others.\nIf the\ | |
| \ application lacks proper security measures (e.g., authentication and \nauthorization),\ | |
| \ sensitive data could be accessed, compromising the application and \nits infrastructure.\ | |
| \ This configuration poses a serious risk in production \nenvironments or public-facing\ | |
| \ deployments.\n\nTo mitigate the risks, take the following measures:\n - Expose\ | |
| \ only the Actuator endpoints required for your use case\n - For production environments,\ | |
| \ restrict exposure to non-sensitive endpoints \n like `health` or `info`\n \ | |
| \ - Ensure Actuator endpoints are protected with authentication and authorization\ | |
| \ \n (e.g., via Spring Security)\n - Use environment-specific configurations\ | |
| \ to limit exposure in production\n\nSecure Code Example:\nInstead of include:\ | |
| \ \"*\", list only the endpoints you need to expose:\n```\nmanagement:\n endpoints:\n\ | |
| \ web:\n exposure:\n include: \"health,info,metrics\"\n```\n\n\ | |
| References:\n- https://docs.spring.io/spring-boot/reference/actuator/endpoints.html#actuator.endpoints.exposing\n\ | |
| - https://medium.com/walmartglobaltech/perils-of-spring-boot-actuators-misconfiguration-185c43a0f785\n\ | |
| - https://blog.maass.xyz/spring-actuator-security-part-1-stealing-secrets-using-spring-actuators\n" | |
| metadata: | |
| likelihood: MEDIUM | |
| impact: HIGH | |
| confidence: MEDIUM | |
| shortDescription: Exposure of sensitive system information to an unauthorized | |
| control sphere | |
| category: security | |
| cwe: CWE-497 | |
| owasp: | |
| - A01:2021-Broken Access Control | |
| - A3:2017-Sensitive Data Exposure | |
| security-severity: Medium | |
| technology: | |
| - java | |
| patterns: | |
| - pattern: "management:\n ...\n endpoints:\n ...\n web:\n ...\n \ | |
| \ exposure:\n ...\n include: \"*\"\n ...\n" | |
| - id: rules_lgpl_swift_other_rule-ios-biometric-acl | |
| patterns: | |
| - pattern-either: | |
| - pattern: .biometryAny | |
| - pattern: .userPresence | |
| - pattern: .touchIDAny | |
| - pattern: SecAccessControlCreateWithFlags(...) | |
| message: "Weak biometric ACL flag is associated with a key stored in Keychain. \n\ | |
| With '.biometryAny/.userPresence/.touchIDAny' flag, an attacker with \nthe ability\ | |
| \ to add a biometry to the device can authenticate as the \nuser. It is recommended\ | |
| \ to use more specific and secure authentication \nmechanisms like '.biometryCurrentSet'\ | |
| \ and '.touchIDCurrentSet'.\n\nHere's an example of how to fix the problem by\ | |
| \ using .biometryCurrentSet \nfor biometric authentication in Swift:\n```\nimport\ | |
| \ LocalAuthentication\n\n// Create an instance of LAContext for biometric authentication\n\ | |
| let context = LAContext()\n\n// Check if biometric authentication is available\n\ | |
| if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error:\ | |
| \ nil) {\n // Use biometryCurrentSet for biometric authentication\n context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,\ | |
| \ \n localizedReason: \"Authenticate with biometrics\", \n reply:\ | |
| \ { success, error in\n if success {\n print(\"Biometric\ | |
| \ authentication successful.\")\n // Proceed with authenticated actions\n\ | |
| \ } else {\n print(\"Biometric authentication failed:\ | |
| \ \n \\(error?.localizedDescription ?? \"Unknown error\")\"\ | |
| )\n // Handle authentication failure\n }\n })\n} else\ | |
| \ {\n print(\"Biometric authentication not available.\")\n // Fallback to alternative\ | |
| \ authentication method\n}\n\n```\n" | |
| languages: | |
| - swift | |
| severity: ERROR | |
| metadata: | |
| category: security | |
| cwe: CWE-305 | |
| shortDescription: Authentication bypass by primary weakness | |
| owasp: | |
| - A2:2017-Broken Authentication | |
| - A07:2021-Identification and Authentication Failures | |
| security-severity: CRITICAL | |
| - id: rules_lgpl_swift_other_rule-ios-dtls1-used | |
| patterns: | |
| - pattern: $Y.TLSMinimumSupportedProtocolVersion | |
| - pattern-inside: '... | |
| $X = "tls_protocol_version_t.DTLSv10" | |
| ... | |
| ' | |
| message: "DTLS 1.2 should be used. Detected old version - DTLS 1.0.\nDTLS (Datagram\ | |
| \ Transport Layer Security) 1.0 suffers from \nvarious security vulnerabilities\ | |
| \ and weaknesses, as it is \nan outdated and less secure protocol compared to\ | |
| \ newer \nversions such as DTLS 1.2 or 1.3.\n\nHere's an example of how to use\ | |
| \ DTLS 1.2:\n```\nimport Network\n\n// Create a NWConnection instance with DTLS\ | |
| \ 1.2\nlet connection = NWConnection(host: NWEndpoint.Host(\"example.com\"), port:\ | |
| \ NWEndpoint.Port(\"443\"), using: .dtls)\n\n// Start the connection\nconnection.start(queue:\ | |
| \ .main)\n\n// Handle connection state changes\nconnection.stateUpdateHandler\ | |
| \ = { newState in\n switch newState {\n case .ready:\n print(\"Connection\ | |
| \ ready.\")\n // Perform data transfer or other operations\n case .failed(let\ | |
| \ error):\n print(\"Connection failed with error: \\(error)\")\n default:\n\ | |
| \ break\n }\n}\n```\n" | |
| languages: | |
| - swift | |
| severity: WARNING | |
| metadata: | |
| category: security | |
| cwe: CWE-757 | |
| shortDescription: Selection of less-secure algorithm during negotiation ('algorithm | |
| downgrade') | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| security-severity: MEDIUM | |
| - id: rules_lgpl_swift_other_rule-ios-keychain-weak-accessibility-value | |
| pattern-either: | |
| - pattern: kSecAttrAccessibleAlways | |
| - pattern: kSecAttrAccessibleAfterFirstUnlock | |
| message: "A key stored in the Keychain is using a weak accessibility value. \n\n\ | |
| kSecAttrAccessibleAlways allows access to the keychain item at all \ntimes, even\ | |
| \ when the device is locked. Storing sensitive data with \nthis accessibility\ | |
| \ option means that the data is accessible to anyone \nwho gains physical access\ | |
| \ to the device, regardless of whether it's \nlocked or not. This increases the\ | |
| \ risk of unauthorized access to \nsensitive information. kSecAttrAccessibleAfterFirstUnlock\ | |
| \ allows access\nto the keychain item only after the device has been unlocked\ | |
| \ once after\na reboot. While this provides some level of protection, the data\ | |
| \ becomes\naccessible as soon as the device is unlocked for the first time after\ | |
| \ a\nreboot. If sensitive data is stored with this accessibility option, it \n\ | |
| could still be accessed by an attacker who gains physical access to the\ndevice\ | |
| \ before it's unlocked for the first time after a reboot.\n\nTo mitigate these\ | |
| \ security risks, it's important to use the appropriate \naccessibility option\ | |
| \ based on the sensitivity of the data being stored. \nFor sensitive data that\ | |
| \ should only be accessible when the device is \nunlocked, the kSecAttrAccessibleWhenUnlocked\ | |
| \ or \nkSecAttrAccessibleWhenUnlockedThisDeviceOnly \noptions should be used.\n\ | |
| \nHere's an example code that fixes the problem by using the \nkSecAttrAccessibleWhenUnlocked\ | |
| \ option:\n```\nimport Foundation\nimport Security\n\n// Define the data to be\ | |
| \ stored in the keychain\nlet secretData = \"superSecretData\".data(using: .utf8)!\n\ | |
| \n// Create query dictionary to specify the keychain item\nlet query: [String:\ | |
| \ Any] = [\n kSecClass as String: kSecClassGenericPassword,\n \ | |
| \ kSecAttrService as String: \"com.example.myApp\",\n kSecAttrAccount\ | |
| \ as String: \"userPassword\",\n kSecValueData as String: secretData,\n\ | |
| \ kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked\n]\n\n\ | |
| // Add the keychain item\nlet status = SecItemAdd(query as CFDictionary, nil)\n\ | |
| if status == errSecSuccess {\n print(\"Secret data successfully stored in keychain.\"\ | |
| )\n} else {\n print(\"Error storing secret data in keychain: \\(status)\")\n\ | |
| }\n```\n" | |
| languages: | |
| - swift | |
| severity: WARNING | |
| metadata: | |
| category: security | |
| cwe: CWE-305 | |
| shortDescription: Authentication bypass by primary weakness | |
| owasp: | |
| - A2:2017-Broken Authentication | |
| - A07:2021-Identification and Authentication Failures | |
| security-severity: MEDIUM | |
| - id: rules_lgpl_swift_other_rule-ios-file-no-special | |
| pattern-either: | |
| - pattern: .noFileProtection | |
| - pattern: FileProtectionType.none | |
| message: "The file has no special protections associated with it.\nUsing .noFileProtection\ | |
| \ or FileProtectionType.none for \nfile protection means that the file is not\ | |
| \ encrypted on disk, \nleaving it vulnerable to unauthorized access if the device\ | |
| \ is \ncompromised or if the file is accessed outside of the app's \nsandbox.\ | |
| \ To enhance security, it's crucial to use appropriate \nfile protection attributes\ | |
| \ based on the sensitivity of the data \nbeing stored. For sensitive data, you\ | |
| \ should use file protection \noptions that encrypt the data on disk, such as\ | |
| \ \nFileProtectionType.complete or \nFileProtectionType.completeUnlessOpen.\n\n\ | |
| Here's an example of how to fix the problem:\n```\nimport Foundation \n// Define\ | |
| \ the file URL\nlet fileURL = URL(fileURLWithPath: \"path/to/file\")\n// Define\ | |
| \ data to be written to the file\nlet data = \"Sensitive data\".data(using: .utf8)!\n\ | |
| // Write data to the file with complete file protection\ndo {\n try data.write(to:\ | |
| \ fileURL, options: .completeFileProtection)\n print(\"Data written to file with\ | |
| \ complete file protection.\")\n} catch {\n print(\"Error writing data to file:\ | |
| \ \\(error)\")\n}\n```\n" | |
| languages: | |
| - swift | |
| severity: ERROR | |
| metadata: | |
| category: security | |
| cwe: CWE-312 | |
| shortDescription: Cleartext storage of sensitive information | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: CRITICAL | |
| - id: rules_lgpl_swift_other_rule-ios-tls3-not-used | |
| pattern-either: | |
| - patterns: | |
| - pattern: $X.TLSMinimumSupportedProtocolVersion = $VAL | |
| - metavariable-pattern: | |
| metavariable: $VAL | |
| pattern-either: | |
| - pattern: '.TLSv1_0 | |
| ' | |
| - pattern: '.TLSv1_1 | |
| ' | |
| - pattern: '.TLSv1_2 | |
| ' | |
| message: "The app uses TLS 1.0, TLS 1.1 or TLS 1.2. TLS 1.3 should be used instead.\n\ | |
| TLS versions 1.1 and 1.0 were deprecated by the IETF in June 2018 due to \na number\ | |
| \ of attacks against the vulnerable versions. Use of a deprecated \nTLS version\ | |
| \ may result in the unauthorized retrieval of sensitive \ninformation. It is strongly\ | |
| \ recommended that all TLS connections\nuse TLS 1.3\n\nTLS 1.3 includes several\ | |
| \ security improvements over previous versions, such\nas stronger cryptographic\ | |
| \ algorithms and negotiation mechanisms, reducing \nthe risk of security vulnerabilities\ | |
| \ and attacks like BEAST and POODLE.\n\n\nExample using TLS 1.3:\n```\nimport\ | |
| \ Foundation\n// Create a URLSession configuration with TLS 1.3 support\nlet configuration\ | |
| \ = URLSessionConfiguration.default\nconfiguration.tlsMinimumSupportedProtocol\ | |
| \ = .TLSv13\n// Create a URLSession with the custom configuration\nlet session\ | |
| \ = URLSession(configuration: configuration) \n// Define the URL to connect\ | |
| \ to\nlet url = URL(string: \"https://example.com\")!\n// Create a data task to\ | |
| \ fetch data from the URL\nlet task = session.dataTask(with: url) { data, response,\ | |
| \ error in\n // Handle response\n if let error = error {\n print(\"Error:\ | |
| \ \\(error)\")\n return\n }\n if let httpResponse = response as? HTTPURLResponse\ | |
| \ {\n print(\"Status code: \\(httpResponse.statusCode)\")\n } \n if let\ | |
| \ data = data {\n // Process received data\n print(\"Received data: \\(data)\"\ | |
| )\n }\n}\n// Start the data task\ntask.resume()\n```\n" | |
| languages: | |
| - swift | |
| severity: ERROR | |
| metadata: | |
| category: security | |
| cwe: CWE-757 | |
| shortDescription: Selection of less-secure algorithm during negotiation ('algorithm | |
| downgrade') | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| security-severity: CRITICAL | |
| - id: properties_spring_rule-SpringActuatorFullyEnabled | |
| languages: | |
| - generic | |
| severity: WARNING | |
| message: "Spring Boot Actuator is fully enabled. This exposes sensitive endpoints\n\ | |
| such as /actuator/env, /actuator/logfile, /actuator/heapdump and others.\nIf the\ | |
| \ application lacks proper security measures (e.g., authentication and \nauthorization),\ | |
| \ sensitive data could be accessed, compromising the application and \nits infrastructure.\ | |
| \ This configuration poses a serious risk in production \nenvironments or public-facing\ | |
| \ deployments.\n\nTo mitigate the risks, take the following measures:\n - Expose\ | |
| \ only the Actuator endpoints required for your use case\n - For production environments,\ | |
| \ restrict exposure to non-sensitive endpoints \n like `health` or `info`\n \ | |
| \ - Ensure Actuator endpoints are protected with authentication and authorization\ | |
| \ \n (e.g., via Spring Security)\n - Use environment-specific configurations\ | |
| \ to limit exposure in production\n\nSecure Code Example:\nInstead of include:\ | |
| \ \"*\", list only the endpoints you need to expose:\n```\nmanagement.endpoints.web.exposure.include=\"\ | |
| health,info,metrics\"\n```\n\nReferences:\n- https://docs.spring.io/spring-boot/reference/actuator/endpoints.html#actuator.endpoints.exposing\n\ | |
| - https://medium.com/walmartglobaltech/perils-of-spring-boot-actuators-misconfiguration-185c43a0f785\n\ | |
| - https://blog.maass.xyz/spring-actuator-security-part-1-stealing-secrets-using-spring-actuators\n" | |
| metadata: | |
| likelihood: MEDIUM | |
| impact: HIGH | |
| confidence: MEDIUM | |
| shortDescription: Exposure of sensitive system information to an unauthorized | |
| control sphere | |
| category: security | |
| cwe: CWE-497 | |
| owasp: | |
| - A01:2021-Broken Access Control | |
| - A3:2017-Sensitive Data Exposure | |
| security-severity: Medium | |
| technology: | |
| - java | |
| paths: | |
| include: | |
| - '*properties' | |
| pattern: management.endpoints.web.exposure.include=* | |
| - id: php_phpinfo_rule-phpinfo-use | |
| pattern: phpinfo(...); | |
| message: The 'phpinfo' function may reveal sensitive information about your environment. | |
| metadata: | |
| cwe: CWE-497 | |
| shortDescription: Exposure of sensitive system information to an unauthorized | |
| control sphere | |
| references: | |
| - https://www.php.net/manual/en/function.phpinfo | |
| - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/PhpinfosSniff.php | |
| category: security | |
| technology: | |
| - php | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| cwe2021-top25: true | |
| subcategory: | |
| - vuln | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Mishandled Sensitive Information | |
| security-severity: MEDIUM | |
| languages: | |
| - php | |
| severity: WARNING | |
| - id: php_ftp_rule-ftp-use | |
| patterns: | |
| - pattern: $FUNC(...); | |
| - metavariable-regex: | |
| metavariable: $FUNC | |
| regex: ftp_.+ | |
| message: FTP allows for unencrypted file transfers. Consider using an encrypted | |
| alternative. | |
| metadata: | |
| cwe: CWE-319 | |
| shortDescription: Cleartext transmission of sensitive information | |
| references: | |
| - https://www.php.net/manual/en/intro.ftp.php | |
| - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/FringeFunctionsSniff.php | |
| category: security | |
| technology: | |
| - php | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| subcategory: | |
| - audit | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Mishandled Sensitive Information | |
| security-severity: MEDIUM | |
| languages: | |
| - php | |
| severity: WARNING | |
| - id: php_crypto_rule-weak-crypto | |
| patterns: | |
| - pattern: $FUNC(...); | |
| - metavariable-regex: | |
| metavariable: $FUNC | |
| regex: crypt|md5|md5_file|sha1|sha1_file|str_rot13 | |
| message: Detected usage of weak crypto function. Consider using stronger alternatives. | |
| metadata: | |
| cwe: CWE-328 | |
| shortDescription: Use of weak hash | |
| references: | |
| - https://www.php.net/manual/en/book.sodium.php | |
| - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/CryptoFunctionsSniff.php | |
| category: security | |
| technology: | |
| - php | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| subcategory: | |
| - audit | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Insecure Hashing Algorithm | |
| security-severity: MEDIUM | |
| languages: | |
| - php | |
| severity: WARNING | |
| - id: php_file_rule-file-inclusion | |
| message: Detected non-constant file inclusion. This can lead to local file inclusion | |
| (LFI) or remote file inclusion (RFI) if user input reaches this statement. LFI | |
| and RFI could lead to sensitive files being obtained by attackers. Instead, explicitly | |
| specify what to include. If that is not a viable solution, validate user input | |
| thoroughly. | |
| metadata: | |
| cwe: CWE-98 | |
| shortDescription: Improper control of filename for include/require statement in | |
| PHP program ('PHP Remote File Inclusion') | |
| references: | |
| - https://www.php.net/manual/en/function.include.php | |
| - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/EasyRFISniff.php | |
| - https://en.wikipedia.org/wiki/File_inclusion_vulnerability#Types_of_Inclusion | |
| category: security | |
| technology: | |
| - php | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| subcategory: | |
| - audit | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Code Injection | |
| security-severity: CRITICAL | |
| languages: | |
| - php | |
| severity: ERROR | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: $_GET | |
| - pattern: $_POST | |
| - pattern: $_COOKIE | |
| - pattern: $_REQUEST | |
| - pattern: $_SERVER | |
| pattern-sanitizers: | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: basename($PATH, ...) | |
| - pattern-inside: linkinfo($PATH, ...) | |
| - pattern-inside: readlink($PATH, ...) | |
| - pattern-inside: realpath($PATH, ...) | |
| - pattern-inside: include_safe(...) | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-inside: $FUNC(...); | |
| - pattern: $VAR | |
| - metavariable-regex: | |
| metavariable: $FUNC | |
| regex: \b(include|include_once|require|require_once)\b | |
| - id: php_backticks_rule-backticks-use | |
| pattern: '`...`;' | |
| message: Backticks use may lead to command injection vulnerabilities. | |
| metadata: | |
| cwe: CWE-94 | |
| shortDescription: Improper control of generation of code ('Code Injection') | |
| references: | |
| - https://www.php.net/manual/en/language.operators.execution.php | |
| - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/BackticksSniff.php | |
| category: security | |
| technology: | |
| - php | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe2022-top25: true | |
| subcategory: | |
| - audit | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Code Injection | |
| security-severity: CRITICAL | |
| languages: | |
| - php | |
| severity: ERROR | |
| - id: php_assert_rule-assert-use | |
| mode: taint | |
| pattern-sources: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: $_GET | |
| - pattern: $_POST | |
| - pattern: $_COOKIE | |
| - pattern: $_REQUEST | |
| - pattern: $_SERVER | |
| - patterns: | |
| - pattern: 'Route::$METHOD($ROUTENAME, function(..., $ARG, ...) { ... }) | |
| ' | |
| - focus-metavariable: $ARG | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: assert($SINK, ...); | |
| - pattern-not: assert("...", ...); | |
| - pattern: $SINK | |
| message: Calling assert with user input is equivalent to eval'ing. | |
| metadata: | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-95 | |
| shortDescription: Improper neutralization of directives in dynamically evaluated | |
| code ('Eval Injection') | |
| references: | |
| - https://www.php.net/manual/en/function.assert | |
| - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/AssertsSniff.php | |
| category: security | |
| technology: | |
| - php | |
| subcategory: | |
| - vuln | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Code Injection | |
| security-severity: CRITICAL | |
| languages: | |
| - php | |
| severity: ERROR | |
| - id: php_mcrypt_rule-mcrypt-use | |
| patterns: | |
| - pattern: $FUNC(...); | |
| - metavariable-regex: | |
| metavariable: $FUNC | |
| regex: (mcrypt_|mdecrypt_).+ | |
| message: Mcrypt functionality has been deprecated and/or removed in recent PHP versions. | |
| Consider using Sodium or OpenSSL. | |
| metadata: | |
| cwe: CWE-676 | |
| shortDescription: Use of potentially dangerous function | |
| references: | |
| - https://www.php.net/manual/en/intro.mcrypt.php | |
| - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/CryptoFunctionsSniff.php | |
| category: security | |
| owasp: | |
| - A9:2017-Using Components with Known Vulnerabilities | |
| - A06:2021-Vulnerable and Outdated Components | |
| technology: | |
| - php | |
| subcategory: | |
| - audit | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Dangerous Method or Function | |
| security-severity: MEDIUM | |
| languages: | |
| - php | |
| severity: WARNING | |
| - id: php_exec_rule-exec-use | |
| patterns: | |
| - pattern: $FUNC(...); | |
| - pattern-not: $FUNC('...', ...); | |
| - metavariable-regex: | |
| metavariable: $FUNC | |
| regex: exec|passthru|proc_open|popen|shell_exec|system|pcntl_exec | |
| message: Executing non-constant commands. This can lead to command injection. | |
| metadata: | |
| cwe: CWE-94 | |
| shortDescription: Improper control of generation of code ('Code Injection') | |
| references: | |
| - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/SystemExecFunctionsSniff.php | |
| category: security | |
| technology: | |
| - php | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe2022-top25: true | |
| subcategory: | |
| - audit | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Code Injection | |
| security-severity: CRITICAL | |
| languages: | |
| - php | |
| severity: ERROR | |
| - id: php_eval_rule-eval-use | |
| patterns: | |
| - pattern: eval(...); | |
| - pattern-not: eval('...'); | |
| message: Evaluating non-constant commands. This can lead to command injection. | |
| metadata: | |
| cwe: CWE-78 | |
| shortDescription: Improper neutralization of special elements used in an OS command | |
| ('OS Command Injection') | |
| references: | |
| - https://www.php.net/manual/en/function.eval | |
| - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/NoEvalsSniff.php | |
| category: security | |
| technology: | |
| - php | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe2022-top25: true | |
| cwe2021-top25: true | |
| subcategory: | |
| - audit | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Command Injection | |
| security-severity: CRITICAL | |
| languages: | |
| - php | |
| severity: ERROR | |
| - id: kotlin_ssrf_rule-SSRF | |
| languages: | |
| - kotlin | |
| message: 'Server-Side Request Forgery occur when a web server executes a request | |
| to a user supplied | |
| destination parameter that is not validated. Such vulnerabilities could allow | |
| an attacker to | |
| access internal services or to launch attacks from your web server. | |
| ' | |
| metadata: | |
| shortDescription: Server-Side Request Forgery (SSRF) | |
| category: security | |
| cwe: CWE-918 | |
| owasp: | |
| - A1:2017-Injection | |
| - A10:2021-Server-Side Request Forgery | |
| security-severity: CRITICAL | |
| severity: ERROR | |
| pattern-either: | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: 'import java.net.*; | |
| ... | |
| ' | |
| - pattern-inside: 'import java.net.URL; | |
| ... | |
| ' | |
| - pattern-inside: 'import java.net.URI; | |
| ... | |
| ' | |
| - pattern: $TYPE(...). ... .$FUNC | |
| - pattern-not: $TYPE("..."). ... .$FUNC | |
| - metavariable-pattern: | |
| metavariable: $FUNC | |
| pattern-either: | |
| - pattern: connect | |
| - pattern: GetContent | |
| - pattern: openConnection | |
| - pattern: openStream | |
| - pattern: getContent | |
| - pattern: content | |
| - metavariable-pattern: | |
| metavariable: $TYPE | |
| pattern-either: | |
| - pattern: URL | |
| - pattern: java.net.URL | |
| - pattern: URI | |
| - pattern: java.net.URI | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: 'import java.net.*; | |
| ... | |
| ' | |
| - pattern-inside: 'import java.net.InetSocketAddress; | |
| ... | |
| ' | |
| - pattern: 'InetSocketAddress(..., $PORT) | |
| ' | |
| - pattern-not: 'InetSocketAddress("...", $PORT) | |
| ' | |
| - id: kotlin_crypto_rule-CipherECBMode | |
| languages: | |
| - kotlin | |
| message: 'An authentication cipher mode which provides better confidentiality of | |
| the encrypted data | |
| should be used instead of Electronic Code Book (ECB) mode, which does not provide | |
| good | |
| confidentiality. Specifically, ECB mode produces the same output for the same | |
| input each time. | |
| This allows an attacker to intercept and replay the data. | |
| ' | |
| metadata: | |
| category: security | |
| cwe: CWE-326 | |
| shortDescription: Inadequate Encryption Strength | |
| technology: | |
| - kotlin | |
| security-severity: CRITICAL | |
| severity: ERROR | |
| patterns: | |
| - pattern: javax.crypto.Cipher.getInstance($TRANSFORMATION, ...) | |
| - metavariable-regex: | |
| metavariable: $TRANSFORMATION | |
| regex: ^"[^/]*/ECB(/.*)?"$ | |
| - id: kotlin_crypto_rule-InsufficientKeySizeRsa | |
| languages: | |
| - kotlin | |
| message: 'Detected an insufficient key size for DSA. NIST recommends a key size | |
| of 2048 or higher. | |
| ' | |
| metadata: | |
| shortDescription: Inadequate encryption strength | |
| category: security | |
| cwe: CWE-326 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: '$GEN = KeyPairGenerator.getInstance($ALG, ...); | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: $VAR.initialize($SIZE, ...); | |
| - pattern: java.security.spec.RSAKeyGenParameterSpec($SIZE,...); | |
| - metavariable-comparison: | |
| comparison: $SIZE < 2048 | |
| metavariable: $SIZE | |
| - metavariable-regex: | |
| metavariable: $ALG | |
| regex: '"(RSA|DSA)"' | |
| - id: kotlin_crypto_rule-CipherIntegrity | |
| languages: | |
| - kotlin | |
| message: 'The ciphertext produced is susceptible to alteration by an adversary. | |
| This mean that the | |
| cipher provides no way to detect that the data has been tampered with. If the | |
| ciphertext can be | |
| controlled by an attacker, it could be altered without detection. | |
| ' | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Use of a broken or risky cryptographic algorithm | |
| category: security | |
| cwe: CWE-327 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| technology: | |
| - kotlin | |
| security-severity: CRITICAL | |
| patterns: | |
| - pattern: 'javax.crypto.Cipher.getInstance($TRANSFORMATION, ...) | |
| ' | |
| - metavariable-pattern: | |
| metavariable: $TRANSFORMATION | |
| patterns: | |
| - pattern-regex: ^"[^/]*(/(CBC|OFB|CTR|ECB)(/.*)?)?"$ | |
| - pattern-not-regex: ^"(ECIES|RSA)(/|"$) | |
| - id: kotlin_crypto_rule-WeakTLSProtocolVersion | |
| languages: | |
| - kotlin | |
| message: 'The application was found enabling insecure TLS protocol versions. When | |
| enabling protocol | |
| versions for an `SSLContext`, only the following versions should be allowed: | |
| - TLSv1.2 | |
| - TLSv1.3 | |
| - DTLSv1.2 | |
| - DTLSv1.3 | |
| To mitigate potential security risks, it is strongly advised to enforce TLS 1.2 | |
| as the minimum | |
| protocol version and disallow older versions such as TLS 1.0. Do note that newer | |
| versions of | |
| Java do not even support TLS 1.0 and will throw `NoSuchAlgorithmException`. Versions | |
| of TLS | |
| prior to 1.2 could expose the connection to downgrade attacks, where an adversary | |
| intercepts | |
| the | |
| connection and alters the requested protocol version to be a less secure one. | |
| In many scenarios, relying on the default system configuration does not meet compliance | |
| standards. This is due to the application being deployed across diverse systems | |
| with varying | |
| configurations and Java versions. While the default value may be secure on modern | |
| and | |
| up-to-date systems, it may not hold true for older systems. Consequently, it is | |
| highly | |
| recommended to explicitly define a secure configuration in all cases. | |
| Example configuring an SSLContext with TLSv1.2: | |
| ``` | |
| // Create an SSLContext with TLSv1.2 explicitly | |
| SSLContext tlsContext = SSLContext.getInstance("TLSv1.2"); // or TLSv1.3, DTLSv1.2, | |
| DTLSv1.3 | |
| // Alternatively, set the enabled protocols | |
| SSLContext serverSslContext = SSLContext.getInstance("TLS"); | |
| SSLEngine serverEngine = serverSslContext.createSSLEngine(); | |
| // Calling setEnabledProtocols will override the original context''s configured | |
| protocol version | |
| serverEngine.setEnabledProtocols(new String[]{ "TLSv1.2" }); | |
| ``` | |
| For more information on `SSLContext` see: | |
| - https://docs.oracle.com/en/java/javase/11/docs/api/java.base/javax/net/ssl/SSLContext.html | |
| For more information on MiTM attacks see: | |
| - https://owasp.org/www-community/attacks/Manipulator-in-the-middle_attack | |
| ' | |
| metadata: | |
| shortDescription: Inadequate encryption strength | |
| category: security | |
| cwe: CWE-326 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: 'import javax.net.ssl.*; | |
| ... | |
| ' | |
| - pattern-inside: 'import javax.net.ssl.SSLContext; | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern-inside: 'SSLContext.getInstance("$UNSAFE_VERSION"); | |
| ' | |
| - pattern-inside: 'SSLContext.getInstance(...); | |
| ... | |
| $ENGINE.setEnabledProtocols(arrayOf(...,"$UNSAFE_VERSION",...)); | |
| ' | |
| - pattern-not: | |
| patterns: | |
| - pattern-inside: '$C = SSLContext.getInstance(...); | |
| ... | |
| $ENGINE.setEnabledProtocols(arrayOf(...,"$DT_GOODNESS",...)); | |
| ' | |
| - metavariable-regex: | |
| metavariable: $DT_GOODNESS | |
| regex: ^D?TLSv1\.[23]$ | |
| - pattern-not: | |
| patterns: | |
| - pattern-inside: '$C = SSLContext.getInstance(...); | |
| ... | |
| $E = $C.createSSLEngine() | |
| ... | |
| $E.enabledProtocols = arrayOf(...,"$DT_GOODNESS",...) | |
| ' | |
| - metavariable-regex: | |
| metavariable: $DT_GOODNESS | |
| regex: ^DTLSv1\.[23]$ | |
| - metavariable-regex: | |
| metavariable: $UNSAFE_VERSION | |
| regex: ^(TLS|(D)?TLSv1.(0|1))$ | |
| - id: kotlin_crypto_rule-NullCipher | |
| languages: | |
| - kotlin | |
| message: 'The NullCipher implements the Cipher interface by returning ciphertext | |
| identical to the | |
| supplied plaintext. In a few contexts, such as testing, a NullCipher may be appropriate. | |
| Avoid | |
| using the NullCipher. Its accidental use can introduce a significant confidentiality | |
| risk. | |
| ' | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Use of a broken or risky cryptographic algorithm | |
| category: security | |
| cwe: CWE-327 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| pattern: javax.crypto.NullCipher() | |
| - id: kotlin_crypto_rule-CipherDESedeInsecure | |
| languages: | |
| - kotlin | |
| message: 'Triple DES (also known as 3DES or DESede) is considered strong ciphers | |
| for modern | |
| applications. NIST recommends the usage of AES block ciphers instead of 3DES. | |
| ' | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Use of a broken or risky cryptographic algorithm | |
| category: security | |
| cwe: CWE-327 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| patterns: | |
| - pattern-inside: javax.crypto.Cipher.getInstance($ALG, ...) | |
| - metavariable-regex: | |
| metavariable: $ALG | |
| regex: (?i)^"DESede(/|"$) | |
| - id: kotlin_crypto_rule-CipherDESInsecure | |
| languages: | |
| - kotlin | |
| message: 'DES is considered strong ciphers for modern applications. Currently, NIST | |
| recommends the usage | |
| of AES block ciphers instead of DES. | |
| ' | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Inadequate encryption strength | |
| category: security | |
| cwe: CWE-326 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| patterns: | |
| - pattern-inside: javax.crypto.Cipher.getInstance($TRANSFORMATION, ...) | |
| - metavariable-regex: | |
| metavariable: $TRANSFORMATION | |
| regex: ^"DES(/|"$) | |
| - id: kotlin_crypto_rule-RsaNoPadding | |
| languages: | |
| - kotlin | |
| message: 'The software uses the RSA algorithm but does not incorporate Optimal Asymmetric | |
| Encryption Padding (OAEP), which might weaken the encryption. | |
| ' | |
| metadata: | |
| shortDescription: Use of RSA algorithm without OAEP | |
| category: security | |
| cwe: CWE-780 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| pattern-either: | |
| - patterns: | |
| - pattern: '$VAR = "$ALG"; | |
| ... | |
| javax.crypto.Cipher.getInstance($VAR); | |
| ' | |
| - metavariable-regex: | |
| metavariable: $ALG | |
| regex: .*RSA.*NoPadding.* | |
| - patterns: | |
| - pattern: javax.crypto.Cipher.getInstance($ALG,...); | |
| - metavariable-regex: | |
| metavariable: $ALG | |
| regex: .*RSA.*NoPadding.* | |
| - id: kotlin_crypto_rule-BlowfishKeySize | |
| languages: | |
| - kotlin | |
| message: 'A small key size makes the ciphertext vulnerable to brute force attacks. | |
| At least 128 bits of | |
| entropy should be used when generating the key if use of Blowfish is required. | |
| ' | |
| severity: WARNING | |
| metadata: | |
| category: security | |
| shortDescription: Inadequate encryption strength | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| cwe: CWE-326 | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| patterns: | |
| - pattern-inside: '$KEYGEN = javax.crypto.KeyGenerator.getInstance("Blowfish", ...); | |
| ... | |
| $KEYGEN.init($KEY_SIZE); | |
| ' | |
| - metavariable-comparison: | |
| comparison: $KEY_SIZE < 128 | |
| metavariable: $KEY_SIZE | |
| - id: kotlin_crypto_rule-CustomMessageDigest | |
| languages: | |
| - kotlin | |
| message: 'Implementing a custom MessageDigest is error-prone. National Institute | |
| of Standards and | |
| Technology(NIST) recommends the use of SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, | |
| or | |
| SHA-512/256. | |
| ' | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Use of a broken or risky cryptographic algorithm | |
| category: security | |
| cwe: CWE-327 | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A04:2021-Insecure Design | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| pattern: "class $CLAZZ : java.security.MessageDigest(...) {\n ...\n}\n" | |
| - id: kotlin_crypto_rule-CipherPaddingOracle | |
| languages: | |
| - kotlin | |
| message: 'This specific mode of CBC with PKCS5Padding is susceptible to padding | |
| oracle attacks. An | |
| adversary could potentially decrypt the message if the system exposed the difference | |
| between | |
| plaintext with invalid padding or valid padding. The distinction between valid | |
| and invalid | |
| padding is usually revealed through distinct error messages being returned for | |
| each condition. | |
| ' | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Use of a broken or risky cryptographic algorithm | |
| category: security | |
| cwe: CWE-327 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| technology: | |
| - java | |
| security-severity: CRITICAL | |
| patterns: | |
| - pattern: javax.crypto.Cipher.getInstance($TRANSFORMATION) | |
| - metavariable-regex: | |
| metavariable: $TRANSFORMATION | |
| regex: ^"[^/]*/CBC/PKCS5Padding | |
| - metavariable-pattern: | |
| metavariable: $TRANSFORMATION | |
| patterns: | |
| - pattern-not-regex: ^"(RSA|ECIES)/ | |
| - id: kotlin_crypto_rule-WeakMessageDigest | |
| languages: | |
| - kotlin | |
| message: 'DES is considered strong ciphers for modern applications. Currently, NIST | |
| recommends the usage | |
| of AES block ciphers instead of DES. | |
| ' | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Use of a broken or risky cryptographic algorithm (SHA1/MD5) | |
| category: security | |
| cwe: CWE-327 | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A04:2021-Insecure Design | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| patterns: | |
| - pattern-either: | |
| - pattern: MessageDigest.getInstance($ALG, ...) | |
| - pattern: Signature.getInstance($ALG, ...) | |
| - metavariable-regex: | |
| metavariable: $ALG | |
| regex: .*(MD5|MD4|MD2|SHA1|SHA-1).* | |
| - id: kotlin_crypto_rule-HazelcastSymmetricEncryption | |
| languages: | |
| - kotlin | |
| message: 'The network communications for Hazelcast is configured to use a symmetric | |
| cipher (probably DES | |
| or Blowfish). Those ciphers alone do not provide integrity or secure authentication. | |
| The use of | |
| asymmetric encryption is preferred. | |
| ' | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Inadequate encryption strength | |
| category: security | |
| cwe: CWE-326 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| pattern: com.hazelcast.config.SymmetricEncryptionConfig() | |
| - id: kotlin_crypto_rule-WeakTLSProtocol | |
| languages: | |
| - kotlin | |
| message: 'A HostnameVerifier that accept any host are often use because of certificate | |
| reuse on many hosts. As a consequence, this is vulnerable to Man-in-the-middleattacks | |
| attacks since the client will trust any certificate. | |
| ' | |
| metadata: | |
| shortDescription: Improper certificate validation | |
| category: security | |
| cwe: CWE-295 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| patterns: | |
| - pattern-either: | |
| - pattern: org.apache.http.impl.client.DefaultHttpClient() | |
| - pattern: javax.net.ssl.SSLContext.getInstance("SSL") | |
| - id: kotlin_strings_rule-ModifyAfterValidation | |
| languages: | |
| - kotlin | |
| message: 'CERT: IDS11-J. Perform any string modifications before validation | |
| ' | |
| metadata: | |
| shortDescription: Collapse of data into unsafe value | |
| category: security | |
| cwe: CWE-182 | |
| confidence: HIGH | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| patterns: | |
| - pattern-inside: '$PATTERN = Pattern.compile(...) | |
| ... | |
| ' | |
| - pattern-inside: '$PATTERN.matcher($VAR) | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: '$VAR + $OTHER | |
| ' | |
| - patterns: | |
| - pattern: '$VAR.$METHOD(...) | |
| ' | |
| - metavariable-regex: | |
| metavariable: $METHOD | |
| regex: (replace|replaceAll|replaceFirst|concat) | |
| - id: kotlin_strings_rule-NormalizeAfterValidation | |
| languages: | |
| - kotlin | |
| message: 'IDS01-J. Normalize strings before validating them | |
| ' | |
| metadata: | |
| shortDescription: 'Incorrect behavior order: validate before canonicalize' | |
| category: security | |
| cwe: CWE-180 | |
| confidence: HIGH | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| patterns: | |
| - pattern: '$Y = java.util.regex.Pattern.compile("[<>]"); | |
| ... | |
| $Y.matcher($VAR); | |
| ... | |
| java.text.Normalizer.normalize($VAR, ...);' | |
| - id: kotlin_strings_rule-BadHexConversion | |
| languages: | |
| - kotlin | |
| message: 'When converting a byte array containing a hash signature to a human readable | |
| string, a | |
| conversion mistake can be made if the array is read byte by byte. | |
| ' | |
| metadata: | |
| shortDescription: Incorrect type conversion or cast | |
| cwe: CWE-704 | |
| category: security | |
| confidence: HIGH | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| patterns: | |
| - pattern-inside: '$B_ARR = ($MD: java.security.MessageDigest).digest(...); | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: "for($B in $B_ARR) {\n ...\n $B_TOSTR\n}\n" | |
| - pattern: "while(...) {\n ...\n $B_TOSTR\n}\n" | |
| - pattern: "do {\n ...\n $B_TOSTR\n} while(...)\n" | |
| - metavariable-pattern: | |
| metavariable: $B_TOSTR | |
| patterns: | |
| - pattern-either: | |
| - pattern: java.lang.Integer.toHexString($B_TOINT) | |
| - pattern: Integer.toHexString($B_TOINT) | |
| - pattern: $B_TOINT.toHexString(...) | |
| - metavariable-pattern: | |
| metavariable: $B_TOINT | |
| pattern-either: | |
| - pattern: $B_ARR[...].toInt() | |
| - pattern: $B_ARR[...] | |
| - pattern: $B.toInt() | |
| - pattern: $B | |
| - id: kotlin_strings_rule-FormatStringManipulation | |
| languages: | |
| - kotlin | |
| message: 'Allowing user input to control format parameters could enable an attacker | |
| to cause exceptions | |
| to be thrown or leak information.Attackers may be able to modify the format string | |
| argument, | |
| such that an exception is thrown. If this exception is left uncaught, it may crash | |
| the | |
| application. Alternatively, if sensitive information is used within the unused | |
| arguments, | |
| attackers may change the format string to reveal this information. | |
| ' | |
| metadata: | |
| shortDescription: Use of externally-controlled format string | |
| cwe: CWE-134 | |
| category: security | |
| confidence: HIGH | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| severity: ERROR | |
| patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: '$INPUT = ($REQ: HttpServletRequest).getParameter(...) | |
| ... | |
| ' | |
| - pattern-inside: '$FORMAT_STR = ... + $INPUT | |
| ... | |
| ' | |
| - patterns: | |
| - pattern-inside: '$INPUT = ($REQ: HttpServletRequest).getParameter(...) | |
| ... | |
| ' | |
| - pattern-inside: '$FORMAT_STR = ... + $INPUT + ... | |
| ... | |
| ' | |
| - pattern-inside: '$FORMAT_STR = ... + ($REQ: HttpServletRequest).getParameter(...) | |
| + ... | |
| ... | |
| ' | |
| - pattern-inside: '$FORMAT_STR = ... + ($REQ: HttpServletRequest).getParameter(...) | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: String.format($FORMAT_STR, ...) | |
| - pattern: String.format(java.util.Locale.$LOCALE, $FORMAT_STR, ...) | |
| - patterns: | |
| - pattern-inside: '$F = java.util.Formatter(...) | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: $F.format($FORMAT_STR, ...) | |
| - pattern: $F.format(java.util.Locale.$LOCALE, $FORMAT_STR, ...) | |
| - pattern: '($F: java.io.PrintStream).printf($FORMAT_STR, ...)' | |
| - pattern: '($F: java.io.PrintStream).printf(java.util.Locale.$LOCALE, $FORMAT_STR, | |
| ...)' | |
| - pattern: '($F: java.io.PrintStream).format($FORMAT_STR, ...)' | |
| - pattern: '($F: java.io.PrintStream).format(java.util.Locale.$LOCALE, $FORMAT_STR, | |
| ...)' | |
| - pattern: System.out.printf($FORMAT_STR, ...) | |
| - pattern: System.out.printf(java.util.Locale.$LOCALE, $FORMAT_STR, ...) | |
| - pattern: System.out.format($FORMAT_STR, ...) | |
| - pattern: System.out.format(java.util.Locale.$LOCALE, $FORMAT_STR, ...) | |
| - id: kotlin_password_rule-ConstantDBPassword | |
| pattern: java.sql.DriverManager.getConnection($URI, $USR, "...") | |
| message: 'A potential hard-coded password was identified in a database connection | |
| string. | |
| Passwords should not be stored directly in code | |
| but loaded from secure locations such as a Key Management System (KMS). | |
| The purpose of using a Key Management System is so access can be audited and keys | |
| easily | |
| rotated | |
| in the event of a breach. By hardcoding passwords, it will be extremely difficult | |
| to determine | |
| when or if, a key is compromised. | |
| The recommendation on which KMS to use depends on the environment the application | |
| is running | |
| in: | |
| - For Google Cloud Platform consider [Cloud Key Management](https://cloud.google.com/kms/docs) | |
| - For Amazon Web Services consider [AWS Key Management](https://aws.amazon.com/kms/) | |
| - For on premise or other alternatives to cloud providers, consider [Hashicorp''s | |
| Vault](https://www.vaultproject.io/) | |
| - For other cloud providers, please see their documentation | |
| ' | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Use of hard-coded password | |
| category: security | |
| cwe: CWE-259 | |
| owasp: | |
| - A2:2017-Broken Authentication | |
| - A07:2021-Identification and Authentication Failures | |
| technology: | |
| - kotlin | |
| security-severity: Critical | |
| languages: | |
| - kotlin | |
| - id: kotlin_password_rule-EmptyDBPassword | |
| pattern: java.sql.DriverManager.getConnection($URI, $USR, ""); | |
| message: 'The application does not provide authentication when communicating a database | |
| server. It is strongly recommended that the database server be configured with | |
| authentication and restrict what queries users can execute. | |
| Please see your database server''s documentation on how to configure a password. | |
| Additionally, passwords should not be stored directly in code | |
| but loaded from secure locations such as a Key Management System (KMS). | |
| The purpose of using a Key Management System is so access can be audited and keys | |
| easily | |
| rotated | |
| in the event of a breach. By hardcoding passwords, it will be extremely difficult | |
| to determine | |
| when or if, a key is compromised. | |
| The recommendation on which KMS to use depends on the environment the application | |
| is running | |
| in: | |
| - For Google Cloud Platform consider [Cloud Key Management](https://cloud.google.com/kms/docs) | |
| - For Amazon Web Services consider [AWS Key Management](https://aws.amazon.com/kms/) | |
| - For on premise or other alternatives to cloud providers, consider [Hashicorp''s | |
| Vault](https://www.vaultproject.io/) | |
| - For other cloud providers, please see their documentation | |
| ' | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Missing authentication for critical function (database) | |
| category: security | |
| cwe: CWE-306 | |
| owasp: | |
| - A2:2017-Broken Authentication | |
| - A07:2021-Identification and Authentication Failures | |
| technology: | |
| - kotlin | |
| security-severity: Critical | |
| languages: | |
| - kotlin | |
| - id: kotlin_password_rule-HardcodePassword | |
| languages: | |
| - kotlin | |
| message: 'A potential hard-coded password was identified in the source code. | |
| Passwords should not be stored directly in code | |
| but loaded from secure locations such as a Key Management System (KMS). | |
| The purpose of using a Key Management System is so access can be audited and keys | |
| easily | |
| rotated | |
| in the event of a breach. By hardcoding passwords, it will be extremely difficult | |
| to determine | |
| when or if, a key is compromised. | |
| The recommendation on which KMS to use depends on the environment the application | |
| is running | |
| in: | |
| - For Google Cloud Platform consider [Cloud Key Management](https://cloud.google.com/kms/docs) | |
| - For Amazon Web Services consider [AWS Key Management](https://aws.amazon.com/kms/) | |
| - For on premise or other alternatives to cloud providers, consider [Hashicorp''s | |
| Vault](https://www.vaultproject.io/) | |
| - For other cloud providers, please see their documentation | |
| ' | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Use of hard-coded password | |
| category: security | |
| cwe: CWE-259 | |
| owasp: | |
| - A2:2017-Broken Authentication | |
| - A07:2021-Identification and Authentication Failures | |
| technology: | |
| - kotlin | |
| security-severity: High | |
| pattern-either: | |
| - pattern: java.security.KeyStore.PasswordProtection("...".toCharArray()) | |
| - pattern: java.security.KeyStore.getInstance(...).load(..., "...".toCharArray()) | |
| - pattern: '($KS: java.security.KeyStore).load(..., "...".toCharArray())' | |
| - pattern: KeyManagerFactory.getInstance(...).init(..., "...".toCharArray()) | |
| - pattern: '($KMF: KeyManagerFactory).init(..., "...".toCharArray())' | |
| - pattern: PBEKeySpec("...", ...) | |
| - pattern: PasswordAuthentication("...", "...") | |
| - pattern: '($CB: PasswordCallback).setPassword("...")' | |
| - pattern: KerberosKey(...,"...",...) | |
| - pattern: java.sql.DriverManager.getConnection(..., "...") | |
| - pattern: io.vertx.ext.web.handler.CSRFHandler.create(..., "...") | |
| - pattern: $S.setPassword("...") | |
| - id: kotlin_templateinjection_rule-TemplateInjection | |
| languages: | |
| - kotlin | |
| message: 'A malicious user in control of a template can run malicious code on the | |
| server-side. Velocity templates should be seen as scripts. | |
| ' | |
| metadata: | |
| shortDescription: Improper control of generation of code ('Code Injection') | |
| category: security | |
| cwe: CWE-94 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| severity: ERROR | |
| pattern-either: | |
| - patterns: | |
| - pattern: org.apache.velocity.app.Velocity.evaluate(..., $VAR) | |
| - pattern-not: org.apache.velocity.app.Velocity.evaluate(..., "...") | |
| - patterns: | |
| - pattern-not-inside: '$C = ($CFG: freemarker.template.Configuration).getTemplate("..."); | |
| ... | |
| ' | |
| - pattern-inside: '$C = ($CFG: freemarker.template.Configuration).getTemplate($IN); | |
| ... | |
| ' | |
| - pattern: $C.process(...) | |
| - patterns: | |
| - pattern-inside: 'import com.mitchellbosecke.pebble.PebbleEngine; | |
| ... | |
| ' | |
| - pattern-inside: '$C = $T.getTemplate($IN); | |
| ... | |
| ' | |
| - pattern-not-inside: '$C = $T.getTemplate("..."); | |
| ... | |
| ' | |
| - pattern: $C.evaluate(...) | |
| - id: kotlin_xxe_rule-SaxParserXXE | |
| languages: | |
| - kotlin | |
| message: 'XML External Entity (XXE) attacks can occur when an XML parser supports | |
| XML | |
| entities while processing XML received from an untrusted source. | |
| ' | |
| metadata: | |
| shortDescription: Improper restriction of XML external entity reference ('XXE') | |
| category: security | |
| cwe: CWE-611 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| severity: ERROR | |
| patterns: | |
| - pattern-inside: '$SF = SAXParserFactory.newInstance() | |
| ... | |
| ' | |
| - pattern-not-inside: '$SF.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); | |
| ... | |
| ' | |
| - pattern-not-inside: '$SF.setFeature("http://apache.org/xml/features/disallow-doctype-decl", | |
| true); | |
| ... | |
| ' | |
| - pattern-inside: '$P = $SFP.newSAXParser(); | |
| ... | |
| ' | |
| - pattern: $P.parse(...); | |
| - id: kotlin_xxe_rule-XMLRdr | |
| languages: | |
| - kotlin | |
| message: 'XML External Entity (XXE) attacks can occur when an XML parser supports | |
| XML | |
| entities while processing XML received from an untrusted source. | |
| ' | |
| metadata: | |
| shortDescription: Improper restriction of XML external entity reference ('XXE') | |
| category: security | |
| cwe: CWE-611 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| severity: ERROR | |
| patterns: | |
| - pattern-inside: '$R = XMLReaderFactory.createXMLReader() | |
| ... | |
| ' | |
| - pattern-not-inside: '$R.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true) | |
| ... | |
| ' | |
| - pattern: $R.parse(...) | |
| - id: kotlin_xxe_rule-XMLStreamRdr | |
| languages: | |
| - kotlin | |
| message: 'XML External Entity (XXE) attacks can occur when an XML parser supports | |
| XML | |
| entities while processing XML received from an untrusted source. | |
| ' | |
| metadata: | |
| shortDescription: Improper restriction of XML external entity reference ('XXE') | |
| category: security | |
| cwe: CWE-611 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| severity: ERROR | |
| patterns: | |
| - pattern-inside: '$SF = XMLInputFactory.newFactory(); | |
| ... | |
| ' | |
| - pattern-not-inside: '$SF.setProperty(XMLInputFactory.SUPPORT_DTD, false); | |
| ... | |
| ' | |
| - pattern-not-inside: '$SF.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, | |
| false); | |
| ... | |
| ' | |
| - pattern-not-inside: '$SF.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE); | |
| ... | |
| ' | |
| - pattern-not-inside: '$SF.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, | |
| Boolean.FALSE); | |
| ... | |
| ' | |
| - pattern: $SF.createXMLStreamReader(...) | |
| - id: kotlin_file_rule-FilenameUtils | |
| languages: | |
| - kotlin | |
| message: 'A file is opened to read its content. The filename comes from an input | |
| parameter. If an unfiltered parameter is passed to this file API, files from an | |
| arbitrary filesystem location could be read. | |
| ' | |
| metadata: | |
| shortDescription: Improper limitation of a pathname to a restricted directory | |
| ('Path Traversal') | |
| cwe: CWE-22 | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| security-severity: MEDIUM | |
| technology: | |
| - kotlin | |
| category: security | |
| severity: WARNING | |
| patterns: | |
| - pattern-inside: 'import org.apache.commons.io.FilenameUtils | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: normalize(...) | |
| - pattern: getExtension(...) | |
| - pattern: isExtensions(...) | |
| - pattern: getName(...) | |
| - pattern: getBaseName(...) | |
| - pattern: org.apache.commons.io.FilenameUtils.normalize(...) | |
| - pattern: org.apache.commons.io.FilenameUtils.getExtension(...) | |
| - pattern: org.apache.commons.io.FilenameUtils.isExtensions(...) | |
| - pattern: org.apache.commons.io.FilenameUtils.getName(...) | |
| - pattern: org.apache.commons.io.FilenameUtils.getBaseName(...) | |
| - id: kotlin_file_rule-FileUploadFileName | |
| languages: | |
| - kotlin | |
| message: 'The filename provided by the FileUpload API can be tampered with by the | |
| client to reference | |
| unauthorized files. The provided filename should be properly validated to ensure | |
| it''s properly | |
| structured, contains no unauthorized path characters (e.g., / \), and refers to | |
| an authorized | |
| file. | |
| ' | |
| metadata: | |
| category: security | |
| cwe: CWE-22 | |
| shortDescription: Improper limitation of a pathname to a restricted directory | |
| ('Path Traversal') | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| technology: | |
| - kotlin | |
| security-severity: CRITICAL | |
| severity: ERROR | |
| pattern-either: | |
| - patterns: | |
| - pattern-inside: "$FILES = ($SFU: ServletFileUpload).parseRequest(($REQ: $X.servlet.http.HttpServletRequest?))\n\ | |
| ...\nfor($ITEM in $FILES) {\n ...\n}\n" | |
| - pattern: $ITEM.getName() | |
| - pattern: '($PART: $X.servlet.http.Part).getSubmittedFileName()' | |
| - id: kotlin_inject_rule-FileDisclosure | |
| languages: | |
| - kotlin | |
| message: 'Constructing a server-side redirect path with user input could allow an | |
| attacker to download application binaries (including application classes or | |
| jar files) or view arbitrary files within protected directories. | |
| ' | |
| metadata: | |
| shortDescription: Files or directories accessible to external parties | |
| category: security | |
| cwe: CWE-552 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| severity: ERROR | |
| mode: taint | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: org.springframework.web.servlet.ModelAndView($FST); | |
| - pattern: $FST | |
| - patterns: | |
| - pattern: org.springframework.web.servlet.ModelAndView($FST, $SND); | |
| - pattern: $FST | |
| - patterns: | |
| - pattern: org.springframework.web.servlet.ModelAndView($FST, $SND, $TRD); | |
| - pattern: $FST | |
| - patterns: | |
| - pattern: org.apache.struts.action.ActionForward($FST) | |
| - pattern: $FST | |
| - patterns: | |
| - pattern: org.apache.struts.action.ActionForward($FST, $SND) | |
| - pattern: $FST | |
| - patterns: | |
| - pattern: org.apache.struts.action.ActionForward($FST, $SND, $TRD) | |
| - pattern: $SND | |
| - patterns: | |
| - pattern: org.apache.struts.action.ActionForward($FST, $SND, $TRD) | |
| - pattern: $TRD | |
| - patterns: | |
| - pattern-inside: '$ACTION = org.apache.struts.action.ActionForward(); | |
| ... | |
| ' | |
| - pattern: $ACTION.setPath(...) | |
| - patterns: | |
| - pattern-inside: '$MVC = org.springframework.web.servlet.ModelAndView(); | |
| ... | |
| ' | |
| - pattern: $MVC.setViewName(...); | |
| - patterns: | |
| - pattern-inside: '$REQ = $HTTP.getRequestDispatcher(...); | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: $REQ.include($FST, $SND) | |
| - pattern: $REQ.forward($FST, $SND) | |
| pattern-sources: | |
| - pattern: '($VAR: javax.servlet.http.HttpServletRequest).getParameter(...)' | |
| - id: kotlin_inject_rule-SqlInjection | |
| languages: | |
| - kotlin | |
| message: 'The input values included in SQL queries need to be passed in safely. | |
| Bind | |
| variables in prepared statements can be used to easily mitigate the risk of | |
| SQL injection. | |
| ' | |
| options: | |
| taint_assume_safe_functions: true | |
| metadata: | |
| shortDescription: Improper Neutralization of Special Elements used in an SQL Command | |
| ('SQL Injection') | |
| category: security | |
| cwe: CWE-89 | |
| technology: | |
| - java | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| severity: ERROR | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-inside: 'fun $FUNC(..., $SRC: String, ...) { ... }' | |
| - pattern: $SRC | |
| pattern-propagators: | |
| - pattern: $SB.append($SRC) | |
| from: $SRC | |
| to: $SB | |
| - patterns: | |
| - pattern: $F(..., $SRC, ...) | |
| - focus-metavariable: $F | |
| - pattern-either: | |
| - pattern: String.format | |
| - pattern: StringBuilder | |
| from: $SRC | |
| to: $F | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: '($PM: javax.jdo.PersistenceManager).newQuery($ARG)' | |
| - pattern: '($PM: javax.jdo.PersistenceManager).newQuery(..., $ARG)' | |
| - pattern: '($Q: javax.jdo.Query).setFilter($ARG)' | |
| - pattern: '($Q: javax.jdo.Query).setGrouping($ARG)' | |
| - pattern: org.hibernate.criterion.Restrictions.sqlRestriction($ARG, ...) | |
| - pattern: '($S: org.hibernate.Session).createQuery($ARG, ...)' | |
| - pattern: '($S: org.hibernate.Session).createSQLQuery($ARG, ...)' | |
| - pattern: '($S: java.sql.Statement).executeQuery($ARG, ...)' | |
| - pattern: '($S: java.sql.Statement).execute($ARG, ...)' | |
| - pattern: '($S: java.sql.Statement).executeUpdate($ARG, ...)' | |
| - pattern: '($S: java.sql.Statement).executeLargeUpdate($ARG, ...)' | |
| - pattern: '($S: java.sql.Statement).addBatch($ARG, ...)' | |
| - pattern: '($S: java.sql.PreparedStatement).executeQuery($ARG, ...)' | |
| - pattern: '($S: java.sql.PreparedStatement).execute($ARG, ...)' | |
| - pattern: '($S: java.sql.PreparedStatement).executeUpdate($ARG, ...)' | |
| - pattern: '($S: java.sql.PreparedStatement).executeLargeUpdate($ARG, ...)' | |
| - pattern: '($S: java.sql.PreparedStatement).addBatch($ARG, ...)' | |
| - pattern: '($S: java.sql.Connection).prepareCall($ARG, ...)' | |
| - pattern: '($S: java.sql.Connection).prepareStatement($ARG, ...)' | |
| - pattern: '($S: java.sql.Connection).nativeSQL($ARG, ...)' | |
| - pattern: org.springframework.jdbc.core.PreparedStatementCreatorFactory($ARG, | |
| ...) | |
| - pattern: '($F: org.springframework.jdbc.core.PreparedStatementCreatorFactory).newPreparedStatementCreator($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcOperations).batchUpdate($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcOperations).execute($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcOperations).query($ARG, ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcOperations).queryForList($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcOperations).queryForMap($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcOperations).queryForObject($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcOperations).queryForObject($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcOperations).queryForRowSet($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcOperations).queryForInt($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcOperations).queryForLong($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcOperations).update($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcTemplate).batchUpdate($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcTemplate).execute($ARG, ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcTemplate).query($ARG, ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcTemplate).queryForList($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcTemplate).queryForMap($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcTemplate).queryForObject($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcTemplate).queryForRowSet($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcTemplate).queryForInt($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcTemplate).queryForLong($ARG, | |
| ...)' | |
| - pattern: '($O: org.springframework.jdbc.core.JdbcTemplate).update($ARG, ...)' | |
| - pattern: '($O: io.vertx.sqlclient.SqlClient).query($ARG, ...)' | |
| - pattern: '($O: io.vertx.sqlclient.SqlClient).preparedQuery($ARG, ...)' | |
| - pattern: '($O: io.vertx.sqlclient.SqlConnection).prepare($ARG, ...)' | |
| - pattern: '($O: org.apache.turbine.om.peer.BasePeer).executeQuery($ARG, ...)' | |
| - pattern: '($O: org.apache.torque.util.BasePeer).executeQuery($ARG, ...)' | |
| - pattern: '($O: javax.persistence.EntityManager).createQuery($ARG, ...)' | |
| - pattern: '($O: javax.persistence.EntityManager).createNativeQuery($ARG, ...)' | |
| - pattern: '($H: org.jdbi.v3.core.Handle).createQuery($ARG, ...)' | |
| - pattern: '($H: org.jdbi.v3.core.Handle).createScript($ARG, ...)' | |
| - pattern: '($H: org.jdbi.v3.core.Handle).createUpdate($ARG, ...)' | |
| - pattern: '($H: org.jdbi.v3.core.Handle).execute($ARG, ...)' | |
| - pattern: '($H: org.jdbi.v3.core.Handle).prepareBatch($ARG, ...)' | |
| - pattern: '($H: org.jdbi.v3.core.Handle).select($ARG, ...)' | |
| - pattern: org.jdbi.v3.core.statement.Script($H, $ARG) | |
| - pattern: org.jdbi.v3.core.statement.Update($H, $ARG) | |
| - pattern: org.jdbi.v3.core.statement.PreparedBatch($H, $ARG) | |
| - focus-metavariable: $ARG | |
| - id: kotlin_inject_rule-OgnlInjection | |
| message: '"A expression is built with a dynamic value. The source of the value(s) | |
| should be verified to | |
| avoid that unfiltered values fall into this risky code evaluation." | |
| ' | |
| languages: | |
| - kotlin | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Expression injection (OGNL) | |
| category: security | |
| cwe: CWE-917 | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: "fun $FUNC(..., $VAR: String, ...) {\n ...\n}\n" | |
| - pattern-inside: "fun $FUNC(..., $VAR: Map<$K,$V>, ...) {\n ...\n}\n" | |
| - pattern-inside: "fun $FUNC(..., $VAR: Map<$K,*>, ...) {\n ...\n}\n" | |
| - pattern-inside: "fun $FUNC(..., $VAR: java.util.HashMap<$K,$V>, ...) {\n ...\n\ | |
| }\n" | |
| - pattern-either: | |
| - pattern: com.opensymphony.xwork2.util.TextParseUtil.translateVariables(...,$VAR, | |
| ...) | |
| - pattern: com.opensymphony.xwork2.util.TextParseUtil.translateVariablesCollection(..., | |
| $VAR, ...) | |
| - pattern: com.opensymphony.xwork2.util.TextParseUtil.shallBeIncluded(..., $VAR, | |
| ...) | |
| - pattern: com.opensymphony.xwork2.util.TextParseUtil.commaDelimitedStringToSet(..., | |
| $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.util.TextParser).evaluate(..., $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.util.OgnlTextParser).evaluate(..., $VAR, | |
| ...) | |
| - pattern: ($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).getGetMethod(..., | |
| $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).getSetMethod(..., | |
| $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).getField(..., | |
| $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).setProperties(..., | |
| $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).setProperty(...,$VAR, | |
| ...) | |
| - pattern: ($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).getValue(...,$VAR, | |
| ...) | |
| - pattern: ($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).setValue(...,$VAR, | |
| ...) | |
| - pattern: ($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).getGetMethod(..., | |
| $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).getSetMethod(..., | |
| $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).getField(..., | |
| $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).setProperties(..., | |
| $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).setProperty(..., | |
| $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).getValue(..., | |
| $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).setValue(..., | |
| $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.ognl.OgnlUtil).setProperties(..., $VAR, | |
| ...) | |
| - pattern: ($P:com.opensymphony.xwork2.ognl.OgnlUtil).setProperty(..., $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.ognl.OgnlUtil).getValue(..., $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.ognl.OgnlUtil).setValue(..., $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.ognl.OgnlUtil).callMethod(..., $VAR, ...) | |
| - pattern: ($P:com.opensymphony.xwork2.ognl.OgnlUtil).compile(..., $VAR, ...) | |
| - pattern: ($P:org.apache.struts2.util.VelocityStrutsUtil).evaluate(...) | |
| - pattern: org.apache.struts2.util.StrutsUtil.findString(...) | |
| - pattern: org.apache.struts2.util.StrutsUtil.findValue(..., $VAL) | |
| - pattern: org.apache.struts2.util.StrutsUtil.getText(...) | |
| - pattern: org.apache.struts2.util.StrutsUtil.translateVariables(...) | |
| - pattern: org.apache.struts2.util.StrutsUtil.makeSelectList(..., $VAR, ...) | |
| - pattern: ($T:org.apache.struts2.views.jsp.ui.OgnlTool).findValue(..., $VAR, | |
| ...) | |
| - pattern: ($V:com.opensymphony.xwork2.util.ValueStack).findString(...) | |
| - pattern: ($V:com.opensymphony.xwork2.util.ValueStack).findValue(..., $VAR, ...) | |
| - pattern: ($V:com.opensymphony.xwork2.util.ValueStack).setValue(..., $VAR, ...) | |
| - pattern: ($V:com.opensymphony.xwork2.util.ValueStack).setParameter(..., $VAR, | |
| ...) | |
| - id: kotlin_inject_rule-CommandInjection | |
| languages: | |
| - kotlin | |
| message: 'The highlighted API is used to execute a system command. If unfiltered | |
| input is passed to this | |
| API, it can lead to arbitrary command execution. | |
| ' | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Improper neutralization of special elements used in an OS command | |
| ('OS Command Injection') | |
| category: security | |
| cwe: CWE-78 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| pattern-either: | |
| - patterns: | |
| - pattern-inside: "fun $FUNC(..., $PARAM: String, ...) {\n ...\n}\n" | |
| - pattern-inside: '$R = Runtime.getRuntime() | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: $R.exec(<...$PARAM...>,...) | |
| - patterns: | |
| - pattern-either: | |
| - pattern: '$CMDARR = arrayOf("$SHELL",...,<...$PARAM...>,...) | |
| ... | |
| $R.exec($CMDARR,...) | |
| ' | |
| - pattern: $R.exec(arrayOf("$SHELL",...,<...$PARAM...>,...), ...) | |
| - pattern: $R.exec(java.util.String.format("...", ...,<...$PARAM...>,...)) | |
| - pattern: '$R.exec(($A: String) + ($B: String))' | |
| - metavariable-regex: | |
| metavariable: $SHELL | |
| regex: (/.../)?(sh|bash|ksh|csh|tcsh|zsh)$ | |
| - pattern-not: $R.exec("...","...","...",...) | |
| - pattern-not: '$R.exec(arrayOf("...","...","...",...),...) | |
| ' | |
| - patterns: | |
| - pattern-inside: "fun $FUNC(..., $PARAM: String, ...) {\n ...\n}\n" | |
| - pattern-inside: '$PB = ProcessBuilder() | |
| ... | |
| ' | |
| - pattern-either: | |
| - pattern: $PB.command(<...$PARAM...>,...) | |
| - patterns: | |
| - pattern-inside: $VAL = <...$PARAM...>; ... | |
| - pattern: $PB.command(<...$VAL...>,...) | |
| - patterns: | |
| - pattern-either: | |
| - pattern: $PB.command("$SHELL",...,<...$PARAM...>,...) | |
| - pattern: '$CMDARR = java.util.Arrays.asList("$SHELL",...,<...$PARAM...>,...) | |
| ... | |
| $PB.command($CMDARR,...) | |
| ' | |
| - pattern: $PB.command(java.util.Arrays.asList("$SHELL",...,<...$PARAM...>,...),...) | |
| - pattern: $PB.command(java.util.String.format("...", ...,<...$PARAM...>,...)) | |
| - pattern: '$PB.command(($A: String) + ($B: String))' | |
| - metavariable-regex: | |
| metavariable: $SHELL | |
| regex: (/.../)?(sh|bash|ksh|csh|tcsh|zsh)$ | |
| - pattern-not: $PB.command("...","...","...",...) | |
| - pattern-not: '$PB.command(java.util.Arrays.asList("...","...","...",...)) | |
| ' | |
| - id: kotlin_inject_rule-SpotbugsPathTraversalAbsolute | |
| languages: | |
| - kotlin | |
| message: 'The software uses an HTTP request parameter to construct a pathname that | |
| should be within a | |
| restricted directory, but it does not properly neutralize absolute path sequences | |
| such as | |
| "/abs/path" that can resolve to a location that is outside of that directory. | |
| See | |
| http://cwe.mitre.org/data/definitions/36.html for more information. | |
| ' | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Improper limitation of a pathname to a restricted directory | |
| ('Path Traversal') | |
| category: security | |
| cwe: CWE-22 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| mode: taint | |
| pattern-sanitizers: | |
| - pattern: org.apache.commons.io.FilenameUtils.getName(...) | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-inside: '$U = java.net.URI($VAR) | |
| ' | |
| - pattern-either: | |
| - pattern-inside: java.io.File($U) | |
| - pattern-inside: java.nio.file.Paths.get($U) | |
| - pattern: $VAR | |
| - patterns: | |
| - pattern-inside: java.io.RandomAccessFile($INPUT,...) | |
| - pattern: $INPUT | |
| - pattern: java.io.FileReader(...) | |
| - pattern: javax.activation.FileDataSource(...) | |
| - pattern: java.io.FileInputStream(...) | |
| - pattern: java.io.File(...) | |
| - pattern: java.nio.file.Paths.get(...) | |
| - pattern: java.io.File.createTempFile(...) | |
| - pattern: java.io.File.createTempDirectory(...) | |
| - pattern: java.nio.file.Files.createTempFile(...) | |
| - pattern: java.nio.file.Files.createTempDirectory(...) | |
| - patterns: | |
| - pattern: $SRC.$METHOD(...) | |
| - metavariable-pattern: | |
| metavariable: $SRC | |
| pattern-either: | |
| - pattern: getClass() | |
| - pattern: getClass().getClassLoader() | |
| - pattern: '($C: ClassLoader)' | |
| - pattern: '($C: Class)' | |
| - pattern: $CLZ.getClassLoader() | |
| - metavariable-pattern: | |
| metavariable: $METHOD | |
| pattern-either: | |
| - pattern: getResourceAsStream | |
| - pattern: getResource | |
| - patterns: | |
| - pattern-inside: java.io.FileWriter($PATH, ...) | |
| - pattern: $PATH | |
| - patterns: | |
| - pattern-inside: java.io.FileOutputStream($PATH, ...) | |
| - pattern: $PATH | |
| pattern-sources: | |
| - pattern: '($REQ: HttpServletRequest).getParameter(...)' | |
| - patterns: | |
| - pattern-inside: fun $FUNC(..., @RequestParam $REQ:$TYPE, ...) {...} | |
| - focus-metavariable: $REQ | |
| - id: kotlin_inject_rule-HttpParameterPollution | |
| languages: | |
| - kotlin | |
| message: 'Concatenating unvalidated user input into a URL can allow an attacker | |
| to override the value of | |
| a request parameter. Attacker may be able to override existing parameter values, | |
| inject a new | |
| parameter or exploit variables out of a direct reach. HTTP Parameter Pollution | |
| (HPP) attacks | |
| consist of injecting encoded query string delimiters into other existing parameters. | |
| If a web | |
| application does not properly sanitize the user input, a malicious user may compromise | |
| the | |
| logic of the application to perform either client-side or server-side attacks. | |
| ' | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Improper neutralization of argument delimiters in a command | |
| ('Argument Injection') | |
| category: security | |
| cwe: CWE-88 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| technology: | |
| - kotlin | |
| security-severity: CRITICAL | |
| mode: taint | |
| pattern-sources: | |
| - pattern: '($REQ: HttpServletRequest).getParameter(...)' | |
| pattern-sanitizers: | |
| - pattern: java.net.URLEncoder.encode(...) | |
| - pattern: com.google.common.net.UrlEscapers.urlPathSegmentEscaper().escape(...) | |
| pattern-sinks: | |
| - pattern: org.apache.http.client.methods.HttpGet(...) | |
| - pattern: org.apache.commons.httpclient.methods.GetMethod(...) | |
| - pattern: '($GM: org.apache.commons.httpclient.methods.GetMethod).setQueryString(...)' | |
| - id: kotlin_inject_rule-LDAPInjection | |
| languages: | |
| - kotlin | |
| message: 'Just like SQL, all inputs passed to an LDAP query need to be passed in | |
| safely. Unfortunately, | |
| LDAP doesn''t have prepared statement interfaces like SQL. Therefore, the primary | |
| defense | |
| against LDAP injection is strong input validation of any untrusted data before | |
| including it in | |
| an LDAP query. | |
| ' | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Improper neutralization of special elements used in an LDAP | |
| query ('LDAP Injection') | |
| category: security | |
| cwe: CWE-90 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| mode: taint | |
| pattern-sinks: | |
| - pattern: javax.naming.ldap.LdapName(...) | |
| - pattern: '($C: javax.naming.directory.Context).lookup(...)' | |
| - pattern: '($C: javax.naming.Context).lookup(...)' | |
| - patterns: | |
| - pattern-inside: '($C: com.unboundid.ldap.sdk.LDAPConnection).search($QUERY, | |
| ...)' | |
| - pattern: $QUERY | |
| - patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: $CTX.lookup(...) | |
| - patterns: | |
| - pattern-inside: $CTX.search($QUERY, ...) | |
| - pattern: $QUERY | |
| - patterns: | |
| - pattern-inside: $CTX.search($NAME, $FILTER, ...) | |
| - pattern: $FILTER | |
| - metavariable-pattern: | |
| metavariable: $CTX | |
| pattern-either: | |
| - pattern: '($C: DirContext)' | |
| - pattern: '($IDC: InitialDirContext)' | |
| - pattern: '($LC: LdapContext)' | |
| - pattern: '($EDC: EventDirContext)' | |
| - pattern: '($LC: LdapCtx)' | |
| - pattern: '($C: javax.naming.directory.DirContext)' | |
| - pattern: '($IDC: javax.naming.directory.InitialDirContext)' | |
| - pattern: '($LC: javax.naming.ldap.LdapContext)' | |
| - pattern: '($EDC: javax.naming.event.EventDirContext)' | |
| - pattern: '($LC: com.sun.jndi.ldap.LdapCtx)' | |
| - patterns: | |
| - pattern-either: | |
| - pattern: $CTX.lookup(...) | |
| - patterns: | |
| - pattern-inside: $CTX.search($QUERY, ...) | |
| - pattern: $QUERY | |
| - patterns: | |
| - pattern-inside: $CTX.search($NAME, $FILTER, ...) | |
| - pattern: $FILTER | |
| - pattern-inside: | |
| pattern-either: | |
| - pattern: $CTX = DirContext(...);... | |
| - pattern: $CTX = InitialDirContext(...);... | |
| - pattern: $CTX = LdapContext(...);... | |
| - pattern: $CTX = EventDirContext(...);... | |
| - pattern: $CTX = LdapCtx(...);... | |
| - pattern: $CTX = javax.naming.directory.DirContext(...);... | |
| - pattern: $CTX = javax.naming.directory.InitialDirContext(...);... | |
| - pattern: $CTX = javax.naming.ldap.LdapContext(...);... | |
| - pattern: $CTX = javax.naming.event.EventDirContext(...);... | |
| - pattern: $CTX = com.sun.jndi.ldap.LdapCtx(...);... | |
| - pattern-either: | |
| - patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: $CTX.list($QUERY, ...) | |
| - pattern: $QUERY | |
| - patterns: | |
| - pattern-inside: $CTX.lookup($QUERY, ...) | |
| - pattern: $QUERY | |
| - patterns: | |
| - pattern-inside: $CTX.search($QUERY, ...) | |
| - pattern: $QUERY | |
| - patterns: | |
| - pattern-inside: $CTX.search($NAME, $FILTER, ...) | |
| - pattern: $FILTER | |
| - metavariable-pattern: | |
| metavariable: $CTX | |
| pattern-either: | |
| - pattern: '($LT: LdapTemplate)' | |
| - pattern: '($LO: LdapOperations)' | |
| - pattern: '($LT: org.springframework.ldap.core.LdapTemplate)' | |
| - pattern: '($LO: org.springframework.ldap.core.LdapOperations)' | |
| - patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: $CTX.list($QUERY, ...) | |
| - pattern: $QUERY | |
| - patterns: | |
| - pattern-inside: $CTX.lookup($QUERY, ...) | |
| - pattern: $QUERY | |
| - patterns: | |
| - pattern-inside: $CTX.search($QUERY, ...) | |
| - pattern: $QUERY | |
| - patterns: | |
| - pattern-inside: $CTX.search($NAME, $FILTER, ...) | |
| - pattern: $FILTER | |
| - pattern-inside: | |
| pattern-either: | |
| - pattern: $CTX = LdapTemplate(...);... | |
| - pattern: $CTX = LdapOperations(...);... | |
| - pattern: $CTX = org.springframework.ldap.core.LdapTemplate(...);... | |
| - pattern: $CTX = org.springframework.ldap.core.LdapOperations(...);... | |
| pattern-sources: | |
| - patterns: | |
| - pattern-inside: "fun $FUNC(..., $VAR: String, ...) {\n ...\n}\n" | |
| - pattern: $VAR | |
| - patterns: | |
| - pattern-inside: "fun $FUNC(..., $X: String, ...) {\n ...\n $VAR = ... + $X\n\ | |
| \ ...\n}\n" | |
| - pattern: $VAR | |
| - id: kotlin_inject_rule-ELInjection | |
| languages: | |
| - kotlin | |
| message: 'An expression is built with a dynamic value. The source of the value(s) | |
| should be verified to | |
| avoid that unfiltered values fall into this risky code evaluation. | |
| ' | |
| metadata: | |
| category: security | |
| cwe: CWE-917 | |
| shortDescription: Improper neutralization of special elements used in an expression | |
| language statement ('Expression Language Injection') | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| pattern-either: | |
| - patterns: | |
| - metavariable-regex: | |
| metavariable: $METHOD | |
| regex: ^create(Method|Value)Expression$ | |
| - metavariable-pattern: | |
| metavariable: $EXPR | |
| patterns: | |
| - pattern-not: '"..."' | |
| - pattern: '($EXP: ExpressionFactory ).$METHOD(($CTX: $X.el.ELContext), $EXPR, | |
| ...) | |
| ' | |
| - patterns: | |
| - pattern: '($P: $X.el.ELProcessor).$METHOD(...) | |
| ' | |
| - pattern-not: '($P: $X.el.ELProcessor).$METHOD("...", ...) | |
| ' | |
| - metavariable-regex: | |
| metavariable: $METHOD | |
| regex: ^(eval|(get|set)Value)$ | |
| - id: kotlin_perm_rule-DangerousPermissions | |
| languages: | |
| - kotlin | |
| message: 'Do not grant dangerous combinations of permissions. | |
| ' | |
| metadata: | |
| shortDescription: Insecure inherited permissions | |
| category: security | |
| cwe: CWE-277 | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| confidence: HIGH | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: '$PC = $X.getPermissions(...) | |
| ... | |
| ' | |
| - pattern: $PC.add($PERMISSION) | |
| - pattern: '$REFVAR = $PERMISSION | |
| ...; | |
| ($PC: PermissionCollection).add($REFVAR) | |
| ' | |
| - pattern: '($PC: PermissionCollection).add($PERMISSION)' | |
| - metavariable-pattern: | |
| metavariable: $PERMISSION | |
| pattern-either: | |
| - pattern: ReflectPermission("suppressAccessChecks") | |
| - pattern: RuntimePermission("createClassLoader") | |
| - id: kotlin_perm_rule-OverlyPermissiveFilePermissionInline | |
| languages: | |
| - kotlin | |
| message: 'Overly permissive file permission | |
| ' | |
| metadata: | |
| shortDescription: Incorrect permission assignment for critical resource | |
| cwe: CWE-732 | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| category: security | |
| confidence: HIGH | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| patterns: | |
| - pattern-either: | |
| - pattern: java.nio.file.Files.setPosixFilePermissions(..., java.nio.file.attribute.PosixFilePermissions.fromString("$PERM_STRING")); | |
| - pattern: '$PERMISSIONS = java.nio.file.attribute.PosixFilePermissions.fromString("$PERM_STRING"); | |
| ... | |
| java.nio.file.Files.setPosixFilePermissions(..., $PERMISSIONS); | |
| ' | |
| - metavariable-regex: | |
| metavariable: $PERM_STRING | |
| regex: '[rwx-]{6}[rwx]{1,}' | |
| - id: kotlin_ldap_rule-AnonymousLDAP | |
| languages: | |
| - kotlin | |
| message: 'Without proper access control, executing an LDAP statement that contains | |
| a | |
| user-controlled value can allow an attacker to abuse poorly configured LDAP | |
| context | |
| ' | |
| metadata: | |
| shortDescription: Missing authentication for critical function (LDAP) | |
| category: security | |
| cwe: CWE-306 | |
| owasp: | |
| - A2:2017-Broken Authentication | |
| - A07:2021-Identification and Authentication Failures | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| patterns: | |
| - pattern-inside: 'import javax.naming.Context | |
| ... | |
| ' | |
| - pattern: $ENV[Context.SECURITY_AUTHENTICATION] = "none" | |
| - id: rules_lgpl_kotlin_other_rule-android-kotlin-webview-debug | |
| patterns: | |
| - pattern: '$X.setWebContentsDebuggingEnabled(true) | |
| ' | |
| - pattern-inside: 'WebView | |
| ... | |
| ' | |
| message: "Remote WebView debugging is enabled.This can introduce security \nrisks\ | |
| \ as it allows remote debugging tools, such as Chrome DevTools, \nto inspect and\ | |
| \ manipulate the WebView content. This can potentially \nexpose sensitive information,\ | |
| \ including user data, session tokens, \nand other confidential data, to unauthorized\ | |
| \ parties.\n\nTo fix this security issue, you should disable remote WebView \n\ | |
| debugging in production builds of your app. Here's how you can do it:\n```\nimport\ | |
| \ WebKit\n\nclass ViewController: UIViewController {\n\n override func viewDidLoad()\ | |
| \ {\n super.viewDidLoad()\n\n // Disable remote WebView debugging\ | |
| \ in production builds\n #if DEBUG\n WebViewConfiguration.shared().preferences.setValue(true,\ | |
| \ forKey: \"developerExtrasEnabled\")\n #else\n WebViewConfiguration.shared().preferences.setValue(false,\ | |
| \ forKey: \"developerExtrasEnabled\")\n #endif\n\n // Other setup\ | |
| \ code...\n }\n\n // Other methods...\n}\n```\n" | |
| languages: | |
| - kotlin | |
| severity: WARNING | |
| metadata: | |
| category: security | |
| cwe: CWE-489 | |
| shortDescription: Leftover debug code | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| security-severity: MEDIUM | |
| - id: kotlin_xss_rule-WicketXSS | |
| languages: | |
| - kotlin | |
| message: 'Disabling HTML escaping put the application at risk for Cross-Site Scripting | |
| (XSS). | |
| ' | |
| metadata: | |
| shortDescription: Improper neutralization of input during web page generation | |
| ('Cross-site Scripting') | |
| category: security | |
| cwe: CWE-79 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| patterns: | |
| - pattern-inside: 'import org.apache.wicket.$A | |
| ... | |
| ' | |
| - pattern: '$OBJ.setEscapeModelStrings(false); | |
| ' | |
| - id: kotlin_xss_rule-XSSReqParamToServletWriter | |
| languages: | |
| - kotlin | |
| message: 'Servlet reflected cross site scripting vulnerability | |
| ' | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Improper neutralization of input during web page generation | |
| ('Cross-site Scripting') | |
| category: security | |
| cwe: CWE-79 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| mode: taint | |
| pattern-sanitizers: | |
| - patterns: | |
| - pattern-inside: org.owasp.encoder.Encode.forHtml($TAINTED); | |
| - pattern: $TAINTED | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-inside: 'fun $FUNC(..., $RES: HttpServletResponse , ...) {...}' | |
| - pattern-inside: '$WRITER = $RES.getWriter(); | |
| ... | |
| ' | |
| - pattern: $WRITER.write($DATA,...); | |
| - pattern: $DATA | |
| - patterns: | |
| - pattern-inside: 'fun $FUNC(..., $RES: HttpServletResponse , ...) {...}' | |
| - pattern: $RES.getWriter().write($DATA,...); | |
| - pattern: $DATA | |
| pattern-sources: | |
| - patterns: | |
| - pattern-inside: 'fun $FUNC(..., $REQ: HttpServletRequest , ...) {...}' | |
| - pattern: $REQ.getParameter(...); | |
| - id: kotlin_script_rule-ScriptInjection | |
| languages: | |
| - kotlin | |
| message: 'The software constructs all or part of a code segment using externally-influenced | |
| input from an upstream component, but it does not neutralize or incorrectly | |
| neutralizes special elements that could modify the syntax or behavior of the | |
| intended code segment. | |
| ' | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Improper control of generation of code ('Code Injection') | |
| category: security | |
| cwe: CWE-94 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| mode: taint | |
| pattern-sinks: | |
| - patterns: | |
| - patterns: | |
| - pattern-inside: '$ENGINE = $F.getEngineByExtension(...) | |
| ... | |
| ' | |
| - pattern: $ENGINE.eval($ARG, ...); | |
| - pattern-not: $ENGINE.eval("..."); | |
| - pattern-not: '$ENGINE.eval("...", ($BINDING: javax.script.Bindings));' | |
| - patterns: | |
| - pattern: '($ENGINE: javax.script.ScriptEngine).eval($ARG, ...);' | |
| - pattern-not: '($ENGINE: javax.script.ScriptEngine).eval("...");' | |
| - pattern-not: '($ENGINE: javax.script.ScriptEngine).eval("...", ($BINDING: javax.script.Bindings));' | |
| - pattern: '($INVC: javax.script.Invocable).invokeFunction(..., $ARG)' | |
| - pattern: '($INVC: javax.script.Invocable).invokeMethod(..., $ARG)' | |
| pattern-sources: | |
| - patterns: | |
| - pattern-inside: 'fun $FUNC(..., $VAR: String, ...) { ... }' | |
| - pattern: $VAR | |
| - id: kotlin_xml_rule-SAMLIgnoreComments | |
| languages: | |
| - kotlin | |
| message: 'Ignoring XML comments in SAML may lead to authentication bypass | |
| ' | |
| metadata: | |
| shortDescription: Weak authentication | |
| cwe: CWE-1390 | |
| category: security | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| pattern: '($POOL: org.opensaml.xml.parse.BasicParserPool).setIgnoreComments(false);' | |
| - id: kotlin_xml_rule-XsltTransform | |
| languages: | |
| - kotlin | |
| message: 'It is possible to attach malicious behavior to those style sheets. Therefore, | |
| if an attacker | |
| can control the content or the source of the style sheet, he might be able to | |
| trigger remote | |
| code execution. | |
| ' | |
| metadata: | |
| shortDescription: XML injection (aka Blind XPath injection) | |
| category: security | |
| cwe: CWE-91 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: "fun $FUNC(...,$VAR: String, ...) {\n ...\n}\n" | |
| - pattern-either: | |
| - pattern: FileInputStream(<... $VAR ...>); | |
| - pattern: javaClass.getResourceAsStream(<... $VAR ...>) | |
| - patterns: | |
| - pattern-inside: "class $CLZ {\n var $X = \"...\";\n ...\n}\n" | |
| - pattern-inside: "fun $FUNC(...,$Y: String, ...) {\n ...\n}\n" | |
| - pattern-either: | |
| - pattern: FileInputStream($X + $Y); | |
| - pattern: javaClass.getResourceAsStream($X + $Y) | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: '($T: javax.xml.transform.TransformerFactory).newTransformer($SRC, | |
| ...)' | |
| - pattern-inside: '($T: javax.xml.transform.Transformer).transform($SRC, ...)' | |
| - patterns: | |
| - pattern-inside: '$FACTORY = javax.xml.transform.TransformerFactory.newInstance(...) | |
| ...' | |
| - pattern-inside: $FACTORY.newTransformer($SRC, ...) | |
| - patterns: | |
| - pattern-inside: '$FACTORY = javax.xml.transform.TransformerFactory(...) | |
| ...' | |
| - pattern-inside: '$T = $FACTORY.newTransformer(...) | |
| ...' | |
| - pattern-inside: $T.transform($SRC, ...) | |
| - pattern: $SRC | |
| - id: kotlin_xml_rule-XmlDecoder | |
| languages: | |
| - kotlin | |
| message: 'Avoid using XMLDecoder to parse content from an untrusted source. | |
| ' | |
| metadata: | |
| shortDescription: Deserialization of untrusted data | |
| category: security | |
| cwe: CWE-502 | |
| owasp: | |
| - A8:2017-Insecure Deserialization | |
| - A08:2021-Software and Data Integrity Failures | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| patterns: | |
| - pattern-either: | |
| - pattern: '($D: java.beans.XMLDecoder).readObject()' | |
| - patterns: | |
| - pattern: $D.readObject() | |
| - pattern-inside: '$D = XMLDecoder(...) | |
| ... | |
| ' | |
| - pattern-not: | |
| pattern-either: | |
| - patterns: | |
| - pattern-inside: '$DEC = java.beans.XMLDecoder(..., $CL) | |
| ... | |
| ' | |
| - pattern: $DEC.readObject() | |
| - metavariable-pattern: | |
| metavariable: $CL | |
| patterns: | |
| - pattern: "object : ClassLoader() {\n ...\n fun loadClass(name: String,\ | |
| \ resolve: Boolean): $RET {\n if($X){\n throw ...\n }\n\ | |
| \ ...\n }\n ...\n}\n" | |
| - metavariable-pattern: | |
| metavariable: $X | |
| pattern-either: | |
| - pattern: 'name != ... | |
| ' | |
| - pattern: '!$LIST.contains(name) | |
| ' | |
| - patterns: | |
| - pattern-inside: '$CLASS_LOADER = $CL | |
| ... | |
| ' | |
| - pattern-inside: '$DEC = java.beans.XMLDecoder(..., $CLASS_LOADER) | |
| ... | |
| ' | |
| - pattern: $DEC.readObject() | |
| - metavariable-pattern: | |
| metavariable: $CL | |
| patterns: | |
| - pattern: "object : ClassLoader(){\n ...\n fun loadClass(name: String,\ | |
| \ resolve: Boolean): $RET{\n if($X){\n throw ...\n }\n\ | |
| \ ...\n }\n ...\n}\n" | |
| - metavariable-pattern: | |
| metavariable: $X | |
| pattern-either: | |
| - pattern: 'name != ... | |
| ' | |
| - pattern: '!$LIST.contains(name) | |
| ' | |
| - id: kotlin_csrf_rule-SpringCSRFDisabled | |
| languages: | |
| - kotlin | |
| message: 'The application fails to protect against Cross-Site Request Forgery (CSRF) | |
| due to disabling Spring''s CSRF protection features. | |
| ' | |
| metadata: | |
| shortDescription: Cross-Site Request Forgery (CSRF) | |
| category: security | |
| cwe: CWE-352 | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| pattern-either: | |
| - pattern: '($H: org.springframework.security.config.annotation.web.builders.HttpSecurity). | |
| ... .csrf().disable()' | |
| - pattern: '($C: CsrfConfigurer<HttpSecurity>).disable()' | |
| - id: kotlin_xpathi_rule-XpathInjection | |
| languages: | |
| - kotlin | |
| message: 'The input values included in SQL queries need to be passed in safely. | |
| Bind | |
| variables in prepared statements can be used to easily mitigate the risk of | |
| SQL injection. | |
| ' | |
| metadata: | |
| shortDescription: Improper neutralization of data within XPath expressions ('XPath | |
| Injection') | |
| category: security | |
| cwe: CWE-643 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| severity: ERROR | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-inside: "fun $FUNC(..., $VAR: $T, ...) {\n ...\n}\n" | |
| - pattern: $VAR | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: "import javax.xml.xpath.*; \n...\n" | |
| - pattern-inside: "import javax.xml.xpath.XPath; \n...\n" | |
| - patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern: $X.compile($VAR) | |
| - pattern-not: $X.compile("...") | |
| - patterns: | |
| - pattern: $X.evaluate($VAR, ...) | |
| - pattern-not: $X.evaluate("...", ...) | |
| pattern-sanitizers: | |
| - pattern-either: | |
| - pattern-inside: '$X.xPathVariableResolver = ...; | |
| ...; | |
| $X.compile("..."); | |
| ' | |
| - pattern-inside: '$X.setXPathVariableResolver(...); | |
| ...; | |
| $X.compile("..."); | |
| ' | |
| - id: kotlin_unsafe_rule-ExternalConfigControl | |
| languages: | |
| - kotlin | |
| message: 'Allowing external control of system settings can disrupt service or cause | |
| an application to | |
| behave in unexpected, and potentially malicious ways. An attacker could cause | |
| an error by | |
| providing a nonexistent catalog name or connect to an unauthorized portion of | |
| the database. | |
| ' | |
| severity: WARNING | |
| metadata: | |
| shortDescription: External control of system or configuration setting | |
| category: security | |
| cwe: CWE-15 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| patterns: | |
| - metavariable-pattern: | |
| metavariable: $GET_PARAMETER | |
| pattern-either: | |
| - pattern: '($REQ: HttpServletRequest).getParameter' | |
| - pattern: '($REQ: HttpServletRequest?)?.getParameter' | |
| - metavariable-pattern: | |
| metavariable: $SET_CATALOG | |
| pattern-either: | |
| - pattern: '($CONN: java.sql.Connection).setCatalog' | |
| - pattern: '($CONN: java.sql.Connection?)?.setCatalog' | |
| - pattern: '$TAINTED = $GET_PARAMETER(...) | |
| ... | |
| $SET_CATALOG($TAINTED)' | |
| - id: kotlin_smtp_rule-InsecureSmtp | |
| languages: | |
| - kotlin | |
| message: 'Server identity verification is disabled when making SSL connections. | |
| ' | |
| metadata: | |
| shortDescription: Improper validation of certificate with host mismatch | |
| category: security | |
| cwe: CWE-297 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: CRITICAL | |
| severity: ERROR | |
| patterns: | |
| - pattern-either: | |
| - pattern-inside: '$E = org.apache.commons.mail.SimpleEmail(...) | |
| ... | |
| ' | |
| - pattern-inside: '$E = org.apache.commons.mail.Email(...) | |
| ... | |
| ' | |
| - pattern-inside: '$E = org.apache.commons.mail.MultiPartEmail(...) | |
| ... | |
| ' | |
| - pattern-inside: '$E = org.apache.commons.mail.HtmlEmail(...) | |
| ... | |
| ' | |
| - pattern-inside: '$E = org.apache.commons.mail.ImageHtmlEmail(...) | |
| ... | |
| ' | |
| - pattern-not: '$E.setSSLOnConnect(true) | |
| ... | |
| $E.setSSLCheckServerIdentity(true) | |
| ' | |
| - id: kotlin_smtp_rule-SmtpClient | |
| languages: | |
| - kotlin | |
| message: 'Simple Mail Transfer Protocol (SMTP) is a the text based protocol used | |
| for | |
| email delivery. Like with HTTP, headers are separate by new line separator. If | |
| kuser input is place in a header line, the application should remove or replace | |
| new line characters (CR / LF). You should use a safe wrapper such as Apache | |
| Common Email and Simple Java Mail which filter special characters that can lead | |
| to header injection. | |
| ' | |
| metadata: | |
| shortDescription: Improper neutralization of special elements used in a command | |
| category: security | |
| cwe: CWE-77 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| severity: ERROR | |
| patterns: | |
| - pattern-inside: '$M = MimeMessage(...); | |
| ... | |
| ' | |
| - pattern-either: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: $M.setSubject($VAR) | |
| - pattern: $M.addHeader($ARG, $VAR) | |
| - pattern: $M.addHeader($VAR, $ARG) | |
| - pattern: $M.setDescription($VAR) | |
| - pattern: $M.setDisposition($VAR) | |
| - metavariable-regex: | |
| metavariable: $VAR | |
| regex: ^[a-zA-Z_$][a-zA-Z0-9_$]*$ | |
| - patterns: | |
| - pattern-either: | |
| - pattern: $M.setSubject($OBJ.$GETTER(...)) | |
| - pattern: $M.setSubject($OBJ.$GETTER(...) + ...) | |
| - pattern: $M.setSubject(... + $OBJ.$GETTER(...)) | |
| - pattern: $M.setSubject(... + $OBJ.$GETTER(...) + ...) | |
| - pattern: $M.addHeader($ARG, $OBJ.$GETTER(...)) | |
| - pattern: $M.addHeader($ARG, $OBJ.$GETTER(...) + ...) | |
| - pattern: $M.addHeader($ARG, ... + $OBJ.$GETTER(...)) | |
| - pattern: $M.addHeader($ARG, ... + $OBJ.$GETTER(...) + ...) | |
| - pattern: $M.addHeader($OBJ.$GETTER(...), $ARG) | |
| - pattern: $M.addHeader($OBJ.$GETTER(...) + ..., $ARG) | |
| - pattern: $M.addHeader(... + $OBJ.$GETTER(...), $ARG) | |
| - pattern: $M.addHeader(... + $OBJ.$GETTER(...) + ..., $ARG) | |
| - pattern: $M.setDescription($OBJ.$GETTER(...)) | |
| - pattern: $M.setDisposition($OBJ.$GETTER(...) + ...) | |
| - pattern: $M.setDisposition(... + $OBJ.$GETTER(...)) | |
| - pattern: $M.setDisposition(... + $OBJ.$GETTER(...) + ...) | |
| - metavariable-regex: | |
| metavariable: $GETTER | |
| regex: ^get | |
| - id: kotlin_endpoint_rule-WeakHostNameVerification | |
| languages: | |
| - kotlin | |
| message: 'A HostnameVerifier that accept any host are often use because of certificate | |
| reuse on many hosts. As a consequence, this is vulnerable to Man-in-the-middle | |
| attacks since the client will trust any certificate. | |
| ' | |
| metadata: | |
| category: security | |
| cwe: CWE-295 | |
| shortDescription: Improper Certificate Validation | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| patterns: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: "class $V : HostnameVerifier {\n ...\n}\n" | |
| - pattern: "fun verify(...): Boolean {\n return true\n}\n" | |
| - patterns: | |
| - pattern-inside: "class $V : X509TrustManager {\n ...\n}\n" | |
| - pattern-either: | |
| - pattern: fun checkClientTrusted(...) {} | |
| - pattern: fun checkServerTrusted(...) {} | |
| - pattern: 'fun getAcceptedIssuers(): Array<X509Certificate>? {return null}' | |
| - id: kotlin_endpoint_rule-UnvalidatedRedirect | |
| languages: | |
| - kotlin | |
| message: 'Unvalidated redirects occur when an application redirects a user to a | |
| destination URL specified by a user supplied parameter that is not validated. | |
| Such vulnerabilities can be used to facilitate phishing attacks. | |
| ' | |
| metadata: | |
| category: security | |
| cwe: CWE-601 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| shortDescription: URL redirection to untrusted site ('Open Redirect') | |
| security-severity: CRITICAL | |
| severity: ERROR | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern: '$URL = ($REQ: $X.servlet.http.HttpServletRequest).$M(...); | |
| ' | |
| - metavariable-regex: | |
| metavariable: $M | |
| regex: (getParameter|getCookies|getHeader|getHeaders|getHeaderNames|getPathInfo|getPathTranslated|getContextPath|getQueryString|getRemoteUser|getRequestedSessionId|getRequestURI|getRequestURL|getServletPath|getParts|getPart|getReader) | |
| pattern-sinks: | |
| - pattern-either: | |
| - pattern: '($RES: $X.servlet.http.HttpServletResponse).sendRedirect($URL) | |
| ' | |
| - pattern: '($RES: $X.servlet.http.HttpServletResponse).addHeader("Location", | |
| $URL) | |
| ' | |
| pattern-sanitizers: | |
| - patterns: | |
| - pattern-inside: "if ($SAFE.contains($URL)){\n ...\n}\n" | |
| - pattern-either: | |
| - pattern: '($RES: $X.servlet.http.HttpServletResponse).sendRedirect($URL) | |
| ' | |
| - pattern: '($RES: $X.servlet.http.HttpServletResponse).addHeader("Location", | |
| $URL) | |
| ' | |
| - id: kotlin_cors_rule-PermissiveCORSInjection | |
| languages: | |
| - kotlin | |
| message: 'Prior to HTML5, Web browsers enforced the Same Origin Policy which ensures | |
| that in order for | |
| JavaScript to access the contents of a Web page, both the JavaScript and the Web | |
| page must | |
| originate from the same domain. Without the Same Origin Policy, a malicious website | |
| could serve | |
| up JavaScript that loads sensitive information from other websites using a client''s | |
| credentials, cull through it, and communicate it back to the attacker. HTML5 makes | |
| it possible | |
| for JavaScript to access data across domains if a new HTTP header called | |
| Access-Control-Allow-Origin is defined. With this header, a Web server defines | |
| which other | |
| domains are allowed to access its domain using cross-origin requests. However, | |
| caution should | |
| be taken when defining the header because an overly permissive CORS policy will | |
| allow a | |
| malicious application to communicate with the victim application in an inappropriate | |
| way, | |
| leading to spoofing, data theft, relay and other attacks. | |
| ' | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Permissive cross-domain policy with untrusted domains | |
| cwe: CWE-942 | |
| category: security | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| technology: | |
| - kotlin | |
| security-severity: CRITICAL | |
| mode: taint | |
| pattern-sources: | |
| - pattern: '($REQ: HttpServletRequest).getParameter(...)' | |
| - pattern: '($REQ: HttpServletRequest).getHeader(...)' | |
| - pattern: '($REQ: HttpServletRequest).getPathInfo()' | |
| - pattern: '($REQ: HttpServletRequest).getQueryString()' | |
| - pattern: '($REQ: HttpServletRequest).getAttribute(...)' | |
| - pattern: '($REQ: HttpServletRequest).getSession().getAttribute(...)' | |
| - pattern: '($REQ: HttpServletRequest).getServletContext().getAttribute(...)' | |
| - pattern: '($REQ: HttpServletRequest).getParameterValues(...)' | |
| - pattern: '($REQ: HttpServletRequest).getParameterNames()' | |
| - pattern: '($REQ: HttpServletRequest).getParameterMap()' | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: '($RES: HttpServletResponse).setHeader("$HEADER", ...)' | |
| - pattern: '($RES: HttpServletResponse).addHeader("$HEADER", ...)' | |
| - metavariable-regex: | |
| metavariable: $HEADER | |
| regex: (?i)(Access-Control-Allow-Origin) | |
| - id: kotlin_cookie_rule-CookieHTTPOnly | |
| languages: | |
| - kotlin | |
| message: 'A new cookie is created without the HttpOnly flag set. The HttpOnly flag | |
| is a directive to the | |
| browser to make sure that the cookie can not be red by malicious script. When | |
| a user is the | |
| target of a "Cross-Site Scripting", the attacker would benefit greatly from getting | |
| the session | |
| id for example. | |
| ' | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Sensitive cookie without 'HttpOnly' flag | |
| category: security | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-1004 | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| patterns: | |
| - pattern: '$C = $X.servlet.http.Cookie(..., ...) | |
| ...; | |
| ($RESP: $X.servlet.http.HttpServletResponse).addCookie($C) | |
| ' | |
| - pattern-not-inside: '$C = $X.servlet.http.Cookie(..., ...) | |
| ... | |
| $C.setHttpOnly(true) | |
| ...; | |
| ($RESP: $X.servlet.http.HttpServletResponse).addCookie($C) | |
| ' | |
| - id: kotlin_cookie_rule-HttpResponseSplitting | |
| languages: | |
| - kotlin | |
| message: 'When an HTTP request contains unexpected CR and LF characters, the server | |
| may respond with an | |
| output stream that is interpreted as two different HTTP responses (instead of | |
| one). An attacker | |
| can control the second response and mount attacks such as cross-site scripting | |
| and cache | |
| poisoning attacks. | |
| ' | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Improper neutralization of CRLF sequences in HTTP headers ('HTTP | |
| Response Splitting') | |
| category: security | |
| cwe: CWE-113 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| mode: taint | |
| pattern-sanitizers: | |
| - patterns: | |
| - metavariable-pattern: | |
| metavariable: $S0 | |
| pattern-either: | |
| - pattern: '...' | |
| - pattern: '""' | |
| - metavariable-pattern: | |
| metavariable: $PATTERN | |
| patterns: | |
| - pattern: '...' | |
| - pattern-regex: .*\[\]?(?=[^]]*\\r)(?=[^]]*\\n)[^]]*\]\+ | |
| - pattern-inside: '$STR.replace($PATTERN, $S0) | |
| ... | |
| ' | |
| - pattern: org.apache.commons.text.StringEscapeUtils.escapeJava(...) | |
| pattern-sinks: | |
| - pattern: javax.servlet.http.Cookie("$KEY", ...) | |
| - patterns: | |
| - pattern-inside: '$C = javax.servlet.http.Cookie("$KEY", ...) | |
| ... | |
| ' | |
| - pattern: $C.setValue(...) | |
| pattern-sources: | |
| - pattern: '($REQ: javax.servlet.http.HttpServletRequest).getParameter(...)' | |
| - pattern: '($REQ: javax.servlet.http.HttpServletRequest).getParameterNames()' | |
| - pattern: '($REQ: javax.servlet.http.HttpServletRequest).getParameterValues(...)' | |
| - pattern: '($REQ: javax.servlet.http.HttpServletRequest).getParameterMap()' | |
| - pattern: '($REQ: javax.servlet.http.HttpServletRequest).getHeader(...)' | |
| - pattern: '($REQ: javax.servlet.http.HttpServletRequest).getPathInfo()' | |
| - id: kotlin_cookie_rule-CookieInsecure | |
| languages: | |
| - kotlin | |
| message: "\"A new cookie is created without the Secure flag set. The Secure flag\ | |
| \ is a\n directive to the browser to make sure that the cookie is not sent for\ | |
| \ insecure communication\n(http://)\"\n" | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Sensitive cookie in HTTPS session without 'Secure' attribute | |
| category: security | |
| cwe: CWE-614 | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| technology: | |
| - kotlin | |
| security-severity: MEDIUM | |
| patterns: | |
| - pattern: '$C = $X.servlet.http.Cookie(..., ...) | |
| ...; | |
| ($RESP: $X.servlet.http.HttpServletResponse).addCookie($C) | |
| ' | |
| - pattern-not-inside: '$C = $X.servlet.http.Cookie(..., ...) | |
| ... | |
| $C.setSecure(true) | |
| ...; | |
| ($RESP: $X.servlet.http.HttpServletResponse).addCookie($C) | |
| ' | |
| - id: kotlin_cookie_rule-RequestParamToHeader | |
| languages: | |
| - kotlin | |
| message: 'This code directly writes an HTTP parameter to an HTTP header, which allows | |
| for a HTTP | |
| response splitting vulnerability. See http://en.wikipedia.org/wiki/HTTP_response_splitting | |
| for | |
| more information. | |
| ' | |
| severity: ERROR | |
| metadata: | |
| shortDescription: Improper neutralization of CRLF sequences in HTTP headers ('HTTP | |
| Response Splitting') | |
| category: security | |
| cwe: CWE-113 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| technology: | |
| - kotlin | |
| security-severity: CRITICAL | |
| mode: taint | |
| pattern-sanitizers: | |
| - patterns: | |
| - metavariable-pattern: | |
| metavariable: $S0 | |
| pattern-either: | |
| - pattern: '...' | |
| - pattern: '""' | |
| - metavariable-pattern: | |
| metavariable: $PATTERN | |
| patterns: | |
| - pattern: '...' | |
| - pattern-regex: .*\[\]?(?=[^]]*\\r)(?=[^]]*\\n)[^]]*\]\+ | |
| - pattern-inside: '$STR.replace($PATTERN, $S0); | |
| ... | |
| ' | |
| - pattern: org.apache.commons.text.StringEscapeUtils.unescapeJava(...); | |
| pattern-sinks: | |
| - pattern: '($RES: $X.servlet.http.HttpServletResponse).setHeader("$KEY", ...);' | |
| - pattern: '($RES: $X.servlet.http.HttpServletResponse).addHeader("$KEY", ...);' | |
| - pattern: '($WRP: $X.servlet.http.HttpServletResponseWrapper).setHeader("$KEY", | |
| ...);' | |
| - pattern: '($WRP: $X.servlet.http.HttpServletResponseWrapper).addHeader("$KEY", | |
| ...);' | |
| pattern-sources: | |
| - pattern: '($REQ: $X.servlet.http.HttpServletRequest).getParameter(...);' | |
| - pattern: '($REQ: $X.servlet.http.HttpServletRequest).getParameterNames();' | |
| - pattern: '($REQ: $X.servlet.http.HttpServletRequest).getParameterValues(...);' | |
| - pattern: '($REQ: $X.servlet.http.HttpServletRequest).getParameterMap();' | |
| - pattern: '($REQ: $X.servlet.http.HttpServletRequest).getHeader(...);' | |
| - pattern: '($REQ: $X.servlet.http.HttpServletRequest).getPathInfo();' | |
| - id: java_ftp_rule-FTPInsecureTransport | |
| message: "This rule identifies instances where the application uses FTP (File\n\ | |
| Transfer Protocol) for transferring files. FTP transmits data in clear\ntext,\ | |
| \ allowing usernames, passwords, and other sensitive information to be\nintercepted\ | |
| \ by attackers. Consider using secure alternatives like SFTP\n(SSH File Transfer\ | |
| \ Protocol) or FTPS (FTP Secure) that provide encryption\nto protect data in transit.\n\ | |
| \nRemediation Strategy: To mitigate the risks associated with using unencrypted\n\ | |
| FTP, the application should switch to a secure file transfer protocol like\nSFTP\ | |
| \ or FTPS. Below is an example of how to implement FTPS in a Java\napplication.\n\ | |
| \n``` \nimport org.apache.commons.net.ftp.FTPSClient;\n\npublic class FTPSExample\ | |
| \ {\n public static void main(String[] args) {\n String server = \"\ | |
| ftps.example.com\";\n int port = 21;\n String user = \"your_username\"\ | |
| ;\n String pass = \"your_password\";\n\n FTPSClient ftpsClient =\ | |
| \ new FTPSClient();\n try {\n ftpsClient.connect(server, port);\n\ | |
| \ ftpsClient.login(user, pass);\n // Perform file operations\n\ | |
| \n ftpsClient.logout();\n ftpsClient.disconnect();\n \ | |
| \ } catch (Exception e) {\n e.printStackTrace();\n }\n \ | |
| \ }\n} \n```\n" | |
| severity: WARNING | |
| metadata: | |
| security-severity: MEDIUM | |
| shortDescription: Cleartext transmission of sensitive information | |
| category: security | |
| cwe: CWE-319 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| references: | |
| - https://www.codejava.net/java-se/ftp/connect-and-login-to-a-ftp-server | |
| - https://commons.apache.org/proper/commons-net/apidocs/org/apache/commons/net/ftp/FTPClient.html | |
| subcategory: | |
| - vuln | |
| technology: | |
| - java | |
| vulnerability: Insecure Transport | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| languages: | |
| - java | |
| pattern-either: | |
| - pattern: '(org.apache.commons.net.ftp.FTPClient $FTPCLIENT).connect(...); | |
| ' | |
| - pattern: 'URL $URL = new URL("=~/^[fF][tT][pP]://.*/"); | |
| ... | |
| URLConnection $CONN = $URL.openConnection(...); | |
| ' | |
| - id: java_crypto_rule-SpringHTTPRequestRestTemplate | |
| message: "This rule detects instances where Java Spring's RestTemplate API sends\ | |
| \ \nrequests to non-secure (http://) URLs. Sending data over HTTP is vulnerable\ | |
| \ \nas it does not use TLS encryption, exposing the data to interception, \nmodification,\ | |
| \ or redirection by attackers. \n\nTo mitigate this vulnerability, modify the\ | |
| \ request URLs to use HTTPS instead, \nwhich ensures that the data is encrypted\ | |
| \ during transit and prevents from\nMITM attacks. \n\nSecure Code Example:\n```\n\ | |
| public void safe(Object obj) throws Exception {\n RestTemplate restTemplate =\ | |
| \ new RestTemplate();\n restTemplate.put(URI.create(\"https://example.com\"),\ | |
| \ obj);\n}\n``` \n" | |
| severity: WARNING | |
| metadata: | |
| likelihood: MEDIUM | |
| impact: MEDIUM | |
| confidence: MEDIUM | |
| category: security | |
| cwe: CWE-319 | |
| shortDescription: Cleartext transmission of sensitive information | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| references: | |
| - https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html#delete-java.lang.String-java.util.Map- | |
| - https://www.baeldung.com/rest-template | |
| subcategory: | |
| - vuln | |
| technology: | |
| - spring | |
| vulnerability: Insecure Transport | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Mishandled Sensitive Information | |
| languages: | |
| - java | |
| mode: taint | |
| pattern-sources: | |
| - pattern: '"=~/^http:\/\/.+/i" | |
| ' | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: '(org.springframework.web.client.RestTemplate $RESTTEMP).$FUNC($URL, | |
| ...); | |
| ' | |
| - focus-metavariable: $URL | |
| - metavariable-regex: | |
| metavariable: $FUNC | |
| regex: (delete|doExecute|exchange|getForEntity|getForObject|headForHeaders|optionsForAllow|patchForObject|postForEntity|postForLocation|postForObject|put|execute) | |
| - id: java_crypto_rule-HttpGetHTTPRequest | |
| languages: | |
| - java | |
| mode: taint | |
| pattern-sources: | |
| - pattern: '"=~/^http:\/\/.+/i" | |
| ' | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: '$R = new org.apache.http.client.methods.HttpGet($PROT); | |
| ... | |
| $CLIENT. ... .execute($R, ...); | |
| ' | |
| - focus-metavariable: $PROT | |
| message: "Detected an HTTP GET request sent via HttpGet. Sending data over HTTP\ | |
| \ can\nexpose sensitive information to interception or modification by attackers,\n\ | |
| as HTTP does not encrypt the data transmitted. It is critical to use\nHTTPS, which\ | |
| \ encrypts the communication, to protect the confidentiality\nand integrity of\ | |
| \ data in transit.\n\nTo mitigate the issue, ensure all data transmitted between\ | |
| \ the client and \nserver is sent over HTTPS. Update all HTTP URLs to HTTPS and\ | |
| \ configure your \nserver to redirect HTTP requests to HTTPS. Additionally, implement\ | |
| \ HSTS \n(HTTP Strict Transport Security) to enforce secure connections.\n\nSecure\ | |
| \ Code Example:\n```\nprivate static void safe() throws IOException {\n HttpGet\ | |
| \ httpGet = new HttpGet(\"https://example.com\");\n HttpClients.createDefault().execute(httpGet);\n\ | |
| }\n```\n" | |
| severity: WARNING | |
| metadata: | |
| likelihood: MEDIUM | |
| impact: MEDIUM | |
| confidence: MEDIUM | |
| cwe: CWE-319 | |
| category: security | |
| shortDescription: Cleartext transmission of sensitive information | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| references: | |
| - https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URLConnection.html | |
| - https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URL.html#openConnection() | |
| subcategory: | |
| - vuln | |
| technology: | |
| - java | |
| vulnerability: Insecure Transport | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Mishandled Sensitive Information | |
| - id: java_crypto_rule-GCMNonceReuse | |
| metadata: | |
| shortDescription: Reuse of cryptographic initialization vector | |
| category: security | |
| cwe: CWE-323 | |
| technology: | |
| - java | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| languages: | |
| - java | |
| message: "GCM is a mode of operation for symmetric-key cryptographic block ciphers.\ | |
| \ GCM allows the usage of\nan initialization vector or nonce used to provide the\ | |
| \ initial state. The IV is an arbitrary number \nthat can be used just once in\ | |
| \ a cryptographic communication. Re use of initialization vectors \nnullifies\ | |
| \ their usage, as the initial state of all GCMs with the same vector will effectively\ | |
| \ be\nthe same.\n\nInstead of hard coding an initialization vector, it is recommended\ | |
| \ to use nextBytes() method from\njava.security.SecureRandom. This generates a\ | |
| \ user specified number of random bytes.\n\nExample using `java.security.SecureRandom`:\n\ | |
| ```\nCipher cipher = Cipher.getInstance(\"AES/GCM/NoPadding\");\nSecretKeySpec\ | |
| \ keySpec = new SecretKeySpec(secretKey.getEncoded(), \"AES\");\n\n// Generate\ | |
| \ a new, random IV for each encryption operation\nSecureRandom secureRandom =\ | |
| \ new SecureRandom();\n// GCM standard recommends a 12-byte (96-bit) IV\nbyte[]\ | |
| \ iv = new byte[12];\nsecureRandom.nextBytes(iv);\n\nGCMParameterSpec gcmParameterSpec\ | |
| \ = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);\ncipher.init(Cipher.ENCRYPT_MODE,\ | |
| \ keySpec, gcmParameterSpec);\n```\n\nFor more information on Java Cryptography\ | |
| \ see:\nhttps://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html\n" | |
| mode: taint | |
| pattern-sources: | |
| - pattern-either: | |
| - pattern: new byte[]{...}; | |
| - pattern: $STRING.getBytes(); | |
| pattern-sinks: | |
| - pattern: new GCMParameterSpec(...,$NONCE, ...) | |
| severity: WARNING | |
| - id: java_crypto_rule_JwtNoneAlgorithm | |
| message: 'Detected use of the ''none'' algorithm in a JWT token. The ''none'' | |
| algorithm assumes the integrity of the token has already been verified. | |
| This would allow a malicious actor to forge a JWT token that will | |
| automatically be verified. Do not explicitly use the ''none'' algorithm. | |
| Instead, use an algorithm such as ''HS256''. | |
| For more information on how to securely use JWT please see OWASP: | |
| - https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html | |
| ' | |
| metadata: | |
| shortDescription: Use of a broken or risky cryptographic algorithm | |
| cwe: CWE-327 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ | |
| asvs: | |
| section: 'V3: Session Management Verification Requirements' | |
| control_id: 3.5.3 Insecue Stateless Session Tokens | |
| control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V3-Session-management.md#v35-token-based-session-management | |
| version: '4' | |
| category: security | |
| technology: | |
| - jwt | |
| confidence: LOW | |
| references: | |
| - https://owasp.org/Top10/A02_2021-Cryptographic_Failures | |
| subcategory: | |
| - audit | |
| likelihood: LOW | |
| impact: MEDIUM | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Cryptographic Issues | |
| security-severity: CRITICAL | |
| languages: | |
| - java | |
| severity: ERROR | |
| pattern-either: | |
| - patterns: | |
| - pattern: 'io.jsonwebtoken.Jwts.builder() | |
| ' | |
| - pattern-not-inside: "$RETURNTYPE $FUNC(...) {\n ...\n $JWTS.signWith(...);\n\ | |
| \ ...\n}\n" | |
| - pattern: '$J.sign(com.auth0.jwt.algorithms.Algorithm.none()) | |
| ' | |
| - pattern: 'new com.nimbusds.jose.PlainHeader(...); | |
| ' | |
| - pattern: 'new com.nimbusds.jose.PlainHeader.Builder(). ... .build(); | |
| ' | |
| - id: java_crypto_rule-TelnetRequest | |
| message: "Checks for attempts to connect through telnet. Telnet is an outdated\n\ | |
| protocol that transmits all data, including sensitive information like\npasswords,\ | |
| \ in clear text. This exposes it to interception and\neavesdropping on unsecured\ | |
| \ networks.\n\nTo mitigate this issue, replace Telnet usage with more secure protocols\ | |
| \ \nsuch as SSH (Secure Shell), which provides encrypted communication. Use \n\ | |
| the SSH functionality provided by libraries like JSch or Apache MINA SSHD \nfor\ | |
| \ secure data transmission.\n\nSecure Code Example:\n```\nimport com.jcraft.jsch.JSch;\n\ | |
| import com.jcraft.jsch.Session;\n\npublic class SecureConnector {\n public\ | |
| \ static void main(String[] args) {\n try {\n JSch jsch = new\ | |
| \ JSch();\n Session session = jsch.getSession(\"username\", \"hostname\"\ | |
| , 22);\n session.setPassword(\"password\");\n session.setConfig(\"\ | |
| StrictHostKeyChecking\", \"no\");\n session.connect();\n \ | |
| \ System.out.println(\"Connected securely.\");\n } catch (Exception e)\ | |
| \ {\n System.err.println(\"Secure connection failed: \" + e.getMessage());\n\ | |
| \ }\n }\n}\n```\n" | |
| severity: WARNING | |
| metadata: | |
| likelihood: MEDIUM | |
| impact: MEDIUM | |
| confidence: MEDIUM | |
| category: security | |
| cwe: CWE-319 | |
| shortDescription: Cleartext transmission of sensitive information | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| references: | |
| - https://commons.apache.org/proper/commons-net/javadocs/api-3.6/org/apache/commons/net/telnet/TelnetClient.html | |
| subcategory: | |
| - vuln | |
| technology: | |
| - java | |
| vulnerability: Insecure Transport | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Mishandled Sensitive Information | |
| languages: | |
| - java | |
| pattern: '(org.apache.commons.net.telnet.TelnetClient $TELNETCLIENT).connect(...); | |
| ' | |
| - id: java_crypto_rule-UnirestHTTPRequest | |
| languages: | |
| - java | |
| patterns: | |
| - pattern: 'Unirest.$METHOD("=~/[hH][tT][tT][pP]://.*/") | |
| ' | |
| message: "This application uses the Unirest library to send\nnetwork requests to\ | |
| \ URLs starting with 'http://'. Communicating over HTTP\nis considered insecure\ | |
| \ because it does not encrypt traffic with TLS\n(Transport Layer Security), exposing\ | |
| \ data to potential interception or\nmanipulation by attackers.\n\nTo mitigate\ | |
| \ the issue, modify the request URL to begin with 'https://' \ninstead of 'http://'.\ | |
| \ Using HTTPS ensures that the data is encrypted and \nsecure during transmission.\ | |
| \ Review all instances where HTTP is used and \nupdate them to use HTTPS to prevent\ | |
| \ security risks.\n\nSecure Code Example:\n```\nimport kong.unirest.core.Unirest;\n\ | |
| \npublic void safe() {\n Unirest.get(\"https://httpbin.org\")\n .queryString(\"\ | |
| fruit\", \"apple\")\n .queryString(\"droid\", \"R2D2\")\n .asString();\n\ | |
| }\n```\n" | |
| severity: WARNING | |
| metadata: | |
| likelihood: MEDIUM | |
| impact: MEDIUM | |
| confidence: MEDIUM | |
| category: security | |
| cwe: CWE-319 | |
| shortDescription: Cleartext transmission of sensitive information | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| references: | |
| - https://kong.github.io/unirest-java/#requests | |
| subcategory: | |
| - vuln | |
| technology: | |
| - unirest | |
| vulnerability: Insecure Transport | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Mishandled Sensitive Information | |
| - id: java_crypto_rule-SocketRequestUnsafeProtocols | |
| message: "This code establishes a network connection using an insecure protocol\n\ | |
| (HTTP, FTP, or Telnet). These protocols transmit data in cleartext, which\ncan\ | |
| \ be intercepted and read by malicious actors. This exposure of\nsensitive information\ | |
| \ violates security best practices and can lead to\ndata breaches.\n\nTo mitigate\ | |
| \ the vulnerability, consider using secure protocols that encrypt\nthe transmission\ | |
| \ of data. For web traffic, replace HTTP with HTTPS, which\nuses SSL/TLS to protect\ | |
| \ the data in transit. For file transfers, use SFTP\nor FTPS instead of FTP. For\ | |
| \ remote terminal access, use SSH instead of Telnet.\n\nSecure Code Example:\n\ | |
| ```\npublic void safe() {\n BufferedReader in = null;\n PrintWriter out = null;\n\ | |
| \ Socket pingSocket = null;\n try{\n pingSocket = new Socket(\"ssh://example.com\"\ | |
| , 22);\n out = new PrintWriter(pingSocket.getOutputStream(), true);\n \ | |
| \ in = new BufferedReader(new InputStreamReader(pingSocket.getInputStream()));\n\ | |
| \ out.println(\"ping\");\n System.out.println(in.readLine());\n }\ | |
| \ catch (Exception e) {\n e.printStackTrace();\n } finally {\n \ | |
| \ try {\n if (in != null) in.close();\n if (pingSocket != null)\ | |
| \ pingSocket.close();\n } catch (IOException e) {\n System.out.println(\"\ | |
| Failed to close resources: \" + e.getMessage());\n }\n }\n}\n```\n" | |
| severity: WARNING | |
| metadata: | |
| likelihood: MEDIUM | |
| impact: MEDIUM | |
| confidence: LOW | |
| category: security | |
| cwe: CWE-319 | |
| shortDescription: Cleartext transmission of sensitive information | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| references: | |
| - https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html | |
| technology: | |
| - java | |
| vulnerability: Insecure Transport | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Mishandled Sensitive Information | |
| languages: | |
| - java | |
| pattern-either: | |
| - pattern: '$SOCKET = new java.net.Socket("=~/^ftp://.+/i", ...); | |
| ' | |
| - pattern: '$SOCKET = new java.net.Socket("=~/^http://.+/i", ...); | |
| ' | |
| - pattern: '$SOCKET = new java.net.Socket("=~/^telnet://.+/i", ...); | |
| ' | |
| - patterns: | |
| - pattern: '$SOCKET = new java.net.Socket("...", $PORT); | |
| ' | |
| - metavariable-comparison: | |
| comparison: $PORT in [23,21,80] | |
| metavariable: $PORT | |
| - id: java_crypto_rule-DisallowOldTLSVersion | |
| languages: | |
| - java | |
| patterns: | |
| - pattern: $VALUE. ... .setProperty("jdk.tls.client.protocols", "$PATTERNS"); | |
| - metavariable-pattern: | |
| metavariable: $PATTERNS | |
| language: generic | |
| patterns: | |
| - pattern-either: | |
| - pattern-regex: ^(.*TLSv1|.*SSLv.*)$ | |
| - pattern-regex: ^(.*TLSv1,.*|.*TLSv1.1.*) | |
| message: "This application sets the `jdk.tls.client.protocols` system property to\n\ | |
| include insecure TLS or SSL versions (SSLv3, TLSv1, TLSv1.1), which are\ndeprecated\ | |
| \ due to serious security vulnerabilities like POODLE attacks and\nsusceptibility\ | |
| \ to man-in-the-middle attacks. Continuing to use these\nprotocols can expose\ | |
| \ data to interception or manipulation. \n\nTo mitigate the issue, upgrade to\ | |
| \ TLSv1.2 or higher, which provide stronger \nencryption and improved security.\ | |
| \ Refrain from using any SSL versions as they \nare entirely deprecated.\n\nSecure\ | |
| \ Code Example:\n```\npublic void safe() {\n java.lang.System.setProperty(\"\ | |
| jdk.tls.client.protocols\", \"TLSv1.3\");\n}\n```\n" | |
| severity: WARNING | |
| metadata: | |
| likelihood: MEDIUM | |
| impact: MEDIUM | |
| confidence: MEDIUM | |
| shortDescription: Inadequate encryption strength | |
| category: security | |
| cwe: CWE-326 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| references: | |
| - https://stackoverflow.com/questions/26504653/is-it-possible-to-disable-sslv3-for-all-java-applications | |
| subcategory: | |
| - vuln | |
| technology: | |
| - java | |
| vulnerability: Insecure Transport | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Mishandled Sensitive Information | |
| - id: java_crypto_rule_JwtDecodeWithoutVerify | |
| languages: | |
| - java | |
| message: Detected the decoding of a JWT token without a verify step. JWT tokens | |
| must be verified before use, otherwise the token's integrity is unknown. This | |
| means a malicious actor could forge a JWT token with any claims. Call '.verify()' | |
| before using the token. | |
| metadata: | |
| shortDescription: Improper verification of cryptographic signature | |
| category: security | |
| cwe: CWE-347 | |
| owasp: | |
| - A8:2017-Insecure Deserialization | |
| - A08:2021-Software and Data Integrity Failures | |
| source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ | |
| technology: jwt | |
| confidence: MEDIUM | |
| references: https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures | |
| subcategory: vuln | |
| likelihood: LOW | |
| impact: HIGH | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: Improper Authentication | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| patterns: | |
| - pattern: 'com.auth0.jwt.JWT.decode(...); | |
| ' | |
| - pattern-not-inside: "class $CLASS {\n ...\n $RETURNTYPE $FUNC (...) {\n ...\n\ | |
| \ $VERIFIER.verify(...);\n ...\n }\n}" | |
| - id: java_crypto_rule-UseOfRC2 | |
| languages: | |
| - java | |
| pattern-either: | |
| - pattern: 'javax.crypto.Cipher.getInstance("RC2") | |
| ' | |
| - patterns: | |
| - pattern-inside: "class $CLS{\n ...\n String $ALG = \"RC2\";\n ...\n}\n" | |
| - pattern: 'javax.crypto.Cipher.getInstance($ALG); | |
| ' | |
| message: "Use of RC2, a deprecated cryptographic algorithm vulnerable to related-key\n\ | |
| attacks, was detected. Modern cryptographic standards recommend the\nadoption\ | |
| \ of algorithms that integrate message integrity to ensure the\nciphertext remains\ | |
| \ unaltered.\n\nTo mitigate the issue, use any of the below algorithms instead:\n\ | |
| 1. `ChaCha20Poly1305` - Preferred for its simplicity and speed, suitable for \n\ | |
| environments where cryptographic acceleration is absent.\n2. `AES-256-GCM` - Highly\ | |
| \ recommended when hardware support is available, \ndespite being somewhat slower\ | |
| \ than `ChaCha20Poly1305`. It is crucial to avoid \nnonce reuse with AES-256-GCM\ | |
| \ to prevent security compromises.\n\nSecure code example using `ChaCha20Poly1305`\ | |
| \ in Java:\n```\npublic void encryptAndDecrypt() throws Exception {\n SecureRandom\ | |
| \ random = new SecureRandom();\n byte[] secretKey = new byte[32]; // 256-bit\ | |
| \ key\n byte[] nonce = new byte[12]; // 96-bit nonce\n random.nextBytes(secretKey);\n\ | |
| \ random.nextBytes(nonce);\n\n Cipher cipher = Cipher.getInstance(\"ChaCha20-Poly1305/None/NoPadding\"\ | |
| );\n SecretKeySpec keySpec = new SecretKeySpec(secretKey, \"ChaCha20\");\n\ | |
| \ GCMParameterSpec spec = new GCMParameterSpec(128, nonce);\n\n cipher.init(Cipher.ENCRYPT_MODE,\ | |
| \ keySpec, spec);\n byte[] plaintext = \"Secret text\".getBytes(StandardCharsets.UTF_8);\n\ | |
| \ byte[] ciphertext = cipher.doFinal(plaintext);\n System.out.println(\"\ | |
| Encrypted: \" + Base64.getEncoder().encodeToString(ciphertext));\n\n cipher.init(Cipher.DECRYPT_MODE,\ | |
| \ keySpec, spec);\n byte[] decrypted = cipher.doFinal(ciphertext);\n System.out.println(\"\ | |
| Decrypted: \" + new String(decrypted, StandardCharsets.UTF_8));\n}\n```\nFor more\ | |
| \ on Java Cryptography, refer:\nhttps://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html\n" | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Use of a broken or risky cryptographic algorithm | |
| category: security | |
| cwe: CWE-327 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| technology: | |
| - java | |
| security-severity: MEDIUM | |
| references: | |
| - https://owasp.org/Top10/A02_2021-Cryptographic_Failures | |
| subcategory: | |
| - vuln | |
| likelihood: MEDIUM | |
| impact: MEDIUM | |
| confidence: HIGH | |
| - id: java_crypto_rule-SpringFTPRequest | |
| languages: | |
| - java | |
| mode: taint | |
| pattern-sources: | |
| - pattern: '"=~/^ftp://.+/i" | |
| ' | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: '(org.springframework.integration.ftp.session.DefaultFtpSessionFactory | |
| $SF).setHost($URL); | |
| ' | |
| - focus-metavariable: $URL | |
| message: "This pattern detects configurations where the Spring Integration FTP plugin\ | |
| \ \nis used to set up connections to FTP servers. FTP is an insecure protocol\ | |
| \ \nthat transmits data, including potentially sensitive information, in plaintext.\ | |
| \ \nThis can expose personal identifiable information (PII) or other sensitive\ | |
| \ data \nto interception by attackers during transmission. \n\nTo mitigate the\ | |
| \ vulnerability, switch to a secure protocol such as SFTP or FTPS \nthat encrypts\ | |
| \ the connection to prevent data exposure. Ensure that any method \nused to set\ | |
| \ the host for an FTP session does not use plaintext FTP. \n\nSecure Code Example:\n\ | |
| ```\npublic SessionFactory<FTPFile> safe(FtpSessionFactoryProperties properties)\ | |
| \ {\n DefaultFtpSessionFactory ftpSessionFactory = new DefaultFtpSessionFactory();\n\ | |
| \ ftpSessionFactory.setHost(\"sftp://example.com\");\n ftpSessionFactory.setPort(properties.getPort());\n\ | |
| \ ftpSessionFactory.setUsername(properties.getUsername());\n ftpSessionFactory.setPassword(properties.getPassword());\n\ | |
| \ ftpSessionFactory.setClientMode(properties.getClientMode().getMode());\n return\ | |
| \ ftpSessionFactory;\n}\n```\n" | |
| severity: WARNING | |
| metadata: | |
| likelihood: MEDIUM | |
| impact: MEDIUM | |
| confidence: MEDIUM | |
| cwe: CWE-319 | |
| category: security | |
| shortDescription: Cleartext transmission of sensitive information | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| references: | |
| - https://docs.spring.io/spring-integration/api/org/springframework/integration/ftp/session/AbstractFtpSessionFactory.html#setClientMode-int- | |
| subcategory: | |
| - vuln | |
| technology: | |
| - spring | |
| vulnerability: Insecure Transport | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Mishandled Sensitive Information | |
| - id: java_crypto_rule-UseOfRC4 | |
| languages: | |
| - java | |
| pattern-either: | |
| - pattern: 'javax.crypto.Cipher.getInstance("RC4") | |
| ' | |
| - patterns: | |
| - pattern-inside: "class $CLS{\n ...\n String $ALG = \"RC4\";\n ...\n}\n" | |
| - pattern: 'javax.crypto.Cipher.getInstance($ALG); | |
| ' | |
| message: "Use of RC4 was detected. RC4 is vulnerable to several types of attacks,\n\ | |
| including stream cipher attacks where attackers can recover plaintexts by\nanalyzing\ | |
| \ a large number of encrypted messages, and bit-flipping attacks\nthat can alter\ | |
| \ messages without knowing the encryption key.\n\nTo mitigate the issue, use any\ | |
| \ of the below algorithms instead:\n1. `ChaCha20Poly1305` - Preferred for its\ | |
| \ simplicity and speed, suitable for \nenvironments where cryptographic acceleration\ | |
| \ is absent.\n2. `AES-256-GCM` - Highly recommended when hardware support is available,\ | |
| \ \ndespite being somewhat slower than `ChaCha20Poly1305`. It is crucial to avoid\ | |
| \ \nnonce reuse with AES-256-GCM to prevent security compromises.\n\nSecure code\ | |
| \ example using `ChaCha20Poly1305` in Java:\n```\npublic void encryptAndDecrypt()\ | |
| \ throws Exception {\n SecureRandom random = new SecureRandom();\n byte[]\ | |
| \ secretKey = new byte[32]; // 256-bit key\n byte[] nonce = new byte[12];\ | |
| \ // 96-bit nonce\n random.nextBytes(secretKey);\n random.nextBytes(nonce);\n\ | |
| \n Cipher cipher = Cipher.getInstance(\"ChaCha20-Poly1305/None/NoPadding\"\ | |
| );\n SecretKeySpec keySpec = new SecretKeySpec(secretKey, \"ChaCha20\");\n\ | |
| \ GCMParameterSpec spec = new GCMParameterSpec(128, nonce);\n\n cipher.init(Cipher.ENCRYPT_MODE,\ | |
| \ keySpec, spec);\n byte[] plaintext = \"Secret text\".getBytes(StandardCharsets.UTF_8);\n\ | |
| \ byte[] ciphertext = cipher.doFinal(plaintext);\n System.out.println(\"\ | |
| Encrypted: \" + Base64.getEncoder().encodeToString(ciphertext));\n\n cipher.init(Cipher.DECRYPT_MODE,\ | |
| \ keySpec, spec);\n byte[] decrypted = cipher.doFinal(ciphertext);\n System.out.println(\"\ | |
| Decrypted: \" + new String(decrypted, StandardCharsets.UTF_8));\n}\n```\nFor more\ | |
| \ information, refer:\nhttps://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions\n" | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Use of a broken or risky cryptographic algorithm | |
| category: security | |
| cwe: CWE-327 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| technology: | |
| - java | |
| security-severity: MEDIUM | |
| references: | |
| - https://owasp.org/Top10/A02_2021-Cryptographic_Failures | |
| - https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html | |
| subcategory: | |
| - vuln | |
| likelihood: MEDIUM | |
| impact: MEDIUM | |
| confidence: HIGH | |
| - id: java_crypto_rule-TLSUnsafeRenegotiation | |
| languages: | |
| - java | |
| patterns: | |
| - pattern: 'java.lang.System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", | |
| $TRUE); | |
| ' | |
| - metavariable-pattern: | |
| metavariable: $TRUE | |
| pattern-either: | |
| - pattern: 'true | |
| ' | |
| - pattern: '"true" | |
| ' | |
| - pattern: 'Boolean.TRUE | |
| ' | |
| message: "This code enables unsafe renegotiation in SSL/TLS connections, which is\n\ | |
| vulnerable to man-in-the-middle attacks. In such attacks, an attacker\ncould inject\ | |
| \ chosen plaintext at the beginning of the secure\ncommunication, potentially\ | |
| \ compromising the security of data transmission. If \nexploited, this vulnerability\ | |
| \ can lead to unauthorized access to sensitive \ndata, data manipulation, and\ | |
| \ potentially full system compromise depending on \nthe data and operations protected\ | |
| \ by the TLS session.\n\nTo mitigate this vulnerability, disable unsafe renegotiation\ | |
| \ in the Java \napplication. Ensure that only secure renegotiation is allowed\ | |
| \ by setting the \nsystem property `sun.security.ssl.allowUnsafeRenegotiation`\ | |
| \ to `false`. \n\nSecure code example:\n```\npublic void safe() {\n java.lang.System.setProperty(\"\ | |
| sun.security.ssl.allowUnsafeRenegotiation\", false);\n}\n```\n" | |
| severity: WARNING | |
| metadata: | |
| likelihood: LOW | |
| impact: MEDIUM | |
| confidence: MEDIUM | |
| category: security | |
| cwe: CWE-319 | |
| shortDescription: Cleartext transmission of sensitive information | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| references: | |
| - https://www.oracle.com/java/technologies/javase/tlsreadme.html | |
| subcategory: | |
| - vuln | |
| technology: | |
| - java | |
| vulnerability: Insecure Transport | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Mishandled Sensitive Information | |
| - id: java_crypto_rule-HttpComponentsRequest | |
| message: "Detected an HTTP GET request sent via Apache HTTP Components. Sending\ | |
| \ data\nover HTTP can expose sensitive information to interception or modification\n\ | |
| by attackers, as HTTP does not encrypt the data transmitted. It is critical\n\ | |
| to use HTTPS, which encrypts the communication, to protect the confidentiality\n\ | |
| and integrity of data in transit.\n\nTo mitigate the issue, ensure all data transmitted\ | |
| \ between the client and \nserver is sent over HTTPS. Update all HTTP URLs to\ | |
| \ HTTPS and configure your \nserver to redirect HTTP requests to HTTPS. Additionally,\ | |
| \ implement HSTS \n(HTTP Strict Transport Security) to enforce secure connections.\n\ | |
| Secure Code Example:\n```\nprivate static void safe() {\n CloseableHttpClient\ | |
| \ httpclient = HttpClients.createDefault();\n CloseableHttpResponse response\ | |
| \ = httpclient.execute(new HttpPost(\"https://example.com\"));\n}\n```\n" | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Cleartext transmission of sensitive information | |
| security-severity: MEDIUM | |
| likelihood: MEDIUM | |
| impact: MEDIUM | |
| confidence: MEDIUM | |
| category: security | |
| cwe: CWE-319 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| references: | |
| - https://hc.apache.org/httpcomponents-client-ga/quickstart.html | |
| subcategory: | |
| - vuln | |
| technology: | |
| - java | |
| vulnerability: Insecure Transport | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Mishandled Sensitive Information | |
| languages: | |
| - java | |
| mode: taint | |
| pattern-sources: | |
| - pattern: '"=~/^http://.+/i" | |
| ' | |
| pattern-sinks: | |
| - pattern: (org.apache.http.impl.client.CloseableHttpClient $A).execute($HTTPREQ); | |
| - id: java_crypto_rule-HTTPUrlConnectionHTTPRequest | |
| message: "Detected an HTTP request sent via HttpURLConnection or URLConnection.\n\ | |
| This could lead to sensitive information being sent over an insecure \nchannel,\ | |
| \ as HTTP does not encrypt data. Transmitting data over HTTP \nexposes it to potential\ | |
| \ interception by attackers, risking data \nintegrity and confidentiality. Using\ | |
| \ HTTP for transmitting sensitive \ndata such as passwords, personal information,\ | |
| \ or financial details can \nlead to information disclosure.\n\nTo mitigate the\ | |
| \ issue, switch to HTTPS to ensure all data transmitted \nis securely encrypted.\ | |
| \ This helps protect against eavesdropping and \nman-in-the-middle attacks. Modify\ | |
| \ the URL in your code from HTTP to \nHTTPS and ensure the server supports HTTPS.\n\ | |
| \nSecure Code Example:\n```\nprivate static void safe() {\n try {\n \ | |
| \ URL url = new URL(\"https://example.com/api/data\"); // Changed to HTTPS\n \ | |
| \ HttpURLConnection con = (HttpURLConnection) url.openConnection();\n \ | |
| \ con.setRequestMethod(\"GET\");\n\n int status = con.getResponseCode();\n\ | |
| \ if (status == HttpURLConnection.HTTP_OK) { \n BufferedReader\ | |
| \ in = new BufferedReader(new InputStreamReader(con.getInputStream()));\n \ | |
| \ String inputLine;\n StringBuilder response = new StringBuilder();\n\ | |
| \ while ((inputLine = in.readLine()) != null) {\n response.append(inputLine);\n\ | |
| \ }\n in.close();\n System.out.println(\"Response:\ | |
| \ \" + response.toString());\n } else {\n System.out.println(\"\ | |
| HTTP error code: \" + status);\n }\n con.disconnect();\n } catch\ | |
| \ (Exception e) {\n e.printStackTrace();\n }\n}\n```\n" | |
| severity: WARNING | |
| metadata: | |
| likelihood: MEDIUM | |
| impact: MEDIUM | |
| confidence: MEDIUM | |
| shortDescription: Cleartext transmission of sensitive information | |
| category: security | |
| cwe: CWE-319 | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| references: | |
| - https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URLConnection.html | |
| - https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URL.html#openConnection() | |
| subcategory: | |
| - vuln | |
| technology: | |
| - java | |
| vulnerability: Insecure Transport | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Mishandled Sensitive Information | |
| languages: | |
| - java | |
| patterns: | |
| - pattern: '"=~/[Hh][Tt][Tt][Pp]://.*/" | |
| ' | |
| - pattern-either: | |
| - pattern-inside: 'URL $URL = new URL ("=~/[Hh][Tt][Tt][Pp]://.*/", ...); | |
| ... | |
| $CON = (HttpURLConnection) $URL.openConnection(...); | |
| ... | |
| $CON.$FUNC(...); | |
| ' | |
| - pattern-inside: 'URL $URL = new URL ("=~/[Hh][Tt][Tt][Pp]://.*/", ...); | |
| ... | |
| $CON = $URL.openConnection(...); | |
| ... | |
| $CON.$FUNC(...); | |
| ' | |
| - id: java_xxe_rule-ExternalGeneralEntitiesTrue | |
| severity: WARNING | |
| languages: | |
| - java | |
| metadata: | |
| cwe: CWE-611 | |
| shortDescription: Improper restriction of XML external entity reference | |
| owasp: | |
| - A4:2017-XML External Entities (XXE) | |
| - A05:2021-Security Misconfiguration | |
| security-severity: MEDIUM | |
| references: | |
| - https://semgrep.dev/blog/2022/xml-security-in-java | |
| - https://semgrep.dev/docs/cheat-sheets/java-xxe/ | |
| - https://blog.sonarsource.com/secure-xml-processor | |
| category: security | |
| technology: | |
| - java | |
| - xml | |
| cwe2022-top25: 'true' | |
| cwe2021-top25: 'true' | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - XML Injection | |
| message: "This rule identifies instances in the code where an XML parser is\nconfigured\ | |
| \ to allow external general entities. Allowing the processing \nof external general\ | |
| \ entities without proper validation or restriction \ncan lead to XXE attacks.\ | |
| \ An attacker can craft an XML document to \nreference sensitive files on the\ | |
| \ server or external systems under the \nattacker's control, leading to data disclosure,\ | |
| \ denial of service, or \nserver-side request forgery (SSRF).\n\nTo mitigate this\ | |
| \ vulnerability, the application should be configured to \ndisable the use of\ | |
| \ external general entities in XML parsing. This can be \nachieved by setting\ | |
| \ the feature \n\"http://xml.org/sax/features/external-general-entities\" to false.\n\ | |
| \nSecure Code Example:\n```\nclass GoodSAXBuilder {\n public void GoodSAXBuilder1()\ | |
| \ throws ParserConfigurationException {\n SAXBuilder saxBuilder = new SAXBuilder();\n\ | |
| \ saxBuilder.setFeature(\"http://xml.org/sax/features/external-general-entities\"\ | |
| , false);\n }\n}\n```\n" | |
| pattern: '$PARSER.setFeature("http://xml.org/sax/features/external-general-entities", | |
| true); | |
| ' | |
| - id: java_xxe_rule-DocumentBuilderFactoryDisallowDoctypeDeclMissing | |
| severity: WARNING | |
| languages: | |
| - java | |
| metadata: | |
| cwe: CWE-611 | |
| shortDescription: Improper restriction of XML external entity reference | |
| owasp: | |
| - A4:2017-XML External Entities (XXE) | |
| - A05:2021-Security Misconfiguration | |
| references: | |
| - https://semgrep.dev/blog/2022/xml-security-in-java | |
| - https://semgrep.dev/docs/cheat-sheets/java-xxe/ | |
| - https://blog.sonarsource.com/secure-xml-processor | |
| - https://xerces.apache.org/xerces2-j/features.html | |
| category: security | |
| security-severity: MEDIUM | |
| technology: | |
| - java | |
| - xml | |
| cwe2022-top25: 'true' | |
| cwe2021-top25: 'true' | |
| subcategory: | |
| - vuln | |
| likelihood: LOW | |
| impact: HIGH | |
| confidence: HIGH | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - XML Injection | |
| message: "DOCTYPE declarations are enabled for this DocumentBuilderFactory. Enabling\ | |
| \ \nDOCTYPE declarations without proper restrictions can make your application\ | |
| \ \nvulnerable to XML External Entity (XXE) attacks. \nIn an XXE attack, an attacker\ | |
| \ can exploit the processing of external entity \nreferences within an XML document\ | |
| \ to access internal files, conduct \ndenial-of-service attacks, or SSRF (Server\ | |
| \ Side Request Forgery), potentially \nleading to sensitive information disclosure\ | |
| \ or system compromise. \n\nTo mitigate this vulnerability, disable this by setting\ | |
| \ the\nfeature \"http://apache.org/xml/features/disallow-doctype-decl\" to true.\n\ | |
| Alternatively, allow DOCTYPE declarations and only prohibit external\nentities\ | |
| \ declarations. This can be done by setting the features\n\"http://xml.org/sax/features/external-general-entities\"\ | |
| \ and\n\"http://xml.org/sax/features/external-parameter-entities\" to false.\n\ | |
| \nSecure Code Example (You can do either of the following):\n```\npublic void\ | |
| \ GoodDocumentBuilderFactory() throws ParserConfigurationException {\n DocumentBuilderFactory\ | |
| \ dbf = DocumentBuilderFactory.newInstance();\n dbf.setFeature(\"http://apache.org/xml/features/disallow-doctype-decl\"\ | |
| , true);\n dbf.newDocumentBuilder();\n}\n\npublic void GoodDocumentBuilderFactory2()\ | |
| \ throws ParserConfigurationException {\n DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\n\ | |
| \ dbf.setFeature(\"http://xml.org/sax/features/external-parameter-entities\"\ | |
| , false);\n dbf.setFeature(\"http://xml.org/sax/features/external-general-entities\"\ | |
| , false);\n dbf.newDocumentBuilder();\n}\n```\n" | |
| mode: taint | |
| pattern-sources: | |
| - by-side-effect: true | |
| patterns: | |
| - pattern: '$FACTORY | |
| ' | |
| - pattern-inside: '$FACTORY = DocumentBuilderFactory.newInstance(); | |
| ' | |
| - pattern-not-inside: "class $C {\n ...\n $V $FACTORY = DocumentBuilderFactory.newInstance();\n\ | |
| \ ...\n static {\n ...\n $FACTORY.setFeature(\"http://apache.org/xml/features/disallow-doctype-decl\"\ | |
| , true);\n ...\n }\n ...\n}\n" | |
| - pattern-not-inside: "class $C {\n ...\n $V $FACTORY = DocumentBuilderFactory.newInstance();\n\ | |
| \ ...\n static {\n ...\n $FACTORY.setFeature(\"http://xml.org/sax/features/external-parameter-entities\"\ | |
| , false);\n ...\n $FACTORY.setFeature(\"http://xml.org/sax/features/external-general-entities\"\ | |
| , false);\n ...\n }\n ...\n}\n" | |
| - pattern-not-inside: "class $C {\n ...\n $V $FACTORY = DocumentBuilderFactory.newInstance();\n\ | |
| \ ...\n static {\n ...\n $FACTORY.setFeature(\"http://xml.org/sax/features/external-general-entities\"\ | |
| , false);\n ...\n $FACTORY.setFeature(\"http://xml.org/sax/features/external-parameter-entities\"\ | |
| , false);\n ...\n }\n ...\n}\n" | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: '$FACTORY.newDocumentBuilder(); | |
| ' | |
| pattern-sanitizers: | |
| - by-side-effect: true | |
| pattern-either: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: '$FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", | |
| true); | |
| ' | |
| - pattern: '$FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", | |
| false); ... $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", | |
| false); | |
| ' | |
| - pattern: '$FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", | |
| false); ... $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", | |
| false); | |
| ' | |
| - focus-metavariable: $FACTORY | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: "class $C {\n ...\n $T $M(...) {\n ...\n $FACTORY.setFeature(\"\ | |
| http://apache.org/xml/features/disallow-doctype-decl\",\n true);\n\ | |
| \ ...\n }\n ...\n}\n" | |
| - pattern-inside: "class $C {\n ...\n $T $M(...) {\n ...\n $FACTORY.setFeature(\"\ | |
| http://xml.org/sax/features/external-general-entities\", false);\n \ | |
| \ ...\n $FACTORY.setFeature(\"http://xml.org/sax/features/external-parameter-entities\"\ | |
| , false);\n ...\n }\n ...\n}\n" | |
| - pattern-inside: "class $C {\n ...\n $T $M(...) {\n ...\n $FACTORY.setFeature(\"\ | |
| http://xml.org/sax/features/external-parameter-entities\", false);\n \ | |
| \ ...\n $FACTORY.setFeature(\"http://xml.org/sax/features/external-general-entities\"\ | |
| ,false);\n ...\n }\n ...\n}\n" | |
| - pattern: $M($X) | |
| - focus-metavariable: $X | |
| - id: java_xxe_rule-DisallowDoctypeDeclFalse | |
| severity: WARNING | |
| languages: | |
| - java | |
| metadata: | |
| cwe: CWE-611 | |
| shortDescription: Improper restriction of XML external entity reference | |
| owasp: | |
| - A4:2017-XML External Entities (XXE) | |
| - A05:2021-Security Misconfiguration | |
| security-severity: MEDIUM | |
| references: | |
| - https://semgrep.dev/blog/2022/xml-security-in-java | |
| - https://semgrep.dev/docs/cheat-sheets/java-xxe/ | |
| - https://blog.sonarsource.com/secure-xml-processor | |
| - https://xerces.apache.org/xerces2-j/features.html | |
| category: security | |
| technology: | |
| - java | |
| - xml | |
| cwe2022-top25: 'true' | |
| cwe2021-top25: 'true' | |
| likelihood: LOW | |
| impact: HIGH | |
| confidence: HIGH | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - XML Injection | |
| message: "DOCTYPE declarations are enabled for $DBFACTORY. Without prohibiting\n\ | |
| external entity declarations, this is vulnerable to XML external entity\nattacks.\ | |
| \ In an XXE attack, an attacker can exploit the processing of external \nentity\ | |
| \ references within an XML document to access internal files, conduct \ndenial-of-service\ | |
| \ attacks, or SSRF (Server Side Request Forgery), potentially \nleading to sensitive\ | |
| \ information disclosure or system compromise.\n\nTo mitigate this vulnerability,\ | |
| \ disable this by setting the feature\n\"http://apache.org/xml/features/disallow-doctype-decl\"\ | |
| \ to true.\nAlternatively, allow DOCTYPE declarations and only prohibit external\n\ | |
| entities declarations. This can be done by setting the features\n\"http://xml.org/sax/features/external-general-entities\"\ | |
| \ and\n\"http://xml.org/sax/features/external-parameter-entities\" to false.\n\ | |
| \nSecure Code Example: \n``` \npublic void GoodXMLInputFactory() throws ParserConfigurationException\ | |
| \ {\n DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\n dbf.setFeature(\"\ | |
| http://apache.org/xml/features/disallow-doctype-decl\", true);\n} \n```\n" | |
| patterns: | |
| - pattern: '$DBFACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", | |
| false); | |
| ' | |
| - pattern-not-inside: "$RETURNTYPE $METHOD(...){\n ...\n $DBF.setFeature(\"http://xml.org/sax/features/external-general-entities\"\ | |
| , false);\n ...\n $DBF.setFeature(\"http://xml.org/sax/features/external-parameter-entities\"\ | |
| , false);\n ...\n}\n" | |
| - pattern-not-inside: "$RETURNTYPE $METHOD(...){\n ...\n $DBF.setFeature(\"http://xml.org/sax/features/external-parameter-entities\"\ | |
| , false);\n ...\n $DBF.setFeature(\"http://xml.org/sax/features/external-general-entities\"\ | |
| , false);\n ...\n}\n" | |
| - pattern-not-inside: "$RETURNTYPE $METHOD(...){\n ...\n $DBF.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD,\ | |
| \ \"\");\n ...\n $DBF.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, \"\ | |
| \");\n ...\n}\n" | |
| - pattern-not-inside: "$RETURNTYPE $METHOD(...){\n ...\n $DBF.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA,\ | |
| \ \"\");\n ...\n $DBF.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, \"\"\ | |
| );\n ...\n}\n" | |
| - id: java_xxe_rule-ExternalParameterEntitiesTrue | |
| severity: WARNING | |
| languages: | |
| - java | |
| metadata: | |
| cwe: CWE-611 | |
| shortDescription: Improper restriction of XML external entity reference | |
| owasp: | |
| - A4:2017-XML External Entities (XXE) | |
| - A05:2021-Security Misconfiguration | |
| security-severity: MEDIUM | |
| references: | |
| - https://semgrep.dev/blog/2022/xml-security-in-java | |
| - https://semgrep.dev/docs/cheat-sheets/java-xxe/ | |
| - https://blog.sonarsource.com/secure-xml-processor | |
| category: security | |
| technology: | |
| - java | |
| - xml | |
| cwe2022-top25: 'true' | |
| cwe2021-top25: 'true' | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - XML Injection | |
| message: "This rule identifies instances in the code where the XML parser is\nconfigured\ | |
| \ to allow external parameter entities. Enabling external\nentities in XML parsing\ | |
| \ can lead to XML External Entity (XXE) attacks,\nwhere an attacker could exploit\ | |
| \ the XML parser to read sensitive files\nfrom the server, perform denial of service\ | |
| \ (DoS) attacks, or achieve\nserver-side request forgery (SSRF). This vulnerability\ | |
| \ occurs when the\napplication processes XML input that includes external entity\ | |
| \ references\nwithin an XML document.\n\nTo mitigate this vulnerability, the application\ | |
| \ should be configured to disable \nthe use of external entities in XML parsing.\ | |
| \ This can be achieved by setting the \nfeature \"http://xml.org/sax/features/external-parameter-entities\"\ | |
| \ to false.\n\nSecure Code Example: \n``` \ntry {\n DBFactory dbFactory = DocumentBuilderFactory.newInstance();\n\ | |
| \ // Disable external entities to mitigate XXE vulnerability\n dbFactory.setFeature(\"\ | |
| http://xml.org/sax/features/external-parameter-entities\", false);\n dbFactory.setFeature(\"\ | |
| http://apache.org/xml/features/disallow-doctype-decl\", true);\n // Additional\ | |
| \ configuration for secure parsing\n dbFactory.setFeature(\"http://xml.org/sax/features/external-general-entities\"\ | |
| , false);\n dbFactory.setXIncludeAware(false);\n dbFactory.setExpandEntityReferences(false);\n\ | |
| \n // Use the configured factory to create a document builder\n DocumentBuilder\ | |
| \ dBuilder = dbFactory.newDocumentBuilder();\n // Parse an XML file using the\ | |
| \ secure document builder\n Document doc = dBuilder.parse(new InputSource(new\ | |
| \ StringReader(xmlData)));\n // Process the document as needed\n} catch (ParserConfigurationException\ | |
| \ | SAXException | IOException e) {\n // Handle exceptions appropriately\n\ | |
| } \n``` \n" | |
| pattern: '$PARSER.setFeature("http://xml.org/sax/features/external-parameter-entities", | |
| true); | |
| ' | |
| - id: java_xxe_rule-XMLInputFactoryExternalEntitiesEnabled | |
| severity: WARNING | |
| languages: | |
| - java | |
| metadata: | |
| cwe: CWE-611 | |
| shortDescription: Improper restriction of XML external entity reference | |
| owasp: | |
| - A4:2017-XML External Entities (XXE) | |
| - A05:2021-Security Misconfiguration | |
| security-severity: MEDIUM | |
| references: | |
| - https://semgrep.dev/blog/2022/xml-security-in-java | |
| - https://semgrep.dev/docs/cheat-sheets/java-xxe/ | |
| - https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf | |
| category: security | |
| cwe2022-top25: 'true' | |
| cwe2021-top25: 'true' | |
| likelihood: LOW | |
| impact: HIGH | |
| confidence: LOW | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - XML Injection | |
| message: "XML external entities are enabled for this XMLInputFactory. Enabling external\ | |
| \ \nentities can make the application vulnerable to XML external entity attacks.\ | |
| \ \nIn an XXE attack, an attacker can exploit the processing of external entity\ | |
| \ \nreferences within an XML document to access internal files, conduct \ndenial-of-service\ | |
| \ attacks, or SSRF (Server Side Request Forgery), potentially \nleading to sensitive\ | |
| \ information disclosure or system compromise.\n\nTo mitigate this vulnerability,\ | |
| \ disable external entities by\nsetting \"javax.xml.stream.isSupportingExternalEntities\"\ | |
| \ to false.\n\nSecure Code Example:\n```\npublic GoodXMLInputFactory() {\n final\ | |
| \ XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();\n xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD,\ | |
| \ false);\n xmlInputFactory.setProperty(\"javax.xml.stream.isSupportingExternalEntities\"\ | |
| , false);\n}\n```\nFor more details, refer to https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.md#xmlinputfactory-a-stax-parser\n" | |
| pattern: '$XMLFACTORY.setProperty("javax.xml.stream.isSupportingExternalEntities", | |
| true); | |
| ' | |
| - id: java_xxe_rule-TransformerfactoryDTDNotDisabled | |
| severity: WARNING | |
| languages: | |
| - java | |
| metadata: | |
| cwe: CWE-611 | |
| shortDescription: Improper restriction of XML external entity reference | |
| owasp: | |
| - A4:2017-XML External Entities (XXE) | |
| - A05:2021-Security Misconfiguration | |
| security-severity: MEDIUM | |
| references: | |
| - https://semgrep.dev/blog/2022/xml-security-in-java | |
| - https://semgrep.dev/docs/cheat-sheets/java-xxe/ | |
| - https://blog.sonarsource.com/secure-xml-processor | |
| - https://xerces.apache.org/xerces2-j/features.html | |
| category: security | |
| technology: | |
| - java | |
| - xml | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| message: "This rule identifies configurations of the TransformerFactory class where\n\ | |
| DOCTYPE declarations are enabled. Enabling DOCTYPE declarations without\nproper\ | |
| \ restrictions can make your application vulnerable to XML External\nEntity (XXE)\ | |
| \ attacks. In an XXE attack, an attacker can exploit the\nprocessing of external\ | |
| \ entity references within an XML document to access\ninternal files, conduct\ | |
| \ denial-of-service attacks, or SSRF (Server Side\nRequest Forgery), potentially\ | |
| \ leading to sensitive information disclosure\nor system compromise.\n\nTo mitigate\ | |
| \ XXE vulnerabilities related to the TransformerFactory instance in \nJava, it\ | |
| \ is crucial to disable external DTD (Document Type Definition) and \nexternal\ | |
| \ stylesheet processing. This can be accomplished by setting the \nACCESS_EXTERNAL_DTD\ | |
| \ and ACCESS_EXTERNAL_STYLESHEET factory attributes to an \nempty string (\"\"\ | |
| ). This approach prevents the parser from fetching and processing \nexternal references\ | |
| \ specified in the XML document.\n\nSecure Code Example:\n```\npublic static void\ | |
| \ configureTransformerFactory() throws TransformerConfigurationException {\n \ | |
| \ TransformerFactory factory = TransformerFactory.newInstance();\n // Disable\ | |
| \ access to external DTDs and stylesheets to prevent XXE\n factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD,\ | |
| \ \"\");\n factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, \"\"\ | |
| );\n}\n```\n" | |
| mode: taint | |
| pattern-sources: | |
| - by-side-effect: true | |
| patterns: | |
| - pattern-either: | |
| - pattern: '$FACTORY = javax.xml.transform.TransformerFactory.newInstance(); | |
| ' | |
| - patterns: | |
| - pattern: $FACTORY | |
| - pattern-inside: "class $C {\n ...\n $V $FACTORY = javax.xml.transform.TransformerFactory.newInstance();\n\ | |
| \ ...\n}\n" | |
| - pattern-not-inside: "class $C {\n ...\n $V $FACTORY = javax.xml.transform.TransformerFactory.newInstance();\n\ | |
| \ static {\n ...\n $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD,\ | |
| \ \"\");\n ...\n $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET,\ | |
| \ \"\");\n ...\n }\n ...\n}\n" | |
| - pattern-not-inside: "class $C {\n ...\n $V $FACTORY = javax.xml.transform.TransformerFactory.newInstance();\n\ | |
| \ static {\n ...\n $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET,\ | |
| \ \"\");\n ...\n $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD,\ | |
| \ \"\");\n ...\n }\n ...\n}\n" | |
| - pattern-not-inside: "class $C {\n ...\n $V $FACTORY = javax.xml.transform.TransformerFactory.newInstance();\n\ | |
| \ static {\n ...\n $FACTORY.setAttribute(\"=~/.*accessExternalDTD.*/\"\ | |
| , \"\");\n ...\n $FACTORY.setAttribute(\"=~/.*accessExternalStylesheet.*/\"\ | |
| , \"\");\n ...\n }\n ...\n}\n" | |
| - pattern-not-inside: "class $C {\n ...\n $V $FACTORY = javax.xml.transform.TransformerFactory.newInstance();\n\ | |
| \ static {\n ...\n $FACTORY.setAttribute(\"=~/.*accessExternalStylesheet.*/\"\ | |
| , \"\");\n ...\n $FACTORY.setAttribute(\"=~/.*accessExternalDTD.*/\"\ | |
| , \"\");\n ...\n }\n ...\n}\n" | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: $FACTORY.newTransformer(...); | |
| pattern-sanitizers: | |
| - by-side-effect: true | |
| pattern-either: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: '$FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, | |
| ""); ... | |
| $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); | |
| ' | |
| - pattern: '$FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); | |
| ... | |
| $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); | |
| ' | |
| - pattern: '$FACTORY.setAttribute("=~/.*accessExternalStylesheet.*/", ""); | |
| ... | |
| $FACTORY.setAttribute("=~/.*accessExternalDTD.*/", ""); | |
| ' | |
| - pattern: '$FACTORY.setAttribute("=~/.*accessExternalDTD.*/", ""); | |
| ... | |
| $FACTORY.setAttribute("=~/.*accessExternalStylesheet.*/", ""); | |
| ' | |
| - focus-metavariable: $FACTORY | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: "class $C {\n ...\n $T $M(...) {\n ...\n $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET,\ | |
| \ \"\");\n ...\n $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD,\ | |
| \ \"\");\n ...\n }\n ...\n}\n" | |
| - pattern-inside: "class $C {\n ...\n $T $M(...) {\n ...\n $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD,\ | |
| \ \"\");\n ...\n $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET,\ | |
| \ \"\");\n ...\n }\n ...\n}\n" | |
| - pattern-inside: "class $C {\n ...\n $T $M(...) {\n ...\n $FACTORY.setAttribute(\"\ | |
| =~/.*accessExternalStylesheet.*/\", \"\");\n ...\n $FACTORY.setAttribute(\"\ | |
| =~/.*accessExternalDTD.*/\", \"\");\n ...\n }\n ...\n}\n" | |
| - pattern-inside: "class $C {\n ...\n $T $M(...) {\n ...\n $FACTORY.setAttribute(\"\ | |
| =~/.*accessExternalDTD.*/\", \"\");\n ...\n $FACTORY.setAttribute(\"\ | |
| =~/.*accessExternalStylesheet.*/\", \"\");\n ...\n }\n ...\n}\n" | |
| - pattern: $M($X) | |
| - focus-metavariable: $X | |
| - id: java_xxe_rule-XMLStreamRdr | |
| languages: | |
| - java | |
| message: "External XML entities are a feature of XML parsers that allow \ndocuments\ | |
| \ to contain references to other documents or data. This \nfeature can be abused\ | |
| \ to read files, communicate with external\nhosts, exfiltrate data, or cause a\ | |
| \ Denial of Service (DoS).\nIn most XML parsers, the recommendation to protect\ | |
| \ against XXE is \nto disable the doctype feature.\nUnfortunately use of the `XMLInputFactory`\ | |
| \ requires that the doctypes \nfeature be enabled. Instead the application can\ | |
| \ set the `ACCESS_EXTERNAL_DTD` \nto an empty string and disable `javax.xml.stream.isSupportingExternalEntities`.\n\ | |
| \nSecure Code Example:\n```\n// Create an XMLInputFactory\nXMLInputFactory factory\ | |
| \ = XMLInputFactory.newFactory();\n// Set the ACCESS_EXTERNAL_DTD property to\ | |
| \ an empty string so it won't access\n// entities using protocols\n// (ref:\n\ | |
| https://docs.oracle.com/javase/8/docs/api/javax/xml/XMLConstants.html#ACCESS_EXTERNAL_DTD)\n\ | |
| factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, \"\");\n// Additionally,\ | |
| \ disable support for resolving external entities\nfactory.setProperty(\"javax.xml.stream.isSupportingExternalEntities\"\ | |
| , false);\n// Continue to work with the factory/stream parser\n```\n\nFor more\ | |
| \ information on XML security see OWASP's guide:\nhttps://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java\n" | |
| patterns: | |
| - pattern-not-inside: '(javax.xml.stream.XMLInputFactory $FAC).setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, | |
| ""); | |
| ... | |
| ' | |
| - pattern-not-inside: | |
| patterns: | |
| - pattern-either: | |
| - pattern: '(javax.xml.stream.XMLInputFactory $FAC).setProperty(XMLInputFactory.SUPPORT_DTD, | |
| $FALSE); | |
| ... | |
| ' | |
| - pattern: '(javax.xml.stream.XMLInputFactory $FAC).setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, | |
| $FALSE); | |
| ... | |
| ' | |
| - pattern: '(javax.xml.stream.XMLInputFactory $FAC).setProperty("javax.xml.stream.isSupportingExternalEntities", | |
| $FALSE); | |
| ... | |
| ' | |
| - metavariable-pattern: | |
| metavariable: $FALSE | |
| pattern-either: | |
| - pattern: 'false | |
| ' | |
| - pattern: 'Boolean.FALSE | |
| ' | |
| - pattern: '(javax.xml.stream.XMLInputFactory $FAC).createXMLStreamReader(...) | |
| ' | |
| metadata: | |
| shortDescription: Improper restriction of XML external entity reference ('XXE') | |
| category: security | |
| cwe: CWE-611 | |
| owasp: | |
| - A4:2017-XML External Entities (XXE) | |
| - A05:2021-Security Misconfiguration | |
| security-severity: MEDIUM | |
| severity: WARNING | |
| - id: java_xxe_rule-SAXParserFactoryDisallowDoctypeDeclMissing | |
| severity: WARNING | |
| languages: | |
| - java | |
| metadata: | |
| cwe: CWE-611 | |
| shortDescription: Improper restriction of XML external entity reference | |
| owasp: | |
| - A4:2017-XML External Entities (XXE) | |
| - A05:2021-Security Misconfiguration | |
| security-severity: MEDIUM | |
| references: | |
| - https://semgrep.dev/blog/2022/xml-security-in-java | |
| - https://semgrep.dev/docs/cheat-sheets/java-xxe/ | |
| - https://blog.sonarsource.com/secure-xml-processor | |
| - https://xerces.apache.org/xerces2-j/features.html | |
| category: security | |
| technology: | |
| - java | |
| - xml | |
| cwe2022-top25: 'true' | |
| cwe2021-top25: 'true' | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - XML Injection | |
| message: "DOCTYPE declarations are enabled for this SAXParserFactory. Enabling DOCTYPE\ | |
| \ \ndeclarations without proper restrictions can make your application vulnerable\ | |
| \ to \nXML External Entity (XXE) attacks. \nIn an XXE attack, an attacker can\ | |
| \ exploit the processing of external entity \nreferences within an XML document\ | |
| \ to access internal files, conduct \ndenial-of-service attacks, or SSRF (Server\ | |
| \ Side Request Forgery), potentially \nleading to sensitive information disclosure\ | |
| \ or system compromise.\n\nTo mitigate this vulnerability, disable DOCTYPE declarations\ | |
| \ by setting the\nfeature `http://apache.org/xml/features/disallow-doctype-decl`\ | |
| \ to true.\nAlternatively, allow DOCTYPE declarations and only prohibit external\n\ | |
| entities declarations. This can be done by setting the features\n`http://xml.org/sax/features/external-general-entities`\ | |
| \ and\n`http://xml.org/sax/features/external-parameter-entities` to false. \n\ | |
| NOTE: The previous links are not meant to be clicked. They are the literal\nconfig\ | |
| \ key values that are supposed to be used to disable these features.\n\nSecure\ | |
| \ Code Example (You can do either of the following):\n```\npublic void GoodSAXParserFactory()\ | |
| \ throws ParserConfigurationException {\n SAXParserFactory spf = SAXParserFactory.newInstance();\n\ | |
| \ spf.setFeature(\"http://apache.org/xml/features/disallow-doctype-decl\", true);\n\ | |
| \ spf.newSAXParser();\n}\n\npublic void GoodSAXParserFactory2() throws ParserConfigurationException\ | |
| \ {\n SAXParserFactory spf = SAXParserFactory.newInstance();\n spf.setFeature(\"\ | |
| http://xml.org/sax/features/external-parameter-entities\", false);\n spf.setFeature(\"\ | |
| http://xml.org/sax/features/external-general-entities\", false);\n spf.newSAXParser();\n\ | |
| } \n```\nFor more information, see\nhttps://semgrep.dev/docs/cheat-sheets/java-xxe/#3a-documentbuilderfactory.\n" | |
| mode: taint | |
| pattern-sources: | |
| - by-side-effect: true | |
| patterns: | |
| - pattern-either: | |
| - pattern: '$FACTORY = SAXParserFactory.newInstance(); | |
| ' | |
| - patterns: | |
| - pattern: $FACTORY | |
| - pattern-inside: "class $C {\n ...\n $V $FACTORY = SAXParserFactory.newInstance();\n\ | |
| \ ...\n}\n" | |
| - pattern-not-inside: "class $C {\n ...\n $V $FACTORY = SAXParserFactory.newInstance();\n\ | |
| \ static {\n ...\n $FACTORY.setFeature(\"http://apache.org/xml/features/disallow-doctype-decl\"\ | |
| , true);\n ...\n }\n ...\n}\n" | |
| - pattern-not-inside: "class $C {\n ...\n $V $FACTORY = SAXParserFactory.newInstance();\n\ | |
| \ static {\n ...\n $FACTORY.setFeature(\"http://xml.org/sax/features/external-parameter-entities\"\ | |
| , false);\n ...\n $FACTORY.setFeature(\"http://xml.org/sax/features/external-general-entities\"\ | |
| , false);\n ...\n }\n ...\n}\n" | |
| - pattern-not-inside: "class $C {\n ...\n $V $FACTORY = SAXParserFactory.newInstance();\n\ | |
| \ static {\n ...\n $FACTORY.setFeature(\"http://xml.org/sax/features/external-general-entities\"\ | |
| , false);\n ...\n $FACTORY.setFeature(\"http://xml.org/sax/features/external-parameter-entities\"\ | |
| , false);\n ...\n }\n ...\n}\n" | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: $FACTORY.newSAXParser(); | |
| pattern-sanitizers: | |
| - by-side-effect: true | |
| pattern-either: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: '$FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", | |
| true); | |
| ' | |
| - pattern: '$FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", | |
| false); | |
| ... | |
| $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", | |
| false); | |
| ' | |
| - pattern: '$FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", | |
| false); | |
| ... | |
| $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", | |
| false); | |
| ' | |
| - focus-metavariable: $FACTORY | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: "class $C {\n ...\n $T $M(...) {\n ...\n $FACTORY.setFeature(\"\ | |
| http://apache.org/xml/features/disallow-doctype-decl\",\n true);\n\ | |
| \ ...\n }\n ...\n}\n" | |
| - pattern-inside: "class $C {\n ...\n $T $M(...) {\n ...\n $FACTORY.setFeature(\"\ | |
| http://xml.org/sax/features/external-general-entities\", false);\n \ | |
| \ ...\n $FACTORY.setFeature(\"http://xml.org/sax/features/external-parameter-entities\"\ | |
| , false);\n ...\n }\n ...\n}\n" | |
| - pattern-inside: "class $C {\n ...\n $T $M(...) {\n ...\n $FACTORY.setFeature(\"\ | |
| http://xml.org/sax/features/external-parameter-entities\", false);\n \ | |
| \ ...\n $FACTORY.setFeature(\"http://xml.org/sax/features/external-general-entities\"\ | |
| ,false);\n ...\n }\n ...\n}\n" | |
| - pattern: $M($X) | |
| - focus-metavariable: $X | |
| - id: java_file_rule_rule-FilePathTraversalHttpServlet | |
| languages: | |
| - java | |
| severity: ERROR | |
| metadata: | |
| security-severity: CRITICAL | |
| shortDescription: Improper Limitation of a Pathname to a Restricted Directory | |
| ('Path Traversal') | |
| cwe: CWE-22 | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| source-rule-url: https://find-sec-bugs.github.io/bugs.htm#PATH_TRAVERSAL_IN | |
| references: | |
| - https://www.owasp.org/index.php/Path_Traversal | |
| category: security | |
| technology: | |
| - java | |
| cwe2022-top25: true | |
| cwe2021-top25: true | |
| impact: MEDIUM | |
| confidence: MEDIUM | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Path Traversal | |
| message: "Detected a potential path traversal. A malicious actor could control\n\ | |
| the location of this file, to include going backwards in the directory\nwith '../'.\ | |
| \ \n\nTo address this, ensure that user-controlled variables in file\npaths are\ | |
| \ sanitized. You may also consider using a utility method such as\norg.apache.commons.io.FilenameUtils.getName(...)\ | |
| \ to only retrieve the file\nname from the path.\n\nExample code using FilenameUtils.getName(...)\n\ | |
| \n```\npublic void ok(HttpServletRequest request, HttpServletResponse response)\n\ | |
| \ throws ServletException, IOException {\n String image = request.getParameter(\"\ | |
| image\");\n File file = new File(\"static/images/\", FilenameUtils.getName(image));\n\ | |
| \n if (!file.exists()) {\n log.info(image + \" could not be created.\"\ | |
| );\n response.sendError();\n }\n\n response.sendRedirect(\"/index.html\"\ | |
| );\n}\n```\n" | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: '(HttpServletRequest $REQ) | |
| ' | |
| - patterns: | |
| - pattern-inside: "(javax.servlet.http.Cookie[] $COOKIES) = (HttpServletRequest\ | |
| \ $REQ).getCookies(...); ...\nfor (javax.servlet.http.Cookie $COOKIE:\ | |
| \ $COOKIES) {\n ...\n}\n" | |
| - pattern: '$COOKIE.getValue(...) | |
| ' | |
| - patterns: | |
| - pattern-inside: '$TYPE[] $VALS = (HttpServletRequest $REQ).$GETFUNC(...); | |
| ... | |
| ' | |
| - pattern: '$PARAM = $VALS[$INDEX]; | |
| ' | |
| pattern-sanitizers: | |
| - pattern: org.apache.commons.io.FilenameUtils.getName(...) | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: '(java.io.File $FILE) = ... | |
| ' | |
| - pattern: '(java.io.FileOutputStream $FOS) = ... | |
| ' | |
| - pattern: 'new java.io.FileInputStream(...) | |
| ' | |
| - id: java_inject_rule-EnvInjection | |
| message: "Detected input from a HTTPServletRequest going into the environment\n\ | |
| variables of an 'exec' command. The user input is passed directly to\nthe Runtime.exec()\ | |
| \ function to set an environment variable. This allows \nmalicious input from\ | |
| \ the user to modify the command that will be executed.\nTo remediate this, do\ | |
| \ not pass user input directly to Runtime.exec().\nValidate any user input before\ | |
| \ using it to set environment variables \nor command arguments. Consider using\ | |
| \ an allow list of allowed values\nrather than a deny list. If dynamic commands\ | |
| \ must be constructed, use\na map to look up valid values based on user input\ | |
| \ instead of using \nthe input directly.\nExample of safely executing an OS command:\n\ | |
| ```\npublic void doPost(HttpServletRequest request, HttpServletResponse response)\n\ | |
| \ throws ServletException, IOException {\n response.setContentType(\"text/html;charset=UTF-8\"\ | |
| );\n\n String param = \"\";\n if (request.getHeader(\"UserDefined\") != null)\ | |
| \ {\n param = request.getHeader(\"UserDefined\");\n }\n\n param = java.net.URLDecoder.decode(param,\ | |
| \ \"UTF-8\");\n String cmd = \"/bin/cmd\";\n\n String[] allowList = {\"FOO=true\"\ | |
| ,\"FOO=false\",\"BAR=true\", \"BAR=false\"}\n if(Arrays.asList(allowList).contains(param)){\n\ | |
| \ String[] argsEnv = {param};\n }\n \n Runtime r = Runtime.getRuntime();\n\ | |
| \n try {\n Process p = r.exec(cmd, argsEnv);\n printOSCommandResults(p,\ | |
| \ response); \n } catch (IOException e) {\n System.out.println(\"\ | |
| Problem executing command\");\n response.getWriter()\n .println(org.owasp.esapi.ESAPI.encoder().encodeForHTML(e.getMessage()));\n\ | |
| \ return;\n }\n```\n" | |
| languages: | |
| - java | |
| severity: ERROR | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: '(HttpServletRequest $REQ) | |
| ' | |
| - patterns: | |
| - pattern-inside: '$FUNC(..., $VAR, ...) { | |
| ... | |
| } | |
| ' | |
| - pattern: $VAR | |
| pattern-sinks: | |
| - pattern-either: | |
| - patterns: | |
| - pattern: (java.lang.Runtime $R).exec($CMD, $ENV_ARGS, ...); | |
| - focus-metavariable: $ENV_ARGS | |
| - patterns: | |
| - pattern: (ProcessBuilder $PB).environment().put($...ARGS); | |
| - focus-metavariable: $...ARGS | |
| - patterns: | |
| - pattern: '$ENV = (ProcessBuilder $PB).environment(); | |
| ... | |
| $ENV.put($...ARGS); | |
| ' | |
| - focus-metavariable: $...ARGS | |
| pattern-sanitizers: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: 'if($VALIDATION){ | |
| ... | |
| } | |
| ' | |
| - patterns: | |
| - pattern-inside: '$A = $VALIDATION; | |
| ... | |
| ' | |
| - pattern: 'if($A){ | |
| ... | |
| } | |
| ' | |
| - metavariable-pattern: | |
| metavariable: $VALIDATION | |
| pattern-either: | |
| - pattern: '$AL.contains(...) | |
| ' | |
| metadata: | |
| shortDescription: Improper neutralization of special elements used in an OS command | |
| ('OS Command Injection') | |
| category: security | |
| technology: | |
| - java | |
| cwe: CWE-78 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| references: | |
| - https://owasp.org/Top10/A03_2021-Injection | |
| subcategory: | |
| - vuln | |
| likelihood: MEDIUM | |
| impact: MEDIUM | |
| confidence: MEDIUM | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Other | |
| security-severity: HIGH | |
| - id: java_inject_rule-SqlInjection | |
| languages: | |
| - java | |
| options: | |
| taint_assume_safe_booleans: true | |
| taint_assume_safe_numbers: true | |
| message: "SQL Injection is a critical vulnerability that can lead to data or system\ | |
| \ compromise. By\ndynamically generating SQL query strings, user input may be\ | |
| \ able to influence the logic of\nthe SQL statement. This could lead to an adversary\ | |
| \ accessing information they should\nnot have access to, or in some circumstances,\ | |
| \ being able to execute OS functionality or code.\n\nReplace all dynamically generated\ | |
| \ SQL queries with parameterized queries. In situations where\ndynamic queries\ | |
| \ must be created, never use direct user input, but instead use a map or\ndictionary\ | |
| \ of valid values and resolve them using a user-supplied key.\n\nFor example,\ | |
| \ some database drivers do not allow parameterized queries for `>` or `<` comparison\n\ | |
| operators. In these cases, do not use a user supplied `>` or `<` value, but rather\ | |
| \ have the\nuser\nsupply a `gt` or `lt` value. The alphabetical values are then\ | |
| \ used to look up the `>` and `<`\nvalues to be used in the construction of the\ | |
| \ dynamic query. The same goes for other queries\nwhere\ncolumn or table names\ | |
| \ are required but cannot be parameterized.\n\nExample using `PreparedStatement`\ | |
| \ queries:\n```\n// Some userInput\nString userInput = \"someUserInput\";\n//\ | |
| \ Your connection string\nString url = \"...\";\n// Get a connection from the\ | |
| \ DB via the DriverManager\nConnection conn = DriverManager.getConnection(url);\n\ | |
| // Create a prepared statement\nPreparedStatement st = conn.prepareStatement(\"\ | |
| SELECT name FROM table where name=?\");\n// Set each parameters value by the index\ | |
| \ (starting from 1)\nst.setString(1, userInput);\n// Execute query and get the\ | |
| \ result set\nResultSet rs = st.executeQuery();\n// Iterate over results\nwhile\ | |
| \ (rs.next()) {\n // Get result for this row at the provided column number\ | |
| \ (starting from 1)\n String result = rs.getString(1);\n // ...\n}\n// Close\ | |
| \ the ResultSet\nrs.close();\n// Close the PreparedStatement\nst.close();\n```\n\ | |
| \nExample on using CriteriaBuilder to build queries\n```\npublic List<YourEntity>\ | |
| \ findBySomeCriteria(EntityManager entityManager, String criteriaValue) {\n \ | |
| \ CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();\n \ | |
| \ CriteriaQuery<YourEntity> query = criteriaBuilder.createQuery(YourEntity.class);\n\ | |
| \ Root<YourEntity> root = query.from(YourEntity.class);\n\n query.select(root).where(criteriaBuilder.equal(root.get(\"\ | |
| someProperty\"), criteriaValue));\n\n return entityManager.createQuery(query).getResultList();\n\ | |
| }\n```\n\nFor more information on SQL Injection see OWASP:\nhttps://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html\n" | |
| mode: taint | |
| pattern-sources: | |
| - pattern: (javax.servlet.http.HttpServletRequest $R).$METHOD(...) | |
| - pattern: (java.util.Scanner $S).$METHOD(...) | |
| - pattern: (java.util.stream.Stream).$METHOD(...) | |
| - pattern: (java.util.StringJoiner $SJ).toString(...) | |
| - pattern: (java.sql.ResultSet.getString $R).$METHOD(...) | |
| - pattern: (java.lang.System $S).getProperty(...) | |
| - pattern: (java.lang.System $S).getenv(...) | |
| - pattern: (java.lang.StringBuilder $SB).toString(...) | |
| - pattern: (java.io.FileInputStream $F).read(...) | |
| - pattern: (java.io.FileReader $F).read(...) | |
| - pattern: (java.net.Socket $S).getInputStream(...) | |
| - pattern: (java.net.Socket $S).getOutputStream(...) | |
| - pattern: (java.net.DatagramSocket $S).receive(...) | |
| - pattern: (java.net.DatagramSocket $S).getInputStream(...) | |
| - pattern: java.nio.file.Files.readAllBytes(...) | |
| - pattern: java.nio.file.Files.readAllLines(...) | |
| - pattern: java.nio.file.Files.lines(...) | |
| - pattern: java.nio.file.Files.newBufferedReader(...) | |
| - pattern: org.apache.commons.io.IOUtils.toString(...) | |
| - pattern: org.apache.commons.io.IOUtils.readLines(...) | |
| - pattern: org.apache.commons.io.IOUtils.toByteArray(...) | |
| - pattern: (com.fasterxml.jackson.databind.ObjectMapper $OM).readValue(...) | |
| - pattern: (com.fasterxml.jackson.databind.ObjectMapper $OM).treeToValue(...) | |
| - pattern: $CLASS.$METHOD(..., (javax.servlet.http.HttpServletRequest $R), ...) | |
| - pattern: $FUNC(..., (javax.servlet.http.HttpServletRequest $R), ...) | |
| - patterns: | |
| - pattern-inside: $FUNC(..., String $X, ...) { ... } | |
| - focus-metavariable: $X | |
| pattern-propagators: | |
| - pattern: $LIST.add($X) | |
| from: $X | |
| to: $LIST | |
| - pattern: $MAP.put(..., $X) | |
| from: $X | |
| to: $MAP | |
| - pattern: $STR.concat($X) | |
| from: $X | |
| to: $STR | |
| - pattern: $STR = String.format(..., $X, ...) | |
| from: $X | |
| to: $STR | |
| - pattern: $STR = String.join(..., $X, ...) | |
| from: $X | |
| to: $STR | |
| - pattern: $SB.append($X) | |
| from: $X | |
| to: $SB | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: (javax.jdo.PersistenceManager $PM).newQuery($ARG) | |
| - pattern: (javax.jdo.PersistenceManager $PM).newQuery(..., $ARG) | |
| - pattern: (javax.jdo.Query $Q).setFilter($ARG) | |
| - pattern: (javax.jdo.Query $Q).setGrouping($ARG) | |
| - pattern: org.hibernate.criterion.Restrictions.sqlRestriction($ARG, ...) | |
| - pattern: (org.hibernate.Session $S).createQuery((String $ARG), ...) | |
| - pattern: (org.hibernate.Session $S).createSQLQuery($ARG, ...) | |
| - pattern: (org.hibernate.Session $S).connection().prepareStatement($ARG) | |
| - pattern: (java.sql.Statement $S).executeQuery($ARG, ...) | |
| - pattern: (java.sql.Statement $S).execute($ARG, ...) | |
| - pattern: (java.sql.Statement $S).executeUpdate($ARG, ...) | |
| - pattern: (java.sql.Statement $S).executeLargeUpdate($ARG, ...) | |
| - pattern: (java.sql.Statement $S).addBatch($ARG, ...) | |
| - pattern: (java.sql.PreparedStatement $S).executeQuery($ARG, ...) | |
| - pattern: (java.sql.PreparedStatement $S).execute($ARG, ...) | |
| - pattern: (java.sql.PreparedStatement $S).executeUpdate($ARG, ...) | |
| - pattern: (java.sql.PreparedStatement $S).executeLargeUpdate($ARG, ...) | |
| - pattern: (java.sql.PreparedStatement $S).addBatch($ARG, ...) | |
| - pattern: (java.sql.Connection $S).prepareCall($ARG, ...) | |
| - pattern: (java.sql.Connection $S).prepareStatement($ARG, ...) | |
| - pattern: (java.sql.Connection $S).nativeSQL($ARG, ...) | |
| - pattern: new org.springframework.jdbc.core.PreparedStatementCreatorFactory($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.PreparedStatementCreatorFactory $F).newPreparedStatementCreator($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcOperations $O).batchUpdate($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcOperations $O).execute($ARG, ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcOperations $O).query($ARG, ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcOperations $O).queryForList($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcOperations $O).queryForMap($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcOperations $O).queryForObject($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcOperations $O).queryForObject($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcOperations $O).queryForRowSet($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcOperations $O).queryForInt($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcOperations $O).queryForLong($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcOperations $O).update($ARG, ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).batchUpdate($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).execute($ARG, ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).query($ARG, ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).queryForList($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).queryForMap($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).queryForObject($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).queryForRowSet($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).queryForInt($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).queryForLong($ARG, | |
| ...) | |
| - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).update($ARG, ...) | |
| - pattern: (io.vertx.sqlclient.SqlClient $O).query($ARG, ...) | |
| - pattern: (io.vertx.sqlclient.SqlClient $O).preparedQuery($ARG, ...) | |
| - pattern: (io.vertx.sqlclient.SqlConnection $O).prepare($ARG, ...) | |
| - pattern: (org.apache.turbine.om.peer.BasePeer $O).executeQuery($ARG, ...) | |
| - pattern: org.apache.torque.util.BasePeer.executeQuery($ARG, ...) | |
| - pattern: org.apache.torque.util.BasePeer.executeStatement($ARG, ...) | |
| - pattern: (javax.persistence.EntityManager $O).createQuery($ARG, ...) | |
| - pattern: (javax.persistence.EntityManager $O).createNativeQuery($ARG, ...) | |
| - pattern: (org.jdbi.v3.core.Handle $H).createQuery($ARG, ...) | |
| - pattern: (org.jdbi.v3.core.Handle $H).createScript($ARG, ...) | |
| - pattern: (org.jdbi.v3.core.Handle $H).createUpdate($ARG, ...) | |
| - pattern: (org.jdbi.v3.core.Handle $H).execute($ARG, ...) | |
| - pattern: (org.jdbi.v3.core.Handle $H).prepareBatch($ARG, ...) | |
| - pattern: (org.jdbi.v3.core.Handle $H).select($ARG, ...) | |
| - pattern: new org.jdbi.v3.core.statement.Script($H, $ARG) | |
| - pattern: new org.jdbi.v3.core.statement.Update($H, $ARG) | |
| - pattern: new org.jdbi.v3.core.statement.PreparedBatch($H, $ARG) | |
| - focus-metavariable: $ARG | |
| - patterns: | |
| - pattern: (java.sql.Connection $S).createStatement(...).$SQLFUNC($ARG, ...) | |
| - pattern-not: (java.sql.Connection $S).createStatement(...).$SQLFUNC("...") | |
| - metavariable-regex: | |
| metavariable: $SQLFUNC | |
| regex: execute|executeQuery|createQuery|query|addBatch|nativeSQL|create|prepare | |
| pattern-sanitizers: | |
| - pattern: (CriteriaBuilder $CB).$ANY(...) | |
| metadata: | |
| shortDescription: Improper neutralization of special elements used in an SQL command | |
| ('SQL Injection') | |
| category: security | |
| cwe: CWE-89 | |
| technology: | |
| - java | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: High | |
| severity: ERROR | |
| - id: java_inject_rule-MongodbNoSQLi | |
| languages: | |
| - java | |
| patterns: | |
| - pattern-either: | |
| - pattern: (com.mongodb.BasicDBObject $QUERY).put("$where", $INPUT); | |
| - pattern: '(HashMap<String, String> $MAP).put("$where", $INPUT); | |
| ... | |
| (com.mongodb.BasicDBObject $QUERY).putAll($MAP); | |
| ' | |
| - pattern: (com.mongodb.BasicDBObject $QUERY).append("$where", $INPUT); | |
| - pattern: new com.mongodb.BasicDBObject("$where", $INPUT); | |
| - pattern: '(HashMap<String, String> $MAP).put("$where", $INPUT); | |
| ... | |
| new com.mongodb.BasicDBObject($MAP); | |
| ' | |
| - pattern: '(HashMap<String, String> $MAP).put("$where", $INPUT); | |
| ... | |
| String json = new JSONObject($MAP).toString(); | |
| ... | |
| (com.mongodb.BasicDBObject $QUERY).parse((String $JSON)); | |
| ' | |
| - pattern: com.mongodb.BasicDBObjectBuilder.start().add("$where", $INPUT); | |
| - pattern: com.mongodb.BasicDBObjectBuilder.start().append("$where", $INPUT); | |
| - pattern: com.mongodb.BasicDBObjectBuilder.start("$where", $INPUT); | |
| - pattern: '(HashMap<String, String> $MAP).put("$where", $INPUT); | |
| ... | |
| com.mongodb.BasicDBObjectBuilder.start($MAP); | |
| ' | |
| - metavariable-pattern: | |
| metavariable: $INPUT | |
| patterns: | |
| - pattern: '... | |
| ' | |
| - pattern-not: '"..." | |
| ' | |
| message: 'Detected non-constant data passed into a NoSQL query using the ''where'' | |
| evaluation operator. If this data can be controlled by an external user, | |
| this is a NoSQL injection. Ensure data passed to the NoSQL query is not | |
| user controllable, or properly sanitize the data. Ideally, avoid using the | |
| ''where'' operator at all and instead use the helper methods provided by | |
| com.mongodb.client.model.Filters with comparative operators such as eq, | |
| ne, lt, gt, etc. | |
| Secure Code Example: | |
| ``` | |
| MongoDatabase database = mongoClient.getDatabase("mydb"); | |
| MongoCollection<Document> collection = database.getCollection("users"); | |
| // Secure usage with Filters.eq: | |
| String username = request.getParameter("username"); | |
| collection.find(Filters.eq("username", username)); | |
| ``` | |
| ' | |
| severity: ERROR | |
| metadata: | |
| category: security | |
| technology: | |
| - nosql | |
| - mongodb | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| cwe: CWE-943 | |
| shortDescription: Improper neutralization of special elements in data query logic | |
| security-severity: CRITICAL | |
| references: | |
| - https://owasp.org/Top10/A03_2021-Injection | |
| - https://www.mongodb.com/docs/manual/tutorial/query-documents/ | |
| - https://www.mongodb.com/docs/manual/reference/operator/query/where/ | |
| subcategory: | |
| - audit | |
| likelihood: LOW | |
| impact: HIGH | |
| confidence: LOW | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Improper Validation | |
| - id: java_inject_rule-DangerousGroovyShell | |
| languages: | |
| - java | |
| patterns: | |
| - pattern-either: | |
| - pattern: '(groovy.lang.GroovyShell $SHELL).parse(...) | |
| ' | |
| - pattern: '(groovy.lang.GroovyShell $SHELL).evaluate(...) | |
| ' | |
| - pattern: '(groovy.lang.GroovyClassLoader $SHELL).parseClass(...) | |
| ' | |
| - pattern-not: '$SHELL.parse("...",...) | |
| ' | |
| - pattern-not: '$SHELL.evaluate("...",...) | |
| ' | |
| - pattern-not: '$SHELL.parseClass("...",...) | |
| ' | |
| - pattern-not-inside: "if($ALLOWLIST.contains($INPUT)){\n ...\n}\n" | |
| message: "This application implements unsafe invocations of methods within the\n\ | |
| `groovy.lang.GroovyShell` or `groovy.lang.GroovyClassLoader` classes,\nwhich are\ | |
| \ used to evaluate or compile Groovy code dynamically. When\nuser-controlled input\ | |
| \ is directly passed to `parse`, `evaluate`, or\n`parseClass` methods, it can\ | |
| \ lead to Remote Code Execution (RCE), where an\nattacker can execute arbitrary\ | |
| \ code on the server. This could potentially\nallow an attacker to gain unauthorized\ | |
| \ access to system resources, modify\ninternal application states, or execute\ | |
| \ commands on the server depending\non the level of permissions assigned to the\ | |
| \ application process.\n\nTo mitigate this vulnerability, always validate and\ | |
| \ sanitize all user inputs \nbefore using them in dynamic code evaluations. Consider\ | |
| \ using safer alternatives \nto executing dynamic code if possible. If dynamic\ | |
| \ code execution is absolutely \nnecessary, use strict allowlists of safe inputs\ | |
| \ and context-specific validation.\n\nSecure Code Example:\n\n```\nimport groovy.lang.GroovyShell;\n\ | |
| \nclass SafeDynamicEvaluation {\n private static final Set<String> ALLOWED_EXPRESSIONS\ | |
| \ = new HashSet<>(Arrays.asList(\n \"println 'Hello World!'\",\n \"\ | |
| println 'Goodbye World!'\"));\n\n public static void test4(String[] args, ClassLoader\ | |
| \ loader) throws Exception {\n GroovyShell shell = new GroovyShell();\n \ | |
| \ String userInput = args[0];\n\n // Validate the user input against the allowlist\n\ | |
| \ if (ALLOWED_EXPRESSIONS.contains(userInput)) {\n shell.evaluate(userInput);\n\ | |
| \ // shell.parse(userInput);\n } else {\n throw new IllegalArgumentException(\"\ | |
| Invalid or unauthorized command.\");\n }\n }\n}\n```\n" | |
| metadata: | |
| shortDescription: Improper control of generation of code ('Code Injection') | |
| category: security | |
| cwe: CWE-94 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| source-rule-url: https://find-sec-bugs.github.io/bugs.htm#GROOVY_SHELL | |
| technology: | |
| - groovy | |
| references: | |
| - https://owasp.org/Top10/A03_2021-Injection | |
| cwe2022-top25: 'true' | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Code Injection | |
| severity: ERROR | |
| - id: java_inject_rule-SeamLogInjection | |
| languages: | |
| - java | |
| patterns: | |
| - pattern: '$LOG.$INFO($X + $Y,...) | |
| ' | |
| - pattern-either: | |
| - pattern-inside: 'import org.jboss.seam.log.Log; | |
| ... | |
| ' | |
| - pattern-inside: 'org.jboss.seam.log.Log $LOG = ...; | |
| ... | |
| ' | |
| - metavariable-regex: | |
| metavariable: $INFO | |
| regex: (debug|error|fatal|info|trace|warn) | |
| message: "The Seam logging API supports an expression language that allows developers\ | |
| \ to \nintroduce bean properties to log messages. The expression language can\ | |
| \ also be \nthe source to unwanted code execution. Expressions could be executed\ | |
| \ by dynamically\ninserting user-controlled input into the various logging calls.\ | |
| \ \n\nUse the [Seam logging API format specifier](https://docs.jboss.org/seam/2.1.2/reference/en-US/html/concepts.html#d0e4244)\ | |
| \ to ensure values are logged and expressions\nare not executed dynamically prior\ | |
| \ to output.\n\nExample logging call that safely logs the unfiltered values.\n\ | |
| ```\nlog.info(\"This is a user controlled input = #0\", input);\n```\n" | |
| severity: ERROR | |
| metadata: | |
| category: security | |
| shortDescription: Improper neutralization of directives in dynamically evaluated | |
| code ('Eval Injection') | |
| cwe: CWE-95 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| references: | |
| - https://owasp.org/Top10/A03_2021-Injection | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| security-severity: CRITICAL | |
| - id: rules_lgpl_java_webview_rule-webview-set-allow-file-access | |
| pattern: $WB.setAllowFileAccess(true); | |
| message: "WebView File System Access is enabled. An attacker able to inject \nscript\ | |
| \ into a WebView, could exploit the opportunity to unauthorized \naccess to sensitive\ | |
| \ user data or system files.\n\nTo fix this security issue, you should disable\ | |
| \ file access in the \nWebView or restrict it to specific directories. \nAn example:\n\ | |
| ```\n// Create a WebView instance\nWebView webView = new WebView(context);\n//\ | |
| \ Disable file access in the WebView\nwebView.getSettings().setAllowFileAccess(false);\n\ | |
| ```\n" | |
| languages: | |
| - java | |
| severity: WARNING | |
| metadata: | |
| category: security | |
| cwe: CWE-73 | |
| shortDescription: External control of file name or path | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| security-severity: MEDIUM | |
| - id: rules_lgpl_java_webview_rule-webview-external-storage | |
| patterns: | |
| - pattern-either: | |
| - pattern: '$X = <... $E.getExternalStorageDirectory() ...>; | |
| ... | |
| $WV.loadUrl(<... $X ...>); | |
| ' | |
| - pattern: '$WV.loadUrl(<... $E.getExternalStorageDirectory().$F() ...>); | |
| ' | |
| - pattern: '$X = <... Environment.getExternalStorageDirectory().$F() ...>; | |
| ... | |
| $WV.loadUrl(<... $X ...>); | |
| ' | |
| - pattern: '$X = <... $E.getExternalFilesDir(...) ...>; | |
| ... | |
| $WV.loadUrl(<... $X ...>); | |
| ' | |
| message: "WebView load files from external storage. Files in external storage can\ | |
| \ be\nmodified by any application.\n\nLoading files from external storage in a\ | |
| \ WebView can introduce security risks, \nas it allows web content to access potentially\ | |
| \ sensitive data stored on the \ndevice's external storage. This can lead to unauthorized\ | |
| \ access to user data, \nincluding personal files, credentials, or other sensitive\ | |
| \ information, by \nmalicious web content.\n\nTo fix this security issue, you\ | |
| \ should avoid loading files directly from external \nstorage in a WebView. Instead,\ | |
| \ you should use a Content Provider or a secure file \nstorage mechanism to access\ | |
| \ files and provide them to the WebView as content.\n\nHere's a general approach\ | |
| \ to fix this problem:\n(1) Use a Content Provider: If you need to load files\ | |
| \ from external storage in a WebView, \nconsider using a Content Provider to securely\ | |
| \ access the files. Content Providers \nprovide controlled access to files stored\ | |
| \ on external storage and allow you to define \npermissions for accessing them.\n\ | |
| (2) Secure File Storage: Store files containing sensitive data in a secure location,\ | |
| \ such \nas internal storage or encrypted storage, and provide access to them\ | |
| \ through a secure \nAPI. Avoid exposing sensitive files directly to the WebView.\n\ | |
| (3) Restrict WebView Access: Configure the WebView to restrict access to external\ | |
| \ resources \nand content. Use methods like setAllowFileAccess() to control file\ | |
| \ access and \nsetAllowContentAccess() to control access to content from other\ | |
| \ origins.\nHere's an example of how you can use a Content Provider to provide\ | |
| \ secure access to \nfiles in a WebView:\n```\n// Define the URI of the content\ | |
| \ provider for accessing files\nUri contentProviderUri = Uri.parse(\"content://com.example.myapp.provider/files\"\ | |
| );\n// Load the content from the Content Provider into the WebView\nwebView.loadUrl(contentProviderUri.toString());\n\ | |
| ```\nIn the above code, we define the URI of a Content Provider that provides\ | |
| \ access to files \nstored in the app's external storage. The content is loaded\ | |
| \ from the Content Provider into \nthe WebView using loadUrl(), which ensures\ | |
| \ that access to files is controlled and secure, \npreventing unauthorized access\ | |
| \ to sensitive data.\n" | |
| languages: | |
| - java | |
| severity: ERROR | |
| metadata: | |
| category: security | |
| cwe: CWE-749 | |
| shortDescription: Exposed dangerous method or function | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: CRITICAL | |
| - id: rules_lgpl_java_webview_rule-webview-debugging | |
| patterns: | |
| - pattern-either: | |
| - pattern: '$WB.setWebContentsDebuggingEnabled(true); | |
| ' | |
| - pattern: '$X = true; | |
| ... | |
| $WB.setWebContentsDebuggingEnabled($X); | |
| ' | |
| message: "Remote WebView debugging is enabled. This allows an attacker with\ndebugging\ | |
| \ access to interact with the webview and steal or corrupt data.\nTo fix these\ | |
| \ security issues, it is recommended to disable remote \ndebugging and restrict\ | |
| \ file access in the WebView. \nHere's how you can do it:\n```\nWebView webView\ | |
| \ = new WebView(context);\n\n// Disable remote debugging\nif (Build.VERSION.SDK_INT\ | |
| \ >= Build.VERSION_CODES.KITKAT) {\n WebView.setWebContentsDebuggingEnabled(false);\n\ | |
| }\n\n// Restrict file access from file URLs\nwebView.getSettings().setAllowFileAccessFromFileURLs(false);\n\ | |
| \n// Load a web page\nwebView.loadUrl(\"https://example.com\");\n```\n" | |
| languages: | |
| - java | |
| severity: WARNING | |
| metadata: | |
| category: security | |
| cwe: CWE-489 | |
| shortDescription: Active debug code | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| security-severity: MEDIUM | |
| - id: rules_lgpl_java_webview_rule-ignore-ssl-certificate-errors | |
| pattern: "$RET onReceivedSslError(WebView $W, SslErrorHandler $H, SslError $E) {\n\ | |
| \ ...\n $H.proceed();\n}\n" | |
| message: "Insecure WebView Implementation. leading to a security problem known as\ | |
| \ SSL certificate \nvalidation bypass. This occurs when the app fails to properly\ | |
| \ validate SSL certificates, \nallowing potentially malicious or spoofed certificates\ | |
| \ to be accepted, leading to a \nMan-in-the-Middle (MitM) attack where an attacker\ | |
| \ intercepts and manipulates communication \nbetween the app and the server. \n\ | |
| \nTo fix this security issue, you should properly handle SSL errors and only proceed\ | |
| \ with \nthe connection if the SSL certificate is valid and trusted. Here's an\ | |
| \ example code in Java:\n``` \npublic class MyWebViewClient extends WebViewClient\ | |
| \ { \n @Override\n public void onReceivedSslError(WebView view, SslErrorHandler\ | |
| \ handler, SslError error) {\n // Check the SSL error type\n switch (error.getPrimaryError())\ | |
| \ {\n case SslError.SSL_UNTRUSTED:\n // Certificate is untrusted\n\ | |
| \ // Handle the error appropriately, such as showing an error message\n\ | |
| \ break;\n case SslError.SSL_EXPIRED:\n // Certificate has\ | |
| \ expired\n // Handle the error appropriately\n break;\n case\ | |
| \ SslError.SSL_IDMISMATCH:\n // Certificate hostname mismatch\n \ | |
| \ // Handle the error appropriately\n break;\n case SslError.SSL_NOTYETVALID:\n\ | |
| \ // Certificate is not yet valid\n // Handle the error appropriately\n\ | |
| \ break;\n }\n // Cancel the connection\n // This prevents the\ | |
| \ WebView from loading the content\n handler.cancel();\n }\n}\n```\n" | |
| languages: | |
| - java | |
| severity: WARNING | |
| metadata: | |
| category: security | |
| cwe: CWE-295 | |
| shortDescription: Improper certificate validation" | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| - id: java_csrf_rule-SpringCSRFDisabled | |
| languages: | |
| - java | |
| pattern-either: | |
| - pattern: (org.springframework.security.config.annotation.web.builders.HttpSecurity | |
| $H). ... .csrf(...). ... .requireCsrfProtectionMatcher(...) | |
| - pattern: (org.springframework.security.config.annotation.web.builders.HttpSecurity | |
| $H). ... .csrf(...). ... .disable(...) | |
| - pattern: (org.springframework.security.config.annotation.web.configurers.CsrfConfigurer<HttpSecurity> | |
| $C). ... .disable(); | |
| message: "The application fails to protect against Cross-Site Request Forgery (CSRF)\n\ | |
| due to disabling Spring's CSRF protection features.\n\nThis vulnerability may\ | |
| \ allow attackers to carry out CSRF attacks by crafting \nmalicious links or forms\ | |
| \ on external websites. Victims who are tricked into \naccessing these links while\ | |
| \ authenticated in your application could inadvertently \nperform actions that\ | |
| \ the attacker intends, such as changing user information, \ninitiating transactions,\ | |
| \ or altering permissions.\n\nTo remediate this issue, remove the call to `HttpSecurity.csrf().disable()`\ | |
| \ or \nremove the custom `CsrfConfigurer`.\n\nFor more information on CSRF protection\ | |
| \ in Spring see:\nhttps://docs.spring.io/spring-security/reference/servlet/exploits/csrf.html#servlet-csrf\n\ | |
| \nAdditionally, consider setting all session cookies to have the `SameSite=Strict`\ | |
| \ \nattribute. It should be noted that this may impact usability when sharing\ | |
| \ links \nacross other mediums.\nIt is recommended that a two cookie based approach\ | |
| \ is taken, as outlined in the\n[Top level\nnavigations](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-08#section-8.8.2)\n\ | |
| section of the SameSite RFC.\n\nFor more information on CSRF see OWASP's guide:\n\ | |
| https://owasp.org/www-community/attacks/csrf\n" | |
| metadata: | |
| shortDescription: Cross-Site Request Forgery (CSRF) | |
| category: security | |
| cwe: CWE-352 | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| security-severity: Medium | |
| severity: WARNING | |
| - id: java_csrf_rule-UnrestrictedRequestMapping | |
| languages: | |
| - java | |
| patterns: | |
| - pattern-inside: '@RequestMapping(...) | |
| $RETURNTYPE $METHOD(...) { ... } | |
| ' | |
| - pattern-not-inside: '@RequestMapping(..., method = $X, ...) | |
| $RETURNTYPE $METHOD(...) { ... } | |
| ' | |
| - pattern: 'RequestMapping | |
| ' | |
| message: "Detected a method annotated with 'RequestMapping' that does not specify\n\ | |
| the HTTP method. CSRF protections are not enabled for GET, HEAD, TRACE, or\nOPTIONS,\ | |
| \ and by default all HTTP methods are allowed when the HTTP method\nis not explicitly\ | |
| \ specified. This means that a method that performs state\nchanges could be vulnerable\ | |
| \ to CSRF attacks. Cross-Site Request Forgery (CSRF) \nis a security vulnerability\ | |
| \ where an attacker tricks a user into performing \nunintended actions on a web\ | |
| \ application where they are authenticated. This \ncan lead to unauthorized actions\ | |
| \ like changing user settings, transferring \nfunds, or altering passwords, all\ | |
| \ without the user's knowledge, by exploiting \nthe trust a web application has\ | |
| \ in the user's browser.\n\nTo mitigate, add the 'method' field and specify the\ | |
| \ HTTP method (such as \n'RequestMethod.POST').\n\nSecure Code Example:\n```\n\ | |
| @RequestMapping(value = \"/path\", method = RequestMethod.POST)\npublic void safe()\ | |
| \ {\n // State-changing operations performed within this method.\n}\n```\n" | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Cross-site request forgery (CSRF) | |
| category: security | |
| cwe: CWE-352 | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| security-severity: MEDIUM | |
| source-rule-url: https://find-sec-bugs.github.io/bugs.htm#SPRING_CSRF_UNRESTRICTED_REQUEST_MAPPING | |
| references: | |
| - https://find-sec-bugs.github.io/bugs.htm#SPRING_CSRF_UNRESTRICTED_REQUEST_MAPPING | |
| technology: | |
| - spring | |
| cwe2022-top25: 'true' | |
| cwe2021-top25: 'true' | |
| subcategory: | |
| - audit | |
| likelihood: LOW | |
| impact: MEDIUM | |
| confidence: LOW | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Cross-Site Request Forgery (CSRF) | |
| - id: java_xpathi_rule-XpathInjection | |
| languages: | |
| - java | |
| message: "The application processes `XPath` queries with potentially malicious input.\n\ | |
| An adversary who is able to control the XPath query could potentially influence\ | |
| \ the logic\nof how data is retrieved, processed or even bypass protections.\n\ | |
| \nTo mitigate the vulnerability, avoid using user input in XPath queries.\nIf\ | |
| \ it cannot be avoided, validate the user input against an allowlist\nof expected\ | |
| \ values before using it in the query. \n\nFollowing is an example that demonstrates\ | |
| \ how to perform an XPath query \nusing user input validated against an allowlist.\n\ | |
| \nSecure code example:\n```\npublic class SecureXPathWithoutResolver {\n\n private\ | |
| \ static final List<String> ALLOWED_AUTHORS = List.of(\"Author1\", \"Author2\"\ | |
| , \"Author3\");\n\n public static void main(String[] args) {\n try {\n \ | |
| \ String userInput = \"Author1\"; // Example user input\n if (ALLOWED_AUTHORS.contains(userInput))\ | |
| \ {\n // User input is safe to use\n DocumentBuilderFactory\ | |
| \ factory = DocumentBuilderFactory.newInstance();\n DocumentBuilder builder\ | |
| \ = factory.newDocumentBuilder();\n Document doc = builder.parse(\"path/to/your/xmlfile.xml\"\ | |
| );\n\n XPathFactory xpathFactory = XPathFactory.newInstance();\n \ | |
| \ XPath xpath = xpathFactory.newXPath();\n\n // Safely embed the\ | |
| \ validated user input into the XPath expression\n String expression\ | |
| \ = String.format(\"//books/book[author='%s']\", userInput);\n NodeList\ | |
| \ nodes = (NodeList) xpath.evaluate(expression, doc, XPathConstants.NODESET);\n\ | |
| \n for (int i = 0; i < nodes.getLength(); i++) {\n System.out.println(nodes.item(i).getTextContent());\n\ | |
| \ }\n } else {\n throw new IllegalArgumentException(\"\ | |
| Input is not allowed.\");\n }\n } catch (Exception e) {\n e.printStackTrace();\n\ | |
| \ }\n }\n}\n```\n\nFor more information on XPath Injection see:\n- https://owasp.org/www-community/attacks/XPATH_Injection\n" | |
| metadata: | |
| shortDescription: Improper neutralization of data within XPath expressions ('XPath | |
| Injection') | |
| category: security | |
| cwe: CWE-643 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| security-severity: Medium | |
| mode: taint | |
| pattern-sources: | |
| - pattern-either: | |
| - pattern: '(HttpServletRequest $REQ).$FUNC(...) | |
| ' | |
| - patterns: | |
| - pattern-inside: '$FUNC(..., $VAR, ...) { | |
| ... | |
| } | |
| ' | |
| - pattern: $VAR | |
| pattern-sinks: | |
| - pattern-either: | |
| - patterns: | |
| - pattern-inside: '(javax.xml.xpath.XPath $XP). ... .evaluate($EXP, ...); | |
| ' | |
| - pattern: $EXP | |
| - patterns: | |
| - pattern-inside: '(javax.xml.xpath.XPath $XP). ... .compile($EXP, ...); | |
| ' | |
| - pattern: $EXP | |
| pattern-sanitizers: | |
| - patterns: | |
| - pattern-inside: $MAP.getOrDefault($VAR,"..."); | |
| - pattern: $VAR | |
| - patterns: | |
| - pattern-either: | |
| - pattern: 'if($VALIDATION){ | |
| ... | |
| } | |
| ' | |
| - patterns: | |
| - pattern-inside: '$A = $VALIDATION; | |
| ... | |
| ' | |
| - pattern: "if($A){\n ...\n}\n" | |
| - metavariable-pattern: | |
| metavariable: $VALIDATION | |
| pattern-either: | |
| - pattern: '$AL.contains(...) | |
| ' | |
| - pattern: '$AL.equals(...) | |
| ' | |
| severity: ERROR | |
| - id: java_endpoint_rule-ManuallyConstructedURLs | |
| languages: | |
| - java | |
| severity: ERROR | |
| message: "User data flows into the host portion of this manually-constructed URL.\n\ | |
| This could allow an attacker to send data to their own server, potentially\nexposing\ | |
| \ sensitive data such as cookies or authorization information sent\nwith this\ | |
| \ request. They could also probe internal servers or other\nresources that the\ | |
| \ server running this code can access. (This is called\nserver-side request forgery,\ | |
| \ or SSRF.) Do not allow arbitrary hosts.\nInstead, create an allowlist for approved\ | |
| \ hosts hardcode the correct host,\nor ensure that the user data can only affect\ | |
| \ the path or parameters.\n\nExample of using allowlist:\n```\nArrayList<String>\ | |
| \ allowlist = (ArrayList<String>)\n Arrays.asList(new String[] { \"https://example.com/api/1\"\ | |
| , \"https://example.com/api/2\", \"https://example.com/api/3\"});\n\nif(allowlist.contains(url)){\n\ | |
| \ ...\n}\n```\n" | |
| options: | |
| interfile: true | |
| metadata: | |
| security-severity: CRITICAL | |
| cwe: CWE-918 | |
| owasp: | |
| - A1:2017-Injection | |
| - A10:2021-Server-Side Request Forgery | |
| shortDescription: Detect manually constructed URLs | |
| references: | |
| - https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html | |
| category: security | |
| technology: | |
| - java | |
| - spring | |
| cwe2022-top25: true | |
| cwe2021-top25: true | |
| subcategory: | |
| - vuln | |
| impact: MEDIUM | |
| likelihood: MEDIUM | |
| confidence: MEDIUM | |
| interfile: true | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Server-Side Request Forgery (SSRF) | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: "$METHODNAME(..., @$REQ(...) $TYPE $SOURCE,...) {\n ...\n\ | |
| }\n" | |
| - pattern-inside: "$METHODNAME(..., @$REQ $TYPE $SOURCE,...) {\n ...\n}\n" | |
| - metavariable-regex: | |
| metavariable: $TYPE | |
| regex: ^(?!(Integer|Long|Float|Double|Char|Boolean|int|long|float|double|char|boolean)) | |
| - metavariable-regex: | |
| metavariable: $REQ | |
| regex: (RequestBody|PathVariable|RequestParam|RequestHeader|CookieValue|ModelAttribute) | |
| - focus-metavariable: $SOURCE | |
| pattern-sinks: | |
| - pattern-either: | |
| - pattern: new URL($ONEARG) | |
| - patterns: | |
| - pattern-either: | |
| - pattern: '"$URLSTR" + ... | |
| ' | |
| - pattern: '"$URLSTR".concat(...) | |
| ' | |
| - patterns: | |
| - pattern-inside: 'StringBuilder $SB = new StringBuilder("$URLSTR"); | |
| ... | |
| ' | |
| - pattern: $SB.append(...) | |
| - patterns: | |
| - pattern-inside: '$VAR = "$URLSTR"; | |
| ... | |
| ' | |
| - pattern: $VAR += ... | |
| - patterns: | |
| - pattern: String.format("$URLSTR", ...) | |
| - pattern-not: String.format("$URLSTR", "...", ...) | |
| - patterns: | |
| - pattern-inside: 'String $VAR = "$URLSTR"; | |
| ... | |
| ' | |
| - pattern: String.format($VAR, ...) | |
| - metavariable-regex: | |
| metavariable: $URLSTR | |
| regex: http(s?)://%(v|s|q).* | |
| pattern-sanitizers: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: "if($VALIDATION){\n ...\n new URL($ONEARG);\n ...\n} \n" | |
| - pattern: "$A = $VALIDATION;\n...\nif($A){\n ...\n new URL($ONEARG);\n ...\n\ | |
| }\n" | |
| - metavariable-pattern: | |
| metavariable: $VALIDATION | |
| pattern-either: | |
| - pattern: "$AL.contains(...) \n" | |
| - pattern: '$AL.indexOf(...) != -1 | |
| ' | |
| - id: java_traversal_rule-RelativePathTraversal | |
| languages: | |
| - java | |
| message: "Detected user input controlling a file path. An attacker could control\n\ | |
| the location of this file, to include going backwards in the directory\nwith '../'.\ | |
| \ \n\nTo address this, ensure that user-controlled variables in file\npaths are\ | |
| \ sanitized. You may also consider using a utility method such as\norg.apache.commons.io.FilenameUtils.getName(...)\ | |
| \ to only retrieve the file\nname from the path.\n\nExample of using `org.apache.commons.io.FilenameUtils.getName(...)`\ | |
| \ to \nonly retrieve the file name from the path\n```\nString fileName = org.apache.commons.io.FilenameUtils.getName(userControlledInput);\n\ | |
| File file = new File(\"/path/to/directory/\" + fileName);\n```\n" | |
| options: | |
| interfile: true | |
| severity: ERROR | |
| metadata: | |
| cwe: CWE-23 | |
| shortDescription: Relative Path Traversal | |
| owasp: | |
| - A01:2021-Broken Access Control | |
| - A5:2017-Broken Access Control | |
| references: | |
| - https://owasp.org/www-community/attacks/Path_Traversal | |
| category: security | |
| security-severity: CRITICAL | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern-either: | |
| - pattern-inside: "$METHODNAME(..., @$REQ(...) $TYPE $SOURCE,...) {\n ...\n\ | |
| }\n" | |
| - pattern-inside: "$METHODNAME(..., @$REQ $TYPE $SOURCE,...) {\n ...\n}\n" | |
| - metavariable-regex: | |
| metavariable: $TYPE | |
| regex: ^(?!(Integer|Long|Float|Double|Char|Boolean|int|long|float|double|char|boolean)) | |
| - metavariable-regex: | |
| metavariable: $REQ | |
| regex: (RequestBody|PathVariable|RequestParam|RequestHeader|CookieValue|ModelAttribute) | |
| - focus-metavariable: $SOURCE | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: new File(...) | |
| - pattern: new java.io.File(...) | |
| - pattern: new FileReader(...) | |
| - pattern: new java.io.FileReader(...) | |
| - pattern: new FileInputStream(...) | |
| - pattern: new java.io.FileInputStream(...) | |
| - pattern: (Paths $PATHS).get(...) | |
| - patterns: | |
| - pattern: '$CLASS.$FUNC(...) | |
| ' | |
| - metavariable-regex: | |
| metavariable: $FUNC | |
| regex: ^(getResourceAsStream|getResource)$ | |
| - patterns: | |
| - pattern-either: | |
| - pattern: new ClassPathResource($FILE, ...) | |
| - pattern: ResourceUtils.getFile($FILE, ...) | |
| - pattern: new FileOutputStream($FILE, ...) | |
| - pattern: new java.io.FileOutputStream($FILE, ...) | |
| - pattern: new StreamSource($FILE, ...) | |
| - pattern: new javax.xml.transform.StreamSource($FILE, ...) | |
| - pattern: FileUtils.openOutputStream($FILE, ...) | |
| - focus-metavariable: $FILE | |
| pattern-sanitizers: | |
| - pattern: org.apache.commons.io.FilenameUtils.getName(...) | |
| - id: java_cookie_rule-CookieHTTPOnly | |
| languages: | |
| - java | |
| patterns: | |
| - pattern-either: | |
| - pattern: ($X.servlet.http.Cookie $COOKIE).setHttpOnly(false); | |
| - patterns: | |
| - pattern-not-inside: ($X.servlet.http.Cookie $COOKIE).setHttpOnly(...); ... | |
| - pattern: $RESPONSE.addCookie($COOKIE); | |
| message: 'The `HttpOnly` attribute when set to `true` protects the cookie value | |
| from being accessed by | |
| client side JavaScript such | |
| as reading the `document.cookie` values. By enabling this protection, a website | |
| that is | |
| vulnerable to | |
| Cross-Site Scripting (XSS) will be able to block malicious scripts from accessing | |
| the cookie | |
| value from JavaScript. | |
| Example of protecting a `Cookie`: | |
| ``` | |
| // Create an HttpOnly cookie. | |
| Cookie someCookie = new Cookie("SomeCookieName", "SomeValue"); | |
| // Set HttpOnly flag to true | |
| someCookie.setHttpOnly(true); | |
| ``` | |
| For more information see: | |
| https://jakarta.ee/specifications/servlet/4.0/apidocs/javax/servlet/http/cookie#setHttpOnly-boolean- | |
| Session cookies should be configured with the following security directives: | |
| - [HTTPOnly](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies) | |
| - [Secure](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies) | |
| - [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) | |
| ' | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Sensitive cookie without 'HttpOnly' flag | |
| category: security | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| cwe: CWE-1004 | |
| technology: | |
| - java | |
| security-severity: Low | |
| - id: java_deserialization_rule-SnakeYamlConstructor | |
| languages: | |
| - java | |
| patterns: | |
| - pattern: '$Y = new org.yaml.snakeyaml.Yaml(); | |
| ... | |
| $Y.load(...); | |
| ' | |
| message: "The application uses SnakeYAML org.yaml.snakeyaml.Yaml() constructor \n\ | |
| with no arguments, which is vulnerable to deserialization attacks. \nWhen Yaml()\ | |
| \ (no-argument constructor) is used, SnakeYAML uses the \ndefault Constructor\ | |
| \ which can instantiate any Java object during \ndeserialization. This is risky\ | |
| \ because an attacker could craft malicious \nYAML files to execute arbitrary\ | |
| \ code or perform unauthorized actions.\n\nTo mitigate the issue and to safely\ | |
| \ use SnakeYaml to parse YAML data, \nalways make sure to only ever use a Yaml\ | |
| \ instance that is constructed \neither with a SafeConstructor or an instance\ | |
| \ constructed with a \nConstructor specifying a specific class. \n\nPlease note,\ | |
| \ if you want to use Constructor with a specific target class\nas a mitigation\ | |
| \ criteria, ensure that snakeyaml version is 2.0 or higher\nas Constructor class\ | |
| \ is vulnerable in snakeyaml versions lower than 2.0.\nRefer - https://github.com/google/security-research/security/advisories/GHSA-mjmj-j48q-9wg2\n\ | |
| \nSecure Code Examples:\n```\npublic void safeConstructorLoad(String toLoad) {\n\ | |
| \ // Configure LoaderOptions for safe deserialization\n LoaderOptions loaderOptions\ | |
| \ = new LoaderOptions();\n loaderOptions.setAllowDuplicateKeys(false);\n loaderOptions.setMaxAliasesForCollections(50);\n\ | |
| \n Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptipon()));\n yaml.load(toLoad);\n\ | |
| }\n\npublic void customConstructorLoad(String toLoad, Class<?> goodClass) {\n\ | |
| \ // Use Constructor with a specific target class\n LoaderOptions loaderOptions\ | |
| \ = new LoaderOptions();\n Constructor customConstructor = new Constructor(goodClass,\ | |
| \ loaderOptions);\n\n Yaml yaml = new Yaml(customConstructor);\n yaml.load(toLoad);\n\ | |
| }\n```\n" | |
| metadata: | |
| cwe: CWE-502 | |
| owasp: | |
| - A8:2017-Insecure Deserialization | |
| - A08:2021-Software and Data Integrity Failures | |
| category: security | |
| shortDescription: Deserialization of untrusted data | |
| security-severity: HIGH | |
| references: | |
| - https://securitylab.github.com/research/swagger-yaml-parser-vulnerability/#snakeyaml-deserialization-vulnerability | |
| technology: | |
| - snakeyaml | |
| likelihood: LOW | |
| impact: HIGH | |
| confidence: LOW | |
| severity: ERROR | |
| - id: java_deserialization_rule-InsecureJmsDeserialization | |
| languages: | |
| - java | |
| patterns: | |
| - pattern-inside: "class $JMS_LISTENER implements MessageListener {\n ...\n public\ | |
| \ void onMessage(Message $JMS_MSG) {\n ...\n }\n}\n" | |
| - pattern: $Y.getObject(...); | |
| message: "Deserialization of untrusted JMS ObjectMessage can lead to arbitrary \n\ | |
| code execution. This vulnerability occurs when `ObjectMessage.getObject()` \n\ | |
| is called to deserialize the payload of an ObjectMessage, potentially \nallowing\ | |
| \ remote attackers to execute arbitrary code with the permissions \nof the JMS\ | |
| \ MessageListener application. \n\nTo mitigate the issue, avoid deserialization\ | |
| \ of untrusted data and \nconsider alternative message formats or explicit whitelisting\ | |
| \ of \nallowable classes for deserialization.\n\nTo implement allowlisting, override\ | |
| \ the ObjectInputStream#resolveClass() \nmethod to limit deserialization to allowed\ | |
| \ classes only. This prevents \ndeserialization of any class except those explicitly\ | |
| \ permitted, such as \nin the following example that restricts deserialization\ | |
| \ to the Bicycle \nclass only:\n\n```\n// Code from https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html\n\ | |
| public class LookAheadObjectInputStream extends ObjectInputStream {\n public\ | |
| \ LookAheadObjectInputStream(InputStream inputStream) throws IOException {\n \ | |
| \ super(inputStream);\n }\n /**\n * Only deserialize instances\ | |
| \ of our expected Bicycle class\n */\n @Override\n protected Class<?>\ | |
| \ resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException\ | |
| \ {\n if (!desc.getName().equals(Bicycle.class.getName())) {\n \ | |
| \ throw new InvalidClassException(\"Unauthorized deserialization attempt\"\ | |
| , desc.getName());\n }\n return super.resolveClass(desc);\n }\n\ | |
| }\n```\n" | |
| metadata: | |
| cwe: CWE-502 | |
| owasp: | |
| - A8:2017-Insecure Deserialization | |
| - A08:2021-Software and Data Integrity Failures | |
| category: security | |
| shortDescription: Deserialization of untrusted data | |
| security-severity: High | |
| references: | |
| - https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities-wp.pdf | |
| technology: | |
| - java | |
| cwe2022-top25: 'true' | |
| cwe2021-top25: 'true' | |
| subcategory: | |
| - vuln | |
| likelihood: LOW | |
| impact: MEDIUM | |
| confidence: MEDIUM | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - 'Insecure Deserialization ' | |
| severity: ERROR | |
| - id: java_deserialization_rule-ServerDangerousObjectDeserialization | |
| languages: | |
| - java | |
| patterns: | |
| - pattern-inside: "interface $INTERFACE extends Remote {\n ...\n}\n" | |
| - pattern: '$RETURNTYPE $METHOD($PARAMTYPE $PARAM) throws RemoteException; | |
| ' | |
| - metavariable-pattern: | |
| metavariable: $PARAMTYPE | |
| language: generic | |
| patterns: | |
| - pattern-not: String | |
| - pattern-not: java.lang.String | |
| - pattern-not: boolean | |
| - pattern-not: Boolean | |
| - pattern-not: java.lang.Boolean | |
| - pattern-not: byte | |
| - pattern-not: Byte | |
| - pattern-not: java.lang.Byte | |
| - pattern-not: char | |
| - pattern-not: Character | |
| - pattern-not: java.lang.Character | |
| - pattern-not: double | |
| - pattern-not: Double | |
| - pattern-not: java.lang.Double | |
| - pattern-not: float | |
| - pattern-not: Float | |
| - pattern-not: java.lang.Float | |
| - pattern-not: int | |
| - pattern-not: Integer | |
| - pattern-not: java.lang.Integer | |
| - pattern-not: long | |
| - pattern-not: Long | |
| - pattern-not: java.lang.Long | |
| - pattern-not: short | |
| - pattern-not: Short | |
| - pattern-not: java.lang.Short | |
| severity: WARNING | |
| metadata: | |
| cwe: CWE-502 | |
| shortDescription: Deserialization of untrusted data | |
| owasp: | |
| - A8:2017-Insecure Deserialization | |
| - A08:2021-Software and Data Integrity Failures | |
| references: | |
| - https://frohoff.github.io/appseccali-marshalling-pickles/ | |
| - https://book.hacktricks.xyz/network-services-pentesting/1099-pentesting-java-rmi | |
| - https://youtu.be/t_aw1mDNhzI | |
| - https://github.com/qtc-de/remote-method-guesser | |
| - https://github.com/openjdk/jdk/blob/master/src/java.rmi/share/classes/sun/rmi/server/UnicastRef.java#L303C4-L331 | |
| - https://mogwailabs.de/en/blog/2019/03/attacking-java-rmi-services-after-jep-290/ | |
| category: security | |
| security-severity: MEDIUM | |
| technology: | |
| - rmi | |
| cwe2022-top25: 'true' | |
| cwe2021-top25: 'true' | |
| likelihood: LOW | |
| impact: HIGH | |
| confidence: LOW | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - 'Insecure Deserialization ' | |
| message: "This application uses Java RMI (Remote Method Invocation) interfaces \n\ | |
| that declare methods with parameters of arbitrary objects \n('$PARAMTYPE $PARAM')\ | |
| \ that could lead to insecure deserialization \nvulnerabilities. Insecure deserialization\ | |
| \ occurs when an application \ndeserializes data from untrusted sources without\ | |
| \ proper sanitization, \npotentially leading to arbitrary code execution, denial\ | |
| \ of service attacks, \nand other critical vulnerabilities.\n\nJava RMI allows\ | |
| \ for remote communication between applications by \ninvoking methods on remote\ | |
| \ objects. When complex objects are used \nas parameters in RMI method declarations,\ | |
| \ there is \na risk that a malicious actor could exploit the deserialization \n\ | |
| process to execute arbitrary code on the server. This vulnerability \nis especially\ | |
| \ significant if the parameter types are not among the safe, \nimmutable types\ | |
| \ like String, Integer, etc.\n\nTo mitigate this vulnerability, use an integer\ | |
| \ ID to look up your \nobject, or consider alternative serialization schemes such\ | |
| \ as JSON.\n\nSecure Code Example:\n```\nimport java.rmi.Remote;\nimport java.rmi.RemoteException;\n\ | |
| \npublic interface SafeTicketService extends Remote {\n // Using String, which\ | |
| \ is a safe, immutable type\n boolean registerTicket(String ticketID) throws\ | |
| \ RemoteException;\n\n // Using primitive data types and wrappers, which are\ | |
| \ safe\n void visitTalk(int talkID) throws RemoteException;\n void poke(Integer\ | |
| \ attendeeID) throws RemoteException;\n}\n```\n" | |
| - id: rules_lgpl_oc_other_rule-ios-self-signed-ssl | |
| pattern-either: | |
| - pattern: canAuthenticateAgainstProtectionSpace | |
| - pattern: continueWithoutCredentialForAuthenticationChallenge | |
| - pattern: kCFStreamSSLAllowsExpiredCertificates | |
| - pattern: kCFStreamSSLAllowsAnyRoot | |
| - pattern: kCFStreamSSLAllowsExpiredRoots | |
| - patterns: | |
| - pattern: validatesSecureCertificate = $NO | |
| - metavariable-regex: | |
| metavariable: $NO | |
| regex: NO|no | |
| - patterns: | |
| - pattern: allowInvalidCertificates = $YES | |
| - metavariable-regex: | |
| metavariable: $YES | |
| regex: YES|yes | |
| paths: | |
| include: | |
| - '**/*.m' | |
| message: "App allows self signed or invalid SSL certificates. App is \nvulnerable\ | |
| \ to MITM attacks. If the app does not verify the \nauthenticity of the server's\ | |
| \ SSL certificate, an attacker could \nimpersonate the server and intercept sensitive\ | |
| \ data transmitted \nbetween the app and the server.\nTo fix these security issues,\ | |
| \ you should ensure proper SSL \ncertificate validation in your Objective-C code.\ | |
| \ Here's how you \ncan do it:\n```\n- (void)loadSecureURL {\n NSURL *url = [NSURL\ | |
| \ URLWithString:@\"https://example.com\"];\n NSURLRequest *request = [NSURLRequest\ | |
| \ requestWithURL:url];\n\n // Create session configuration\n NSURLSessionConfiguration\ | |
| \ *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];\n\ | |
| \ configuration.TLSMinimumSupportedProtocol = kTLSProtocol12;\n\n // Create\ | |
| \ session with configuration\n NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];\n\ | |
| \n // Create data task\n NSURLSessionDataTask *task = [session dataTaskWithRequest:request\ | |
| \ completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response,\ | |
| \ NSError * _Nullable error) {\n if (error) {\n NSLog(@\"Error loading\ | |
| \ URL: %@\", error);\n // Handle error\n } else {\n //\ | |
| \ Handle response\n NSLog(@\"Response: %@\", response);\n }\n }];\n\ | |
| \n // Start task\n [task resume];\n}\n\n```\n" | |
| languages: | |
| - generic | |
| severity: ERROR | |
| metadata: | |
| category: security | |
| cwe: CWE-676 | |
| shortDescription: Use of potentially dangerous function | |
| owasp: | |
| - A9:2017-Using Components with Known Vulnerabilities | |
| - A06:2021-Vulnerable and Outdated Components | |
| security-severity: CRITICAL | |
| - id: rules_lgpl_oc_other_rule-ios-webview-ignore-ssl | |
| pattern-either: | |
| - pattern: allowsAnyHTTPSCertificateForHost | |
| - patterns: | |
| - pattern: loadingUnvalidatedHTTPSPage = $YES | |
| - metavariable-regex: | |
| metavariable: $YES | |
| regex: YES|yes | |
| - patterns: | |
| - pattern: allowsAnyHTTPSCertificate = $YES | |
| - metavariable-regex: | |
| metavariable: $YES | |
| regex: YES|yes | |
| paths: | |
| include: | |
| - '**/*.m' | |
| message: "UIWebView in App ignore SSL errors and accept any SSL Certificate. \n\ | |
| App is vulnerable to MITM attacks. If the app does not verify the \nauthenticity\ | |
| \ of the server's SSL certificate, an attacker could \nimpersonate the server\ | |
| \ and intercept sensitive data transmitted \nbetween the app and the server.\n\ | |
| To fix these security issues, you should ensure proper SSL certificate \nvalidation\ | |
| \ in your Objective-C code. Here's how you can do it:\n```\n- (void)loadSecureURL\ | |
| \ {\n NSURL *url = [NSURL URLWithString:@\"https://example.com\"];\n NSURLRequest\ | |
| \ *request = [NSURLRequest requestWithURL:url];\n \n // Create session configuration\n\ | |
| \ NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];\n\ | |
| \ configuration.TLSMinimumSupportedProtocol = kTLSProtocol12;\n \n // Create\ | |
| \ session with configuration\n NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];\n\ | |
| \ \n // Create data task\n NSURLSessionDataTask *task = [session dataTaskWithRequest:request\ | |
| \ completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response,\ | |
| \ NSError * _Nullable error) {\n if (error) {\n NSLog(@\"Error loading\ | |
| \ URL: %@\", error);\n // Handle error\n } else {\n //\ | |
| \ Handle response\n NSLog(@\"Response: %@\", response);\n }\n }];\n\ | |
| \ \n // Start task\n [task resume];\n}\n```\n" | |
| languages: | |
| - generic | |
| severity: ERROR | |
| metadata: | |
| category: security | |
| cwe: CWE-295 | |
| shortDescription: Improper certificate validation | |
| owasp: | |
| - A6:2017-Security Misconfiguration | |
| - A05:2021-Security Misconfiguration | |
| security-severity: CRITICAL | |
| - id: python_crypto_rule-HTTPConnectionPool | |
| languages: | |
| - python | |
| pattern-either: | |
| - pattern: urllib3.HTTPConnectionPool(...) | |
| - pattern: urllib3.connectionpool.HTTPConnectionPool(...) | |
| message: "The application is using HTTPConnectionPool method. This method transmits\n\ | |
| data in cleartext, which is vulnerable to MITM (Man in the middle)\nattacks. In\ | |
| \ MITM attacks, the data transmitted over the unencrypted\nconnection can be intercepted,\ | |
| \ read and/or modified by unauthorized\nparties which can lead to data integrity\ | |
| \ and confidentiality loss. \n\nTo mitigate this issue, use HTTPSConnectionPool\ | |
| \ instead, which encrypts \ncommunications and enhances security.\n\nSecure Code\ | |
| \ Example:\n```\nimport urllib3\nspool = urllib3.connectionpool.HTTPSConnectionPool(\"\ | |
| example.com\")\n```\n" | |
| metadata: | |
| category: security | |
| cwe: CWE-319 | |
| shortDescription: Cleartext transmission of sensitive information | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| security-severity: MEDIUM | |
| references: | |
| - https://urllib3.readthedocs.io/en/1.2.1/pools.html#urllib3.connectionpool.HTTPSConnectionPool | |
| technology: | |
| - python | |
| subcategory: | |
| - audit | |
| likelihood: MEDIUM | |
| impact: MEDIUM | |
| confidence: MEDIUM | |
| severity: WARNING | |
| - id: python_escaping_rule-django | |
| languages: | |
| - python | |
| message: 'Cross Site Scripting (XSS) is an attack which exploits a web application | |
| or system to treat | |
| user input | |
| as markup or script code. It is important to encode the data depending on the | |
| specific context | |
| it | |
| is used in. There are at least six context types: | |
| - Inside HTML tags `<div>context 1</div>` | |
| - Inside attributes: `<div class="context 2"></div>` | |
| - Inside event attributes `<button onclick="context 3">button</button>` | |
| - Inside script blocks: `<script>var x = "context 4"</script>` | |
| - Unsafe element HTML assignment: `element.innerHTML = "context 5"` | |
| - Inside URLs: `<iframe src="context 6"></iframe><a href="context 6">link</a>` | |
| Script blocks alone have multiple ways they need to be encoded. Extra care must | |
| be taken if | |
| user input | |
| is ever output inside of script tags. | |
| User input that is displayed within the application must be encoded, sanitized | |
| or validated | |
| to ensure it cannot be treated as HTML or executed as Javascript code. Care must | |
| also be | |
| taken | |
| to not mix server-side templating with client-side templating, as the server-side | |
| templating | |
| will | |
| not encode things like {{ 7*7 }} which may execute client-side templating features. | |
| It is _NOT_ advised to encode user input prior to inserting into a data store. | |
| The data will | |
| need to be | |
| encoded depending on context of where it is output. It is much safer to force | |
| the displaying | |
| system to | |
| handle the encoding and not attempt to guess how it should be encoded. | |
| Consider using | |
| [format_html](https://docs.djangoproject.com/en/4.2/ref/utils/#django.utils.html.format_html) | |
| instead of | |
| the `django.utils.safestring` methods. | |
| Example using `format_html`: | |
| ``` | |
| # Use format_html to create an HTML link, using href as the parameter | |
| # which will be encoded automatically | |
| format_html("<li><a href=''{}''>Some Link</a></li>", href) | |
| ``` | |
| For more information on XSS see OWASP: | |
| - https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html | |
| ' | |
| metadata: | |
| cwe: CWE-79 | |
| owasp: | |
| - A7:2017-Cross-Site Scripting (XSS) | |
| - A03:2021-Injection | |
| category: security | |
| shortDescription: Improper neutralization of input during web page generation | |
| ('Cross-site Scripting') | |
| security-severity: Medium | |
| patterns: | |
| - pattern-not-inside: django.utils.html.format_html(...) | |
| - pattern-either: | |
| - patterns: | |
| - pattern: django.utils.safestring.SafeText(...) | |
| - pattern-not: django.utils.safestring.SafeText("...") | |
| - patterns: | |
| - pattern: django.utils.safestring.SafeUnicode(...) | |
| - pattern-not: django.utils.safestring.SafeUnicode("...") | |
| - patterns: | |
| - pattern: django.utils.safestring.SafeString(...) | |
| - pattern-not: django.utils.safestring.SafeString("...") | |
| - patterns: | |
| - pattern: django.utils.safestring.SafeBytes(...) | |
| - pattern-not: django.utils.safestring.SafeBytes("...") | |
| - patterns: | |
| - pattern: django.utils.safestring.mark_safe(...) | |
| - pattern-not: django.utils.safestring.mark_safe("...") | |
| severity: WARNING | |
| - id: python_django_rule-django-raw-used | |
| message: "SQL Injections are a critical type of vulnerability that can lead to data\ | |
| \ \nor system compromise. By dynamically generating SQL query strings, user \n\ | |
| input may be able to influence the logic of the SQL statement. \nThis could lead\ | |
| \ to an adversary accessing information they should not \nhave access to, or in\ | |
| \ some circumstances, being able to execute OS functionality\nor code.\n\nReplace\ | |
| \ all dynamically generated SQL queries with parameterized queries. \nIn situations\ | |
| \ where dynamic queries must be created, never use direct user input,\nbut instead\ | |
| \ use a map or dictionary of valid values and resolve them using a user \nsupplied\ | |
| \ key.\n\nFor example, some database drivers do not allow parameterized queries\ | |
| \ for \n`>` or `<` comparison operators. In these cases, do not use a user supplied\ | |
| \ \n`>` or `<` value, but rather have the user supply a `gt` or `lt` value. \n\ | |
| The alphabetical values are then used to look up the `>` and `<` values to be\ | |
| \ used \nin the construction of the dynamic query. The same goes for other queries\ | |
| \ where \ncolumn or table names are required but cannot be parameterized.\n\n\ | |
| Data that is possible user-controlled from a python request is passed\nto `raw()`\ | |
| \ function. To remediate this issue, use django's QuerySets, \nwhich are built\ | |
| \ with query parameterization and therefore not vulnerable \nto sql injection.\ | |
| \ For example, you could use `Entry.objects.filter(date=2006)`\n\nIf for some\ | |
| \ reason this is not feasible, ensure calls including user-supplied \ndata pass\ | |
| \ it in to the `params` parameter of the `raw()` method.\nBelow is an example\ | |
| \ using `raw()`, passing in user-supplied data as `params`. \nThis will treat\ | |
| \ the query as a parameterized query and `params` as strictly data, \npreventing\ | |
| \ any possibility of SQL Injection.\n\n```\ndef test(request):\n uname = request.GET[\"\ | |
| username\"] \n res = User.objects.raw('SELECT * FROM myapp_user WHERE username\ | |
| \ = %s', (uname,))\n```\n\nFor more information on QuerySet see:\n- https://docs.djangoproject.com/en/5.0/ref/models/querysets/\n\ | |
| \nFor more information on SQL Injection see OWASP:\n- https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html\n" | |
| metadata: | |
| cwe: CWE-89 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| category: security | |
| shortDescription: Improper neutralization of special elements used in an SQL Command | |
| ('SQL Injection') | |
| security-severity: High | |
| languages: | |
| - python | |
| severity: ERROR | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern: $PARAM | |
| - pattern-inside: "def $VIEW(...,$PARAM,...):\n ...\n return ... \n" | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: $QUERY | |
| - pattern-inside: $MODEL.objects.raw($QUERY, ... ) | |
| - id: python_django_rule-django-rawsql-used | |
| languages: | |
| - python | |
| message: "SQL Injections are a critical type of vulnerability that can lead to data\ | |
| \ or system compromise. By \ndynamically generating SQL query strings, user input\ | |
| \ may be able to influence the logic of the SQL \nstatement. This could lead to\ | |
| \ an adversary accessing information they should not have access to, or in\nsome\ | |
| \ circumstances, being able to execute OS functionality or code.\n\nReplace all\ | |
| \ dynamically generated SQL queries with parameterized queries. In situations\ | |
| \ where dynamic \nqueries must be created, never use direct user input, but instead\ | |
| \ use a map or dictionary of valid values \nand resolve them using a user supplied\ | |
| \ key.\n\nFor example, some database drivers do not allow parameterized queries\ | |
| \ for `>` or `<` comparison operators. \nIn these cases, do not use a user supplied\ | |
| \ `>` or `<` value, but rather have the user supply a `gt` or `lt` \nvalue. The\ | |
| \ alphabetical values are then used to look up the `>` and `<` values to be used\ | |
| \ in the \nconstruction of the dynamic query. The same goes for other queries\ | |
| \ where column or table names are required \nbut cannot be parameterized.\n\n\ | |
| To remediate this issue, do not use `raw` or `RawSQL` but use other `QuerySet`\ | |
| \ methods to achieve the same\ngoals. If for some reason this is not feasible,\ | |
| \ ensure calls including user-supplied data pass it in to \nthe `params` parameter\ | |
| \ of the `RawSQL` method.\n\nWhile not recommended due to [potential SQL Injection](https://docs.djangoproject.com/en/5.0/ref/models/expressions/#raw-sql-expressions),\ | |
| \ below is an example using `RawSQL`.\nPassing in user-supplied data as a `param`\ | |
| \ which will escape the input:\n\n```\n# If dealing with integer based user input,\ | |
| \ restrict the values to integers only using the\n# path configuration: path('/someview/<int:user_supplied_id>',\ | |
| \ views.some_view, name='someview'),\n\n# views.py\ndef some_view(request, user_supplied_id):\n\ | |
| \ # Never use string interpolation in the `sql` parameter.\n # Never quote the\ | |
| \ `%s` string format such as `... where id='%s'` as this could lead to SQL Injection.\n\ | |
| \ # Pass the user supplied data only in the `params` parameter.\n for obj in\ | |
| \ DBObject.objects.all().annotate(\n val=RawSQL(sql=\"select id from some_secondary_table\ | |
| \ where id=%s\", params=[user_supplied_id])):\n # Work with the results from\ | |
| \ the query\n # ...\n```\n\nFor more information on QuerySets see:\n- https://docs.djangoproject.com/en/4.2/ref/models/querysets/#queryset-api\n\ | |
| \nFor more information on SQL Injection see OWASP:\n- https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html\n" | |
| metadata: | |
| cwe: CWE-89 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| category: security | |
| shortDescription: Improper neutralization of special elements used in an SQL Command | |
| ('SQL Injection') | |
| security-severity: CRITICAL | |
| mode: taint | |
| pattern-sources: | |
| - patterns: | |
| - pattern: $PARAM | |
| - pattern-inside: "def $VIEW(...,$PARAM,...):\n ...\n return ...\n" | |
| pattern-sinks: | |
| - patterns: | |
| - pattern: $QUERY | |
| - pattern-inside: django.db.models.expressions.RawSQL($QUERY, ... ) | |
| severity: ERROR | |
| - id: python_pyramid_rule-pyramid-csrf-origin-check | |
| patterns: | |
| - pattern-inside: '$CONFIG.set_default_csrf_options(..., check_origin=$CHECK_ORIGIN, | |
| ...) | |
| ' | |
| - pattern: '$CHECK_ORIGIN | |
| ' | |
| - metavariable-comparison: | |
| metavariable: $CHECK_ORIGIN | |
| comparison: $CHECK_ORIGIN == False | |
| message: "Automatic check of the referrer for cross-site request forgery tokens\n\ | |
| has been explicitly disabled globally, which might leave views unprotected\nwhen\ | |
| \ an unsafe CSRF storage policy is used. By passing `check_origin=False` \nto\ | |
| \ `set_default_csrf_options()` method, you opt out of checking the origin \nof\ | |
| \ the domain in the referrer header or the origin header, which can make \nthe\ | |
| \ application vulnerable to CSRF attacks, specially if CSRF token is not \nproperly\ | |
| \ implemented.\nCSRF attacks are a type of exploit where an attacker tricks a\ | |
| \ user into \nexecuting unwanted actions on a web application in which they are\ | |
| \ authenticated. \nIf a user is logged into a web application, an attacker could\ | |
| \ create a malicious \nlink or script on another site that causes the user's browser\ | |
| \ to make a request \nto the web application, carrying out an action without the\ | |
| \ user's consent.\n\nTo mitigate this vulnerability, use \n'pyramid.config.Configurator.set_default_csrf_options(check_origin=True)'\n\ | |
| to turn the automatic check for all unsafe methods (per RFC2616).\n\nSecure Code\ | |
| \ Example:\n```\ndef safe(config):\n config.set_csrf_storage_policy(CookieCSRFStoragePolicy())\n\ | |
| \ config.set_default_csrf_options(check_origin=True)\n```\n" | |
| languages: | |
| - python | |
| severity: WARNING | |
| metadata: | |
| shortDescription: Cross-site request forgery (CSRF) | |
| category: security | |
| cwe: CWE-352 | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| security-severity: MEDIUM | |
| technology: | |
| - pyramid | |
| references: | |
| - https://owasp.org/Top10/A01_2021-Broken_Access_Control | |
| - https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/security.html | |
| cwe2022-top25: 'true' | |
| cwe2021-top25: 'true' | |
| subcategory: | |
| - vuln | |
| likelihood: LOW | |
| impact: LOW | |
| confidence: MEDIUM | |
| license: Commons Clause License Condition v1.0[LGPL-2.1-only] | |
| vulnerability_class: | |
| - Cross-Site Request Forgery (CSRF) | |
| - id: python_flask_rule-flask-open-redirect | |
| languages: | |
| - python | |
| patterns: | |
| - pattern-inside: "@$APP.route(...)\ndef $X(...):\n ...\n" | |
| - pattern-not-inside: "@$APP.route(...)\ndef $X(...):\n ...\n if <... werkzeug.urls.url_parse($V)\ | |
| \ ...>:\n ...\n" | |
| - pattern-either: | |
| - pattern: flask.redirect(<... flask.request.$W.get(...) ...>, ...) | |
| - pattern: flask.redirect(<... flask.request.$W[...] ...>, ...) | |
| - pattern: flask.redirect(<... flask.request.$W(...) ...>, ...) | |
| - pattern: flask.redirect(<... flask.request.$W ...>, ...) | |
| - pattern: '$V = flask.request.$W.get(...) | |
| ... | |
| flask.redirect(<... $V ...>, ...) | |
| ' | |
| - pattern: '$V = flask.request.$W[...] | |
| ... | |
| flask.redirect(<... $V ...>, ...) | |
| ' | |
| - pattern: '$V = flask.request.$W(...) | |
| ... | |
| flask.redirect(<... $V ...>, ...) | |
| ' | |
| - pattern: '$V = flask.request.$W | |
| ... | |
| flask.redirect(<... $V ...>, ...) | |
| ' | |
| - pattern-not: flask.redirect(flask.request.path) | |
| - pattern-not: flask.redirect(flask.request.path + ...) | |
| - pattern-not: flask.redirect(f"{flask.request.path}...") | |
| message: "Data from request is passed to redirect(). This is an open redirect and\ | |
| \ could be exploited. Consider using 'url_for()' to generate links to known locations.\ | |
| \ If you must use a URL to unknown pages, consider using 'urlparse()' or similar\ | |
| \ and checking if the 'netloc' property is the same as your site's host name.\ | |
| \ For example:\n\n Example:\n ```python\n from flask import Flask, request,\ | |
| \ redirect, url_for\n from urllib.parse import urlparse\n\n app = Flask(__name__)\n\ | |
| \n @app.route('/login')\n def login():\n next = request.args.get('next')\n\ | |
| \ if not next:\n next = url_for('index')\n if urlparse(next).netloc\ | |
| \ != urlparse(request.url).netloc:\n return redirect(url_for('index'))\n\ | |
| \ return redirect(next)\n ```\n See the references for more information." | |
| metadata: | |
| cwe: CWE-601 | |
| shortDescription: URL redirection to untrusted site ('Open Redirect') | |
| owasp: | |
| - A01:2021-Broken Access Control | |
| - A5:2017-Broken Access Control | |
| category: security | |
| security-severity: MEDIUM | |
| references: '- https://flask-login.readthedocs.io/en/latest/#login-example | |
| - https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html#dangerous-url-redirect-example-1 | |
| - https://docs.python.org/3/library/urllib.parse.html#url-parsing | |
| ' | |
| technology: | |
| - flask | |
| subcategory: | |
| - audit | |
| likelihood: LOW | |
| impact: MEDIUM | |
| confidence: LOW | |
| severity: WARNING | |
| - id: python_flask_rule-path-traversal-open | |
| languages: | |
| - python | |
| severity: ERROR | |
| message: "Found request data in a call to 'open'. An attacker can manipulate this\ | |
| \ input to access files outside the intended \ndirectory. This can lead to unauthorized\ | |
| \ access to sensitive files or directories. To prevent path traversal attacks,\ | |
| \ \navoid using user-controlled input in file paths. If you must use user-controlled\ | |
| \ input, validate and sanitize the \ninput to ensure it does not contain any path\ | |
| \ traversal sequences. For example, you can use the `os.path.join` function \n\ | |
| to safely construct file paths or validate that the absolute path starts with\ | |
| \ the directory which is whitelisted for \naccessing file. The following code\ | |
| \ snippet demonstrates how to validate a file path from user-controlled input:\n\ | |
| ```\nimport os\n\ndef safe_open_file(filename, base_path):\n # Resolve the absolute\ | |
| \ path of the user-supplied filename\n absolute_path = os.path.abspath(filename)\n\ | |
| \n # Check that the absolute path starts with the base path\n if not absolute_path.startswith(base_path):\n\ | |
| \ raise ValueError(\"Invalid file path\")\n\n return open(absolute_path,\ | |
| \ 'r')\n```\nFor more information, see the OWASP Path Traversal page: https://owasp.org/www-community/attacks/Path_Traversal\n" | |
| metadata: | |
| cwe: CWE-22 | |
| shortDescription: Improper Limitation of a Pathname to a Restricted Directory | |
| ('Path Traversal') | |
| owasp: | |
| - A5:2017-Broken Access Control | |
| - A01:2021-Broken Access Control | |
| category: security | |
| security-severity: CRITICAL | |
| references: | |
| - https://owasp.org/www-community/attacks/Path_Traversal | |
| technology: | |
| - flask | |
| likelihood: MEDIUM | |
| impact: HIGH | |
| confidence: MEDIUM | |
| pattern-either: | |
| - patterns: | |
| - pattern: open(...) | |
| - pattern-either: | |
| - pattern-inside: "@$APP.route($ROUTE, ...)\ndef $FUNC(..., $ROUTEVAR, ...):\n\ | |
| \ ...\n open(..., <... $ROUTEVAR ...>, ...)\n" | |
| - pattern-inside: "@$APP.route($ROUTE, ...)\ndef $FUNC(..., $ROUTEVAR, ...):\n\ | |
| \ ...\n with open(..., <... $ROUTEVAR ...>, ...) as $FD:\n ...\n" | |
| - pattern-inside: "@$APP.route($ROUTE, ...)\ndef $FUNC(..., $ROUTEVAR, ...):\n\ | |
| \ ...\n $INTERIM = <... $ROUTEVAR ...>\n ...\n open(..., <... $INTERIM\ | |
| \ ...>, ...)\n" | |
| - pattern: open(..., <... flask.request.$W.get(...) ...>, ...) | |
| - pattern: open(..., <... flask.request.$W[...] ...>, ...) | |
| - pattern: open(..., <... flask.request.$W(...) ...>, ...) | |
| - pattern: open(..., <... flask.request.$W ...>, ...) | |
| - patterns: | |
| - pattern-inside: '$INTERIM = <... flask.request.$W.get(...) ...> | |
| ... | |
| open(<... $INTERIM ...>, ...) | |
| ' | |
| - pattern: open(...) | |
| - patterns: | |
| - pattern-inside: '$INTERIM = <... flask.request.$W[...] ...> | |
| ... | |
| open(<... $INTERIM ...>, ...) | |
| ' | |
| - pattern: open(...) | |
| - patterns: | |
| - pattern-inside: '$INTERIM = <... flask.request.$W(...) ...> | |
| ... | |
| open(<... $INTERIM ...>, ...) | |
| ' | |
| - pattern: open(...) | |
| - patterns: | |
| - pattern-inside: '$INTERIM = <... flask.request.$W ...> | |
| ... | |
| open(<... $INTERIM ...>, ...) | |
| ' | |
| - pattern: open(...) | |
| - patterns: | |
| - pattern-inside: "$INTERIM = <... flask.request.$W.get(...) ...>\n...\nwith open(<...\ | |
| \ $INTERIM ...>, ...) as $F:\n ...\n" | |
| - pattern: open(...) | |
| - patterns: | |
| - pattern-inside: "$INTERIM = <... flask.request.$W[...] ...>\n...\nwith open(<...\ | |
| \ $INTERIM ...>, ...) as $F:\n ...\n" | |
| - pattern: open(...) | |
| - patterns: | |
| - pattern-inside: "$INTERIM = <... flask.request.$W(...) ...>\n...\nwith open(<...\ | |
| \ $INTERIM ...>, ...) as $F:\n ...\n" | |
| - pattern: open(...) | |
| - patterns: | |
| - pattern-inside: "$INTERIM = <... flask.request.$W ...>\n...\nwith open(<...\ | |
| \ $INTERIM ...>, ...) as $F:\n ...\n" | |
| - pattern: open(...) | |
| - id: python_flask_rule-tainted-sql-string | |
| languages: | |
| - python | |
| message: "Detected user input used to manually construct a SQL string. This is usually\n\ | |
| bad practice because manual construction could accidentally result in a SQL\n\ | |
| injection. An attacker could use a SQL injection to steal or modify contents\n\ | |
| of the database. Instead, use a parameterized query which is available\nby default\ | |
| \ in most database engines. Alternatively, consider using an\nobject-relational\ | |
| \ mapper (ORM) such as SQLAlchemy which will protect your queries.\n\nSQL Injections\ | |
| \ are a critical type of vulnerability that can lead to data \nor system compromise.\ | |
| \ By dynamically generating SQL query strings, user \ninput may be able to influence\ | |
| \ the logic of an SQL statement. \nThis could lead to an malicious parties accessing\ | |
| \ information they should not \nhave access to, or in some circumstances, being\ | |
| \ able to execute OS functionality\nor code.\n\nReplace all dynamically generated\ | |
| \ SQL queries with parameterized queries. \nIn situations where dynamic queries\ | |
| \ must be created, never use direct user input,\nbut instead use a map or dictionary\ | |
| \ of valid values and resolve them using a user \nsupplied key.\n\nFor example,\ | |
| \ some database drivers do not allow parameterized queries for \n`>` or `<` comparison\ | |
| \ operators. In these cases, do not use a user supplied \n`>` or `<` value, but\ | |
| \ rather have the user supply a `gt` or `lt` value. \nThe alphabetical values\ | |
| \ are then used to look up the `>` and `<` values to be used \nin the construction\ | |
| \ of the dynamic query. The same goes for other queries where \ncolumn or table\ | |
| \ names are required but cannot be parameterized.\nData that is possible user-controlled\ | |
| \ from a python request is passed\nto `execute()` function. To remediate this\ | |
| \ issue, use SQLAlchemy statements\nwhich are built with query parameterization\ | |
| \ and therefore not vulnerable \nto sql injection.\n\nIf for some reason this\ | |
| \ is not feasible, ensure calls including user-supplied \ndata pass it in to the\ | |
| \ `params` parameter of the `execute()` method.\nBelow is an example using `execute()`,\ | |
| \ passing in user-supplied data as `params`. \nThis will treat the query as a\ | |
| \ parameterized query and `params` as strictly data, \npreventing any possibility\ | |
| \ of SQL Injection.\n\n```\nname = request.args.get('name')\nreq = text('SELECT\ | |
| \ * FROM student WHERE firstname = :x')\nresult = db.session.execute(req, {\"\ | |
| x\":name})\n```\nFor more information on QuerySets see:\n- https://docs.djangoproject.com/en/4.2/ref/models/querysets/#queryset-api\n\ | |
| For more information on SQL Injections see OWASP:\n- https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html\n" | |
| metadata: | |
| security-severity: High | |
| cwe: CWE-89 | |
| owasp: | |
| - A1:2017-Injection | |
| - A03:2021-Injection | |
| category: security | |
| shortDescription: Improper neutralization of special elements used in an SQL Command | |
| ('SQL Injection') | |
| mode: taint | |
| pattern-sources: | |
| - pattern-either: | |
| - pattern: flask.request.$ANYTHING | |
| - patterns: | |
| - pattern-inside: "@$APP.route(...)\ndef $FUNC(..., $ROUTEVAR, ...):\n ...\n" | |
| - pattern: $ROUTEVAR | |
| pattern-sinks: | |
| - patterns: | |
| - pattern-either: | |
| - pattern: '<... "$QUERYLIKE" ...> | |
| ' | |
| - metavariable-regex: | |
| metavariable: $QUERYLIKE | |
| regex: .*\b(?i)(SELECT .+ FROM|WHERE|DELETE FROM|INSERT INTO| CREATE TABLE|UPDATE | |
| .+ SET|ALTER TABLE|ALTER COLUMN|DROP COLUMN|DROP TABLE|ORDER BY)\b.* | |
| severity: ERROR | |
| - id: python_jwt_rule-jwt-none-alg | |
| languages: | |
| - python | |
| message: 'Detected use of the ''none'' algorithm in a JWT token. | |
| The ''none'' algorithm assumes the integrity of the token has already | |
| been verified. This would allow a malicious actor to forge a JWT token | |
| that will automatically be verified. Do not explicitly use the ''none'' | |
| algorithm. Instead, use an algorithm such as ''HS256''. | |
| ' | |
| metadata: | |
| cwe: CWE-327 | |
| shortDescription: Use of a Broken or Risky Cryptographic Algorithm | |
| owasp: | |
| - A3:2017-Sensitive Data Exposure | |
| - A02:2021-Cryptographic Failures | |
| category: security | |
| security-severity: MEDIUM | |
| source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ | |
| technology: | |
| - jwt | |
| references: | |
| - https://owasp.org/Top10/A02_2021-Cryptographic_Failures | |
| subcategory: | |
| - vuln | |
| likelihood: MEDIUM | |
| impact: MEDIUM | |
| confidence: MEDIUM | |
| severity: ERROR | |
| pattern-either: | |
| - pattern: jwt.encode(...,algorithm="none",...) | |
| - pattern: jwt.decode(...,algorithms=[...,"none",...],...) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment