Active Support
-
ActiveSupport::MessagePackno longer deserializes an unsafe
ActiveSupport::SafeBufferashtml_safe.A
SafeBufferthat was no longerhtml_safe?, for example after an
in-placegsub!, was deserialized as anhtml_safeSafeBuffer. It is now
serialized with an unsafe marker and deserialized as aString. Earlier
versions of Rails cannot read an unsafe buffer serialized this way.Jean Boussier
-
ActiveSupport::Inflector#safe_constantizematches the constant name in a
LoadErrormessage as a literal string instead of building aRegexp
from it.The name's segments were interpolated unescaped into the pattern, so input
that reachessafe_constantize, such as the channel identifier in an Action
Cable subscribe command, chose the source passed to the regexp compiler.Jeremy Daer
Active Model
- No changes.
Active Record
- No changes.
Action View
-
Skip attribute names in tag helpers that are blank once converted to a
string.A Symbol such as
:" "is not blank, becauseSymbol#blank?is
Symbol#empty?, so it reached the escaping step and produced an attribute
with no name. The asset helpers symbolize their keys, so an ordinary String
key reached the same place.Mike Dalessio
-
Fix
strip_tagsto encode"and'in its output.strip_tagsreturns anhtml_safestring, but was not encoding quotation
marks. The method now encodes all five HTML-significant characters (&,
<,>,",'), consistent with the existinghtml_safeconvention.Output used outside HTML, such as in a text template or JSON, now contains
"and'where it contained"and'.CGI.unescapeHTML
decodes them.Mike Dalessio
-
Escape the matched phrase before substituting it into
highlight's
:highlighter.A match was copied into each
\1of the highlighter as it appeared in
the sanitized text, which keeps"and'as they are, so a match
containing a quote ended a quoted attribute value such as the
documented'<a href="search?q=\1">\1</a>'and added attributes of
its own. Each substituted group now goes through
ERB::Util.html_escape_once, so quotes in a match render as"
and'. Only the numbered placeholders\0to\9are expanded,
and a match never replaces the>that closes a tag.Jeremy Daer
-
Require rails-html-sanitizer 1.7.2 or later.
With the HTML5 sanitizer, Nokogiri before 1.19.5 left
<and>
unescaped in attribute values.highlightandsimple_format, which
edit the sanitized HTML as a string, could then turn markup inside an
attribute value into live elements. rails-html-sanitizer 1.7.2 requires
Loofah 2.25.3, which requires Nokogiri 1.19.5.Mike Dalessio
Action Pack
-
Apply
config.action_dispatch.cookies_same_site_protectionto every session
store.ActionDispatch::Session::CacheStore,MemCacheStoreand third-party
stores built onAbstractStoreor the session mixins sent session cookies
with noSameSiteattribute. OnlyCookieStoreapplied the configured
default.Jean Boussier
-
Prevent
ActionController::Livestreams from blocking when a full buffer is
closed or aborted.Jeremy Daer
-
Set and extend the
Varyheader for rendered responses according to the
request headers used in format negotiation.Vary: Acceptwas only added when the request carried a usableAccept
header. A response to a request without one, negotiated to HTML or
JavaScript, could be stored by a shared cache and served to later clients
that requested a different representation.Responses now vary on
AcceptandX-Requested-Withwhenever the format is
not given by the URL. XHR requests withoutAcceptalso vary on
Content-Type, which Rails uses as a legacy format fallback. When
config.action_dispatch.ignore_accept_headeris enabled, responses vary
only onX-Requested-With.These fields are appended to an existing
Varyvalue without duplicating
fields case-insensitively.Vary: *remains unchanged.Jeremy Daer
-
Skip writing a
CacheStoresession that another request deleted while this
one ran.A request that loaded a session from
ActionDispatch::Session::CacheStore
wrote it back when it finished, even after a concurrentreset_sessionor a
server-side delete had removed it, so the old session ID worked again.Mike Dalessio
-
Don't write upgraded cookies to a response that skips the session.
Reading a signed or encrypted cookie written under a rotated secret, or in
the format a:hybridserializer migrates from, writes it back in the
current format. That write ignoredrequest.session_options[:skip], so a
response that skips the session, such as the Active Storage proxy's
public, cacheable response, could still carry the session cookie in
Set-Cookie. Such a response now leaves the cookie unchanged, and a later
request that does not skip the session upgrades it. An application that
skips the session on every request no longer upgrades its signed or
encrypted cookies. Cookies the application sets are still written.Mike Dalessio
-
Detect conflicts between the
ForwardedandX-Forwarded-Forheaders in
ActionDispatch::RemoteIp.When
ip_spoofing_checkis enabled (the default), requests carrying both
headers with conflicting client addresses now raise
ActionDispatch::RemoteIp::IpSpoofAttackError.Gannon McGibbon, Mike Dalessio
-
ActionController::Parameters#each_keyreturnsselfwhen given a block.It returned the internal
ActiveSupport::HashWithIndifferentAccess, which
does not respond topermitted?, so passing that return value to mass
assignment skipped the Strong Parameters check.each,each_pairand
each_valuealready returnself.Document that
ActionController::Parameters#as_jsonreturns every
parameter, permitted or not, in a hash that mass assignment does not check.Mike Dalessio
Active Job
- No changes.
Action Mailer
- No changes.
Action Cable
- No changes.
Active Storage
-
Preserve committed proxy responses when a storage error interrupts a
streamed download.Jeremy Daer
-
Derive
ActiveStorage::Filename#baseand#extensionfrom the sanitized
filename.This prevents null bytes and invalid byte sequences in stored filename
metadata from raising when a blob is opened or represented. Existing blob
records are handled without a data migration.Jeremy Daer
-
Ship an ImageMagick security policy and apply it to every ImageMagick
process MiniMagick spawns.ImageMagick chooses a coder from the content of the file it is given, and
some coders act on files named inside the image rather than on the image
itself. Active Storage constrained none of them, so an uploaded file could
reach any coder the host's policy allowed, through the ImageMagick analyzer
at attach time, with no variant oranalyzecall in the application.Active Storage now ships a
policy.xmlin
ActiveStorage::ImageMagick::POLICY_DIRECTORYand prepends that directory
toMAGICK_CONFIGURE_PATHthroughMiniMagick.cli_env. ImageMagick applies
every policy file on its search path, so the shipped policy adds to the
host's policy rather than replacing it. AMAGICK_CONFIGURE_PATHset in the
environment or inMiniMagick.cli_env, including by an initializer or
dotenv, is kept after the shipped directory.The shipped policy denies the coders that script ImageMagick (
MSL), read
or delete files other than the image (TEXT,EPHEMERAL), fetch remote
references (URL,HTTP,HTTPS,FTP), display to a screen (SHOW,
WIN,PLT), or hand the file to Ghostscript (thePS,EPS,EPTand
PDFcoders, every alias of them, and thegsdelegate), or reach a file
directly (FILE,MPC,XPS,PCL), and it refuses@filename
indirection. The policy applies to every ImageMagick command MiniMagick
runs, not only Active Storage's.These applications must act:
- One whose variant processor is
:mini_magickhas to use mini_magick 5.1
or later, which applying the policy requires. With an older mini_magick,
it raises at boot. - One that renders PostScript or PDF through ImageMagick has to re-allow
thegsdelegate and the coders it uses in the host'spolicy.xml. A
host policy that allows a coder overrides the shipped deny. - One that replaces
MiniMagick.cli_envafter it boots, clears the
environment withMiniMagick.cli_prefix, or installs its own
MiniMagick::Shellnever receives the shipped policy and has to carry
its rules in ImageMagick's system policy. So does one that uses
GraphicsMagick, which does not read ImageMagick policies.
Every other application needs no change. See "ImageMagick Security Policy"
in the Active Storage guide.Mike Dalessio
- One whose variant processor is
-
Enforce the declared content length on Google Cloud Storage direct uploads.
The signed URL now requires an
x-goog-content-length-rangeheader matching the blob's
byte_size, so Cloud Storage rejects a body of any other size.Browsers send the new header, so a bucket's CORS configuration must list
x-goog-content-length-rangeinresponseHeader, or direct uploads from the browser fail.Mike Dalessio
-
Sign GCS direct uploads with V2 when
cache_controlis set.V4 signatures did not bind the Content-Type or Content-MD5 headers, so the uploader could
choose the stored Content-Type. Direct-upload URLs withcache_controlare no longer limited
to 7 days, and the client sendsCache-Controlunsigned.Mike Dalessio
-
Stop an uploaded filename choosing the extension of the tempfile Active
Storage hands to an external tool.ActiveStorage::Blob#opennamed its tempfile after the uploaded filename,
extension and all. Tools that select a decoder from the extension alone,
such as FFmpeg's AviSynth demuxer on.avs, therefore took their
instructions from the uploader. The extension is now kept only when it
denotes the blob's recorded media type, and dropped otherwise.Mike Dalessio
-
Restrict the formats ffmpeg and ffprobe will open when previewing and
analyzing video and audio.Active Storage now passes
-format_whitelistbefore the input at every
ffmpeg and ffprobe call site, limiting demuxer selection to common audio and
video container formats. Configure the list with
config.active_storage.ffmpeg_allowed_formats, or set it tonilto let
ffmpeg choose any demuxer it was built with.Files in other formats, such as MXF, DV, AC3, WavPack, AU, W64, and raw
H.264 or MPEG-1/2 video streams, now fail to preview with
ActiveStorage::PreviewError, and their analysis stores no media metadata
and logs a warning. Add their demuxers to the list to keep them.config.active_storage.ffmpeg_allowed_formats += %w[ mxf ]
Mike Dalessio
Action Mailbox
-
Reject Mailgun inbound emails whose timestamp is more than 2 minutes ahead
of local time.Mike Dalessio
Action Text
- No changes.
Railties
- No changes.
Guides
- No changes.