@sun-asterisk/sunlint 1.3.46 → 1.3.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/core/adapters/sunlint-rule-adapter.js +16 -0
  2. package/core/rule-selection-service.js +24 -3
  3. package/engines/heuristic-engine.js +6 -1
  4. package/package.json +2 -2
  5. package/skill-assets/sunlint-code-quality/rules/ruby/C006-verb-noun-functions.md +63 -0
  6. package/skill-assets/sunlint-code-quality/rules/ruby/C013-no-dead-code.md +48 -0
  7. package/skill-assets/sunlint-code-quality/rules/ruby/C014-dependency-injection.md +42 -0
  8. package/skill-assets/sunlint-code-quality/rules/ruby/C017-no-constructor-logic.md +42 -0
  9. package/skill-assets/sunlint-code-quality/rules/ruby/C018-generic-errors.md +41 -0
  10. package/skill-assets/sunlint-code-quality/rules/ruby/C019-error-log-level.md +41 -0
  11. package/skill-assets/sunlint-code-quality/rules/ruby/C020-no-unused-imports.md +36 -0
  12. package/skill-assets/sunlint-code-quality/rules/ruby/C022-no-unused-variables.md +31 -0
  13. package/skill-assets/sunlint-code-quality/rules/ruby/C023-no-duplicate-names.md +39 -0
  14. package/skill-assets/sunlint-code-quality/rules/ruby/C024-centralize-constants.md +35 -0
  15. package/skill-assets/sunlint-code-quality/rules/ruby/C029-catch-log-root-cause.md +34 -0
  16. package/skill-assets/sunlint-code-quality/rules/ruby/C030-custom-error-classes.md +32 -0
  17. package/skill-assets/sunlint-code-quality/rules/ruby/C033-separate-data-access.md +52 -0
  18. package/skill-assets/sunlint-code-quality/rules/ruby/C035-error-context-logging.md +34 -0
  19. package/skill-assets/sunlint-code-quality/rules/ruby/C041-no-hardcoded-secrets.md +29 -0
  20. package/skill-assets/sunlint-code-quality/rules/ruby/C042-boolean-naming.md +38 -0
  21. package/skill-assets/sunlint-code-quality/rules/ruby/C052-controller-parsing.md +37 -0
  22. package/skill-assets/sunlint-code-quality/rules/ruby/C060-superclass-logic.md +38 -0
  23. package/skill-assets/sunlint-code-quality/rules/ruby/C067-no-hardcoded-config.md +37 -0
  24. package/skill-assets/sunlint-code-quality/rules/ruby/S003-open-redirect.md +58 -0
  25. package/skill-assets/sunlint-code-quality/rules/ruby/S004-no-log-credentials.md +38 -0
  26. package/skill-assets/sunlint-code-quality/rules/ruby/S005-server-authorization.md +37 -0
  27. package/skill-assets/sunlint-code-quality/rules/ruby/S006-default-credentials.md +29 -0
  28. package/skill-assets/sunlint-code-quality/rules/ruby/S007-output-encoding.md +31 -0
  29. package/skill-assets/sunlint-code-quality/rules/ruby/S009-approved-crypto.md +31 -0
  30. package/skill-assets/sunlint-code-quality/rules/ruby/S010-csprng.md +30 -0
  31. package/skill-assets/sunlint-code-quality/rules/ruby/S011-encrypted-client-hello.md +27 -0
  32. package/skill-assets/sunlint-code-quality/rules/ruby/S012-secrets-management.md +28 -0
  33. package/skill-assets/sunlint-code-quality/rules/ruby/S013-tls-connections.md +30 -0
  34. package/skill-assets/sunlint-code-quality/rules/ruby/S016-no-sensitive-query-string.md +37 -0
  35. package/skill-assets/sunlint-code-quality/rules/ruby/S017-parameterized-queries.md +33 -0
  36. package/skill-assets/sunlint-code-quality/rules/ruby/S019-email-input-sanitization.md +31 -0
  37. package/skill-assets/sunlint-code-quality/rules/ruby/S020-eval-code-execution.md +36 -0
  38. package/skill-assets/sunlint-code-quality/rules/ruby/S022-context-escaping.md +36 -0
  39. package/skill-assets/sunlint-code-quality/rules/ruby/S023-dynamic-js-encoding.md +33 -0
  40. package/skill-assets/sunlint-code-quality/rules/ruby/S025-server-validation.md +30 -0
  41. package/skill-assets/sunlint-code-quality/rules/ruby/S026-tls-encryption.md +30 -0
  42. package/skill-assets/sunlint-code-quality/rules/ruby/S027-mtls-validation.md +26 -0
  43. package/skill-assets/sunlint-code-quality/rules/ruby/S028-upload-limits.md +33 -0
  44. package/skill-assets/sunlint-code-quality/rules/ruby/S029-csrf-protection.md +32 -0
  45. package/skill-assets/sunlint-code-quality/rules/ruby/S030-directory-browsing.md +30 -0
  46. package/skill-assets/sunlint-code-quality/rules/ruby/S031-secure-cookie-flag.md +27 -0
  47. package/skill-assets/sunlint-code-quality/rules/ruby/S032-httponly-cookie.md +26 -0
  48. package/skill-assets/sunlint-code-quality/rules/ruby/S033-samesite-cookie.md +29 -0
  49. package/skill-assets/sunlint-code-quality/rules/ruby/S034-host-prefix-cookie.md +30 -0
  50. package/skill-assets/sunlint-code-quality/rules/ruby/S035-app-hostnames.md +28 -0
  51. package/skill-assets/sunlint-code-quality/rules/ruby/S036-internal-file-paths.md +37 -0
  52. package/skill-assets/sunlint-code-quality/rules/ruby/S037-anti-cache-headers.md +31 -0
  53. package/skill-assets/sunlint-code-quality/rules/ruby/S039-tls-certificate-validation.md +29 -0
  54. package/skill-assets/sunlint-code-quality/rules/ruby/S041-logout-invalidation.md +31 -0
  55. package/skill-assets/sunlint-code-quality/rules/ruby/S042-long-lived-sessions.md +27 -0
  56. package/skill-assets/sunlint-code-quality/rules/ruby/S044-critical-changes-reauth.md +34 -0
  57. package/skill-assets/sunlint-code-quality/rules/ruby/S045-brute-force-protection.md +33 -0
  58. package/skill-assets/sunlint-code-quality/rules/ruby/S047-oauth-csrf-protection.md +33 -0
  59. package/skill-assets/sunlint-code-quality/rules/ruby/S048-oauth-redirect-validation.md +29 -0
  60. package/skill-assets/sunlint-code-quality/rules/ruby/S049-auth-code-expiry.md +31 -0
  61. package/skill-assets/sunlint-code-quality/rules/ruby/S050-token-entropy.md +26 -0
  62. package/skill-assets/sunlint-code-quality/rules/ruby/S051-password-length.md +38 -0
  63. package/skill-assets/sunlint-code-quality/rules/ruby/S052-otp-entropy.md +25 -0
  64. package/skill-assets/sunlint-code-quality/rules/ruby/S053-generic-error-messages.md +33 -0
  65. package/skill-assets/sunlint-code-quality/rules/ruby/S054-no-default-admin.md +29 -0
  66. package/skill-assets/sunlint-code-quality/rules/ruby/S055-content-type-validation.md +24 -0
  67. package/skill-assets/sunlint-code-quality/rules/ruby/S056-log-injection.md +28 -0
  68. package/skill-assets/sunlint-code-quality/rules/ruby/S057-synchronized-time.md +18 -0
  69. package/skill-assets/sunlint-code-quality/rules/ruby/S058-ssrf-protection.md +39 -0
@@ -0,0 +1,29 @@
1
+ ---
2
+ title: Validate OAuth Redirect URIs
3
+ impact: HIGH
4
+ impactDescription: prevents redirect hijacking and token leakage
5
+ tags: security, oauth, redirect, validation
6
+ ---
7
+
8
+ ## Validate OAuth Redirect URIs
9
+
10
+ Ensure that the redirect URI sent in the authorization request matches the values pre-registered for your application.
11
+
12
+ **Incorrect (dynamic/unvalidated redirect):**
13
+
14
+ ```ruby
15
+ # Allowing user-supplied redirect_uri
16
+ redirect_uri = params[:redirect_uri]
17
+ redirect_to "https://provider.com/auth?redirect_uri=#{redirect_uri}"
18
+ ```
19
+
20
+ **Correct (pre-registered URI):**
21
+
22
+ ```ruby
23
+ # Hardcode or use config
24
+ CALLBACK_URL = "https://app.com/auth/callback"
25
+ redirect_to "https://provider.com/auth?redirect_uri=#{CALLBACK_URL}"
26
+ ```
27
+
28
+ **Tools:** Manual Review
29
+ ---
@@ -0,0 +1,31 @@
1
+ ---
2
+ title: Enforce Token Expiration
3
+ impact: MEDIUM
4
+ impactDescription: limits the lifespan of stolen tokens or temporary credentials
5
+ tags: security, session, token, timeout
6
+ ---
7
+
8
+ ## Enforce Token Expiration
9
+
10
+ All authorization codes, access tokens, and temporary files should have a strict, short expiration time.
11
+
12
+ **Incorrect (no expiry):**
13
+
14
+ ```ruby
15
+ class ResetToken < ApplicationRecord
16
+ # Token never expires
17
+ end
18
+ ```
19
+
20
+ **Correct (expiration check):**
21
+
22
+ ```ruby
23
+ class ResetToken < ApplicationRecord
24
+ def valid?
25
+ created_at > 2.hours.ago
26
+ end
27
+ end
28
+ ```
29
+
30
+ **Tools:** Manual Review
31
+ ---
@@ -0,0 +1,26 @@
1
+ ---
2
+ title: Use High Entropy for Tokens
3
+ impact: HIGH
4
+ impactDescription: ensures tokens are unpredictable and cannot be guessed
5
+ tags: security, tokens, entropy
6
+ ---
7
+
8
+ ## Use High Entropy for Tokens
9
+
10
+ Always use cryptographically secure random values (CSPRNG) with sufficient entropy (at least 128 bits) for all security tokens.
11
+
12
+ **Incorrect (low entropy):**
13
+
14
+ ```ruby
15
+ token = rand(10**10).to_s # Not long enough and not secure
16
+ ```
17
+
18
+ **Correct (High entropy):**
19
+
20
+ ```ruby
21
+ require 'securerandom'
22
+ token = SecureRandom.hex(32) # 256 bits of entropy
23
+ ```
24
+
25
+ **Tools:** Brakeman, SecureRandom
26
+ ---
@@ -0,0 +1,38 @@
1
+ ---
2
+ title: Enforce Stricter Password Policies
3
+ impact: HIGH
4
+ impactDescription: ensures users use strong, difficult-to-crack passwords
5
+ tags: security, password, authentication
6
+ ---
7
+
8
+ ## Enforce Stricter Password Policies
9
+
10
+ Require a minimum password length and complexity (uppercase, lowercase, numbers, symbols) to protect against credential guessing.
11
+
12
+ **Incorrect (weak password requirements):**
13
+
14
+ ```ruby
15
+ class User < ApplicationRecord
16
+ has_secure_password
17
+ validates :password, length: { minimum: 4 } # Too short
18
+ end
19
+ ```
20
+
21
+ **Correct (strong policy):**
22
+
23
+ ```ruby
24
+ class User < ApplicationRecord
25
+ has_secure_password
26
+ validates :password, length: { minimum: 12 }
27
+ # Complexity check
28
+ validate :password_complexity
29
+
30
+ def password_complexity
31
+ return if password.blank? || password =~ /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{12,}$/
32
+ errors.add :password, 'Complexity requirement not met'
33
+ end
34
+ end
35
+ ```
36
+
37
+ **Tools:** Devise-security, Manual Review
38
+ ---
@@ -0,0 +1,25 @@
1
+ ---
2
+ title: Ensure Strong OTP Entropy
3
+ impact: HIGH
4
+ impactDescription: prevents OTP guessing attacks
5
+ tags: security, mfa, otp, entropy
6
+ ---
7
+
8
+ ## Ensure Strong OTP Entropy
9
+
10
+ When using One-Time Passwords (OTP), ensure they are generated using a secure random source and have sufficient length (at least 6 digits).
11
+
12
+ **Incorrect (not secure):**
13
+
14
+ ```ruby
15
+ otp = rand(9999) # Only 4 digits, predictable rand
16
+ ```
17
+
18
+ **Correct (SecureRandom + 6 digits):**
19
+
20
+ ```ruby
21
+ otp = SecureRandom.random_number(1_000_000).to_s.rjust(6, '0')
22
+ ```
23
+
24
+ **Tools:** ROTP gem, Brakeman
25
+ ---
@@ -0,0 +1,33 @@
1
+ ---
2
+ title: Use Generic Error Messages in Auth
3
+ impact: MEDIUM
4
+ impactDescription: prevents account enumeration by hiding which part of the authentication failed
5
+ tags: security, authentication, privacy
6
+ ---
7
+
8
+ ## Use Generic Error Messages in Auth
9
+
10
+ Avoid indicating whether the email or the password was incorrect. Use generic messages like "Invalid email or password".
11
+
12
+ **Incorrect (reveals existence):**
13
+
14
+ ```ruby
15
+ if @user.nil?
16
+ render json: { error: "User not found" } # Enumeration possible
17
+ elsif !@user.authenticate(params[:password])
18
+ render json: { error: "Incorrect password" }
19
+ end
20
+ ```
21
+
22
+ **Correct (generic message):**
23
+
24
+ ```ruby
25
+ if @user&.authenticate(params[:password])
26
+ login(@user)
27
+ else
28
+ render json: { error: "Invalid email or password" }, status: :unauthorized
29
+ end
30
+ ```
31
+
32
+ **Tools:** Manual Review
33
+ ---
@@ -0,0 +1,29 @@
1
+ ---
2
+ title: No Default or Static Admin Accounts
3
+ impact: CRITICAL
4
+ impactDescription: prevents easy administrative access through well-known or static credentials
5
+ tags: security, authorization, credentials, admin
6
+ ---
7
+
8
+ ## No Default or Static Admin Accounts
9
+
10
+ Avoid creating default users or admin accounts with hardcoded passwords in seeds or initial configuration.
11
+
12
+ **Incorrect (default seed):**
13
+
14
+ ```ruby
15
+ # db/seeds.rb
16
+ User.create!(email: "admin@example.com", password: "password", admin: true)
17
+ ```
18
+
19
+ **Correct (env-driven seed):**
20
+
21
+ ```ruby
22
+ User.find_or_create_by!(email: ENV['INITIAL_ADMIN_EMAIL']) do |u|
23
+ u.password = ENV['INITIAL_ADMIN_PASSWORD']
24
+ u.admin = true
25
+ end
26
+ ```
27
+
28
+ **Tools:** Manual Review
29
+ ---
@@ -0,0 +1,24 @@
1
+ ---
2
+ title: Validate Content-Type for Uploads
3
+ impact: MEDIUM
4
+ impactDescription: prevents uploading of malicious executable files disguised as data
5
+ tags: security, uploads, validation, mimetypes
6
+ ---
7
+
8
+ ## Validate Content-Type for Uploads
9
+
10
+ Always validate the `Content-Type` and file extension of uploaded files. Check the magic bytes/file header rather than just the extension.
11
+
12
+ **Correct (ActiveStorage + Marcel):**
13
+
14
+ ```ruby
15
+ # Rails ActiveStorage uses Marcel gem to check magic bytes
16
+ class User < ApplicationRecord
17
+ has_one_attached :avatar
18
+
19
+ validates :avatar, content_type: ['image/png', 'image/jpeg']
20
+ end
21
+ ```
22
+
23
+ **Tools:** ActiveStorage Validations gem
24
+ ---
@@ -0,0 +1,28 @@
1
+ ---
2
+ title: Prevent Log Injection
3
+ impact: MEDIUM
4
+ impactDescription: prevents attackers from corrupting logs or misleading auditors
5
+ tags: security, logging, sanitization
6
+ ---
7
+
8
+ ## Prevent Log Injection
9
+
10
+ Sanitize all user-input data before including it in log files to prevent attackers from injecting newlines or carriage returns.
11
+
12
+ **Incorrect (unsafe logging):**
13
+
14
+ ```ruby
15
+ # Attacker name: "admin\n[INFO] Login successful for admin"
16
+ logger.info "User update attempted by #{params[:user_name]}"
17
+ ```
18
+
19
+ **Correct (sanitized logging):**
20
+
21
+ ```ruby
22
+ # Replace newlines with spaces or use json logger
23
+ sanitized_name = params[:user_name].gsub(/[\n\r]/, " ")
24
+ logger.info "User update attempted by #{sanitized_name}"
25
+ ```
26
+
27
+ **Tools:** Lograge (default Rails JSON logging avoids this)
28
+ ---
@@ -0,0 +1,18 @@
1
+ ---
2
+ title: Ensure Synchronized System Time
3
+ impact: LOW
4
+ impactDescription: crucial for log correlation, audit trails, and time-based security tokens
5
+ tags: security, infrastructure, timing
6
+ ---
7
+
8
+ ## Ensure Synchronized System Time
9
+
10
+ Ensure all servers in your environment are synchronized using a network time protocol (NTP). This is critical for authentication tokens (OTP, JWT) and log correlation.
11
+
12
+ **Details:**
13
+ - Configure NTP/Chrony on all production servers.
14
+ - Monitor time synchronization offset.
15
+ - Important for TOTP (MFA) and token expiry checks.
16
+
17
+ **Tools:** NTP, Chrony, CloudWatch Time Sync
18
+ ---
@@ -0,0 +1,39 @@
1
+ ---
2
+ title: Prevent Server-Side Request Forgery (SSRF)
3
+ impact: HIGH
4
+ impactDescription: prevents attackers from accessing internal resources or services
5
+ tags: security, ssrf, vulnerability, net-http
6
+ ---
7
+
8
+ ## Prevent Server-Side Request Forgery (SSRF)
9
+
10
+ Never allow users to provide the full URL or IP address for your server to fetch. Use an allow-list of domains or a secure proxy.
11
+
12
+ **Incorrect (unvalidated SSRF):**
13
+
14
+ ```ruby
15
+ def fetch_external_report
16
+ # Attacker url: http://localhost:5432 or http://169.254.169.254/metadata
17
+ response = Net::HTTP.get(URI(params[:url]))
18
+ render body: response
19
+ end
20
+ ```
21
+
22
+ **Correct (validated domain):**
23
+
24
+ ```ruby
25
+ ALLOWED_DOMAINS = ['trusted-report-source.com']
26
+
27
+ def fetch_external_report
28
+ uri = URI(params[:url])
29
+ if ALLOWED_DOMAINS.include?(uri.host)
30
+ response = Net::HTTP.get(uri)
31
+ render body: response
32
+ else
33
+ render_403
34
+ end
35
+ end
36
+ ```
37
+
38
+ **Tools:** Brakeman, ssrf_filter gem
39
+ ---