Critical CSRF Weakness Discovered in Ruby on Rails Framework
A newly uncovered vulnerability in Ruby on Rails has shaken the web development community, allowing threat actors to bypass a core security safeguard: Cross-Site Request Forgery (CSRF) protection.
Disclosed on April 26, 2025, the issue impacts every maintained version of Rails, including those updated after the 2022/2023 patches that were believed to resolve a similar flaw.
At the heart of this vulnerability lies a flawed approach to token obfuscation. Rails employs a process where an “authenticity token” is obscured using a randomly generated one-time pad (OTP). This OTP is XORed with the original token, and both pieces—the OTP and the XOR result—are simply concatenated into what Rails calls a “masked token.”
This shortcut introduces a fatal flaw: by transmitting both the encryption key and the encrypted data together, the framework makes it trivial for an attacker to reverse the process. As a result, malicious actors can reconstruct valid CSRF tokens on the fly, rendering the defense ineffective.
Cybersecurity researchers from Seclists warn that this architectural weakness poses a widespread threat, especially for applications that depend on Rails’ built-in CSRF protections for user action validation.
“This isn’t just a small hole—it’s a total bypass,” said Daniel Owens, the independent security researcher who brought the issue to light. His analysis suggests the vulnerability is effectively the same one Rails attempted to patch years ago, now resurfacing with deeper implications.
Under the Hood: What Went Wrong
The flaw stems from the mask_token method within the Rails core:
ruby
def mask_token(raw_token)
one_time_pad = SecureRandom.random_bytes(AUTHENTICITY_TOKEN_LENGTH)
encrypted_csrf_token = xor_byte_strings(one_time_pad, raw_token)
masked_token = one_time_pad + encrypted_csrf_token
encode_csrf_token(masked_token)
end
While intended to thwart attacks like BREACH by making CSRF tokens dynamic per request, the method undermines its own purpose. It sends both the encryption mechanism and the encrypted payload in the same package—an elementary cryptographic mistake.
Owens illustrated the exploit using JavaScript that regenerates valid CSRF tokens by simply reversing the masking process. Here’s a portion of the proof-of-concept:
javascript
function getCsrfToken(otp, raw_token) {
var masked_token = new Uint8Array(raw_token.length);
for (var i = 0; i < raw_token.length; i++) {
masked_token[i] = otp[i] ^ raw_token[i];
}
return btoa(String.fromCharCode(…masked_token)).replace(/=+$/, ”);
}
By forging these tokens, attackers can impersonate users and execute unauthorized commands on vulnerable applications—an especially dangerous scenario for platforms with high levels of user trust or financial transactions.
This incident serves as a stark reminder: security mechanisms must be built on strong cryptographic foundations—not convenience.




