<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>The Crystal Programming Language</title>
  <subtitle>A language for humans and computers</subtitle>
  <link href="https://deploy-preview-1093--crystal-website.netlify.app/" rel="alternate" type="text/html" />
  <link href="https://deploy-preview-1093--crystal-website.netlify.app/feed.xml" rel="self" type="application/atom+xml" />
  <link href="https://deploy-preview-1093--crystal-website.netlify.app/releases/feed.xml" rel="related" type="application/atom+xml" />
  <updated>2026-07-13T09:17:05+00:00</updated>
  <id>https://deploy-preview-1093--crystal-website.netlify.app/feed.xml</id>
    <entry>
      <title>Releasing Execution Contexts</title>
      <author>
        <name>Julien Portalier</name>
        <uri>https://github.com/ysbaddaden/</uri>
      </author>
      <link href="https://deploy-preview-1093--crystal-website.netlify.app/2026/07/12/releasing-execution-contexts/" rel="alternate" type="text/html" title="Releasing Execution Contexts" />
      <published>2026-07-12T00:00:00+00:00</published>
      <updated>2026-07-12T00:00:00+00:00</updated>
      <id>https://deploy-preview-1093--crystal-website.netlify.app/2026/07/12/releasing-execution-contexts</id>
      <summary type="html">Two and a half years ago, with the invaluable support from 84codes, we re-examined the multithreading model inherited from Crystal 0.28 (preview MT).</summary>
      <content type="html" xml:base="https://deploy-preview-1093--crystal-website.netlify.app/2026/07/12/releasing-execution-contexts/">&lt;p&gt;&lt;a href=&quot;/2024/02/09/84codes-manas-mt/&quot;&gt;Two and a half years ago&lt;/a&gt;, with the
invaluable support from 84codes, we re-examined the multithreading model
inherited from Crystal 0.28 (preview MT).&lt;/p&gt;

&lt;p&gt;There are different ways to spread an application to multiple CPU cores. So far,
preview MT proposed a simple solution, and it worked great for many cases, yet
sometimes we need more control over where and how a specific piece of code must
run.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Sometimes we need a fiber to own a thread, notably GUI and game loops.&lt;/li&gt;
  &lt;li&gt;Sometimes we need a set of fibers to run concurrently.&lt;/li&gt;
  &lt;li&gt;Sometimes we need fibers to scale to as many CPU cores as needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inspired by Kotlin contexts, we realized that we didn’t have to pick just
one model. What if we designed an &lt;em&gt;interface&lt;/em&gt; instead?&lt;/p&gt;

&lt;p&gt;Hence came &lt;strong&gt;Execution Contexts&lt;/strong&gt;. Plural, because there are multiple ways to
orchestrate fibers across one to many threads. Ultimately we plan to make the
interface public, so you may write your own models.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;the-default-execution-context&quot;&gt;The default execution context&lt;/h2&gt;
  &lt;a href=&quot;#the-default-execution-context&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled The default execution context&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Applications run in a default context that is automatically created on the main
thread. It’s a parallel context that defaults to a parallelism of 1, so fibers
run concurrently on just one thread. This avoids a breaking change to existing
applications that may not be ready for MT.&lt;/p&gt;

&lt;p&gt;You can resize the default context to increase parallelism, making it truly
parallel, and letting it automatically scale fibers across CPU cores as needed
at runtime:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;code_section&quot;&gt;&lt;code&gt;Fiber::ExecutionContext.default.resize(maximum: System.cpu_count)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can keep it concurrent and start additional contexts to control the
execution and let the OS preempt the threads:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;code_section&quot;&gt;&lt;code&gt;parallel = Fiber::ExecutionContext::Parallel.new(&quot;MT&quot;, maximum: 4)
parallel.spawn { }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can keep it single-threaded if you don’t need parallelism, or let users
determine the parallelism through a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--threads N&lt;/code&gt; argument.&lt;/p&gt;

&lt;p&gt;Your application, your choice.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;what-do-execution-contexts-provide&quot;&gt;What do execution contexts provide?&lt;/h2&gt;
  &lt;a href=&quot;#what-do-execution-contexts-provide&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled What do execution contexts provide?&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Execution contexts allow you to start one or many fiber orchestrators to run
fibers in different manners. Fibers are tied to their execution context, and the
execution of fibers depends on the context they belong to.&lt;/p&gt;

&lt;p&gt;We currently provide three different context types:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Concurrent&lt;/strong&gt;: Fibers spawned into the context run concurrently to each
other, and will never run in parallel; they only run in parallel to fibers
running in other contexts.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Parallel&lt;/strong&gt;: Fibers spawned in a parallel context run concurrently and in
parallel to each other, in addition to fibers running in other contexts. The
context automatically scales to multiple CPU cores, up to the configured
maximum.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Isolated&lt;/strong&gt;: Spawn a single fiber to a system thread. The fiber owns the
thread for its whole lifetime. The fiber can block the thread however it wants
(it owns it) with no impact on the rest of the application.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;can-execution-contexts-communicate&quot;&gt;Can execution contexts communicate?&lt;/h2&gt;
  &lt;a href=&quot;#can-execution-contexts-communicate&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Can execution contexts communicate?&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Fibers can always communicate and synchronize with any other fibers, regardless
of the execution context in which they run. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Channel&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sync&lt;/code&gt; types
normally.&lt;/p&gt;

&lt;p&gt;Note that cross context communication requires more synchronization than
internal communication, and can thus be slower. This is mostly noticeable in
extreme situations, notably benchmarks.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;how-are-execution-contexts-different-from-the-preview-mt-model&quot;&gt;How are execution contexts different from the ‘preview MT’ model?&lt;/h2&gt;
  &lt;a href=&quot;#how-are-execution-contexts-different-from-the-preview-mt-model&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled How are execution contexts different from the ‘preview MT’ model?&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Preview MT starts a fixed number of threads and ties each fiber to a single
thread on which it is always resumed. You have no control over where a fiber
would start aside from “spawn on the current thread of the current fiber”; you
can’t isolate a fiber to a thread, plus other limitations.&lt;/p&gt;

&lt;p&gt;Fibers can get stuck on one thread busy running a CPU-intensive work, while
other threads are idle. A slow &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getaddrinfo&lt;/code&gt; DNS request, for example, might
block your whole application from making any progress, or event fail to respond
to Ctrl+C or SIGINT to terminate the process.&lt;/p&gt;

&lt;p&gt;Execution contexts solve all these issues.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;what-changes&quot;&gt;What changes?&lt;/h2&gt;
  &lt;a href=&quot;#what-changes&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled What changes?&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;The fiber scheduler has seen a complete overhaul. It is nothing like before. Not
only is it faster than the legacy schedulers, including both single thread and
preview MT, fibers will now automatically scale to as many CPU cores as needed
at runtime.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;the-crystal_workers-environment-variable&quot;&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CRYSTAL_WORKERS&lt;/code&gt; environment variable&lt;/h3&gt;
  &lt;a href=&quot;#the-crystal_workers-environment-variable&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CRYSTAL_WORKERS&lt;/code&gt; environment variable&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CRYSTAL_WORKERS&lt;/code&gt; environment variable is no longer used by default. You can
use it manually to resize the default context, or start a parallel context. For
example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;code_section&quot;&gt;&lt;code&gt;maximum = ENV[&quot;CRYSTAL_WORKERS&quot;]?.try(&amp;amp;.to_i?) || 4
Fiber::ExecutionContext.default.resize(maximum)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking changes&lt;/h2&gt;
  &lt;a href=&quot;#breaking-changes&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Breaking changes&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;We have kept the breaking changes to a minimum and expect most applications to
continue running normally by keeping their default context concurrent.&lt;/p&gt;

&lt;p&gt;If you experience issues, you may revert to the legacy, single-threaded,
scheduler using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;without_mt&lt;/code&gt; compilation flag.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;preview_mt&lt;/code&gt; compilation flag is still supported; using it reverts to the
legacy, multi-threaded, preview scheduler.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Dpreview_mt -Dexecution_context&lt;/code&gt; combinaition of flags is still supported,
and won’t revert to the legacy preview MT scheduler.&lt;/p&gt;

&lt;div class=&quot;callout callout--warning&quot;&gt;
  &lt;div class=&quot;callout-title&quot;&gt;Warning
&lt;/div&gt;
&lt;p&gt;You are heavily encouraged to upgrade to execution contexts because we can’t
 guarantee legacy support will continue in upcoming releases.&lt;/p&gt;

&lt;p&gt;If you need the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;without_mt&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;preview_mt&lt;/code&gt; flag, and it’s unrelated to the
 below breaking changes, then we consider this to be a bug in the Crystal
 runtime.&lt;/p&gt;

&lt;p&gt;Please report any issues!&lt;/p&gt;

&lt;/div&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;1-fibers-can-switch-threads-parallel-contexts&quot;&gt;1. Fibers can switch threads (parallel contexts)&lt;/h3&gt;
  &lt;a href=&quot;#1-fibers-can-switch-threads-parallel-contexts&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled 1. Fibers can switch threads (parallel contexts)&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Unlike the previous models (single-threaded and preview MT), the execution of
Fibers can move to another thread at runtime.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Fibers spawned in a parallel context can be resumed by any thread in the
context. Fibers can start on one system thread, wait on I/O or a channel, then
be resumed by another thread in the context. This feature is known as work
stealing, and allows to scale fibers across CPU cores.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;2-schedulers-can-switch-threads-on-blocking-syscalls&quot;&gt;2. Schedulers can switch threads on blocking syscalls&lt;/h3&gt;
  &lt;a href=&quot;#2-schedulers-can-switch-threads-on-blocking-syscalls&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled 2. Schedulers can switch threads on blocking syscalls&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Unlike the previous schedulers (single-threaded and preview MT), the new
schedulers can move to another thread at runtime.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A scheduler runs fibers sequentially on a single thread. The previous models
kept schedulers tied to their thread, but with execution contexts schedulers can
jump to another thread.&lt;/p&gt;

&lt;p&gt;This can happen for some specific syscalls, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getaddrinfo(3)&lt;/code&gt; that can
block the current thread and thus block the other fibers from progressing. When
that happens the scheduler can move to another thread to continue executing
runnable fibers while the current thread is blocked on the syscall. When the
syscall returns, the fiber is stopped and will eventually be resumed on the new
thread.&lt;/p&gt;

&lt;p&gt;This applies to both concurrent and parallel contexts, including the default
context. It doesn’t apply to the isolated context where blocking the thread is
the expected behavior.&lt;/p&gt;

&lt;p&gt;We don’t expect many applications to break, unless you rely on external C
libraries that expect to keep running on the main thread, or heavily rely on
thread locals. In that case, you may backup and restore thread-local state, or
consider isolated contexts.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;3-execution-contexts-dont-support-the-spawnsame_thread-true-argument&quot;&gt;3. Execution contexts don’t support the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spawn(same_thread: true)&lt;/code&gt; argument&lt;/h3&gt;
  &lt;a href=&quot;#3-execution-contexts-dont-support-the-spawnsame_thread-true-argument&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled 3. Execution contexts don’t support the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spawn(same_thread: true)&lt;/code&gt; argument&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;This impacts the preview MT model. The argument is deprecated and the behavior
depends on the execution context:&lt;/p&gt;

&lt;p&gt;The concurrent execution context simply ignores the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;same_thread&lt;/code&gt; argument
(noop).&lt;/p&gt;

&lt;p&gt;The parallel execution context ignores &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;same_thread: false&lt;/code&gt; (noop), but doesn’t
support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;same_thread: true&lt;/code&gt; argument and will raise an exception at runtime
because that feature can’t be guaranteed.&lt;/p&gt;

&lt;p&gt;The default execution context is parallel, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;same_thread: true&lt;/code&gt; will raise an
exception at runtime, even if you never resize the context to opt in to MT;
because the context might be resized in the future.&lt;/p&gt;

&lt;p&gt;The isolated context can’t directly spawn fibers, but instead spawns into the
default context or another specified context, so the behavior depends on the
target context.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h4 id=&quot;how-to-fix-the-same_thread-breaking-change&quot;&gt;How to fix the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;same_thread&lt;/code&gt; breaking change?&lt;/h4&gt;
  &lt;a href=&quot;#how-to-fix-the-same_thread-breaking-change&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled How to fix the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;same_thread&lt;/code&gt; breaking change?&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;If the value for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;same_thread&lt;/code&gt; is set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; you can safely drop the
argument.&lt;/p&gt;

&lt;p&gt;If set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;, you will have to investigate if there is an actual issue
regarding parallelism.&lt;/p&gt;

&lt;p&gt;If there is an issue, you can either fix the issue (for example by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sync&lt;/code&gt;
primitives), or start a concurrent execution context and spawn the fibers that
can’t run in parallel there, or choose to not resize the default context (no
parallelism until you opt-in).&lt;/p&gt;

&lt;p&gt;In any case, drop the argument.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
  &lt;a href=&quot;#notes&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Notes&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Auto-scaling roughly occurs every 100 ms, and stems from the idea that there’s
no need to spread work until it’s required. Another name for the feature is
“slow-parallelism”. While it improves efficiency, it can alter parallelism
expectations, especially in benchmarks that may finish before the executable
needs to scale to multiple threads. That’s the point of the feature, yet it
defeats the point of a benchmark.&lt;/p&gt;</content>
    </entry>
    <entry>
      <title>Crystal 1.20.3 is released!</title>
      <author>
        <name>Julien Portalier</name>
        <uri>https://github.com/ysbaddaden/</uri>
      </author>
      <link href="https://deploy-preview-1093--crystal-website.netlify.app/2026/07/02/1.20.3-released/" rel="alternate" type="text/html" title="Crystal 1.20.3 is released!" />
      <published>2026-07-02T00:00:00+00:00</published>
      <updated>2026-07-02T00:00:00+00:00</updated>
      <id>https://deploy-preview-1093--crystal-website.netlify.app/2026/07/02/1.20.3-released</id>
      <summary type="html">We are announcing a new Crystal release 1.20.3 with fixes for two security vulnerabilities in the YAML parsers. We recommend upgrading as soon as possible if your application processes YAML files from unknown origins.</summary>
      <content type="html" xml:base="https://deploy-preview-1093--crystal-website.netlify.app/2026/07/02/1.20.3-released/">&lt;p&gt;We are announcing a new Crystal release 1.20.3 with fixes for two security
vulnerabilities in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;YAML&lt;/code&gt; parsers. We recommend upgrading as soon as
possible if your application processes YAML files from unknown origins.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;/2026/04/16/1.20.0-released/&quot;&gt;the release notes of 1.20.0&lt;/a&gt; for all the
changes introduced in Crystal 1.20.&lt;/p&gt;

&lt;p&gt;Pre-built packages are available on &lt;a href=&quot;https://github.com/crystal-lang/crystal/releases/tag/1.20.3&quot;&gt;GitHub
Releases&lt;/a&gt; and our
official distribution channels. See
&lt;a href=&quot;https://crystal-lang.org/install/&quot;&gt;crystal-lang.org/install&lt;/a&gt; for installation
instructions.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;stats&quot;&gt;Stats&lt;/h2&gt;
  &lt;a href=&quot;#stats&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Stats&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;This release includes &lt;a href=&quot;https://github.com/crystal-lang/crystal/pulls?q=is%3Apr+milestone%3A1.20.3&quot;&gt;2 security fixes and 1 refactor since
1.20.2&lt;/a&gt;
by 1 contributor. We thank all the contributors for all the effort put into
improving the language! ❤️&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;changes&quot;&gt;Changes&lt;/h2&gt;
  &lt;a href=&quot;#changes&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Changes&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;limit-max-nesting-of-sequences-of-mappings-in-yaml-parsers&quot;&gt;Limit max nesting of sequences of mappings in YAML parsers&lt;/h3&gt;
  &lt;a href=&quot;#limit-max-nesting-of-sequences-of-mappings-in-yaml-parsers&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Limit max nesting of sequences of mappings in YAML parsers&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;YAML&lt;/code&gt; parsers use recursion to parse sequences and mappings but didn’t
limit how deep they could be nested. A deeply nested YAML document could lead to
stack overflows (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/17107&quot;&gt;#17107&lt;/a&gt;).&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max_nesting&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;YAML::PullParser&lt;/code&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/17107&quot;&gt;#17107&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks, &lt;a href=&quot;https://github.com/ysbaddaden&quot;&gt;@ysbaddaden&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;prevent-excessive-expansion-of-aliases-in-yaml-parsers&quot;&gt;Prevent excessive expansion of aliases in YAML parsers&lt;/h3&gt;
  &lt;a href=&quot;#prevent-excessive-expansion-of-aliases-in-yaml-parsers&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Prevent excessive expansion of aliases in YAML parsers&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;YAML&lt;/code&gt; parsers were vulnerable to the billion laughs attack when expanding
aliases, growing the document from 100 nodes to over 1 billion nodes for
example. The parser had no issues parsing the document, but any attempt to walk
the stack could walk the same nodes over and over, quickly slowing down
applications.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add alias vs anchor ratio check to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;YAML::PullParser&lt;/code&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/17109&quot;&gt;#17109&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Memoize anchor name in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;YAML::PullParser&lt;/code&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/17108&quot;&gt;#17108&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks, &lt;a href=&quot;https://github.com/ysbaddaden&quot;&gt;@ysbaddaden&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;For more details, visit the &lt;a href=&quot;https://github.com/crystal-lang/crystal/releases/tag/1.20.3&quot;&gt;full
changelog&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;callout callout--thanks&quot;&gt;
  &lt;div class=&quot;callout-title&quot;&gt;Thanks
&lt;/div&gt;
&lt;p&gt;We have been able to do all of this thanks to the continued support of
 &lt;a href=&quot;https://www.84codes.com/&quot;&gt;84codes&lt;/a&gt; and every other &lt;a href=&quot;/sponsors&quot;&gt;sponsor&lt;/a&gt;. To
 maintain and increase the development pace, donations and sponsorships are
 essential. &lt;a href=&quot;https://opencollective.com/crystal-lang&quot;&gt;OpenCollective&lt;/a&gt; is
 available for that.&lt;/p&gt;

&lt;p&gt;Reach out to &lt;a href=&quot;mailto:crystal@manas.tech&quot;&gt;crystal@manas.tech&lt;/a&gt; if you’d like to
 become a direct sponsor or find other ways to support Crystal. We thank you in
 advance!&lt;/p&gt;


  &lt;a class=&quot;hex&quot; href=&quot;/sponsors#contribute&quot;&gt;Contribute&lt;/a&gt;
&lt;/div&gt;</content>
    </entry>
    <entry>
      <title>Post Mortem: HTTP Request Smuggling Vulnerability</title>
      <author>
        <name>Julien Portalier</name>
        <uri>https://github.com/ysbaddaden/</uri>
      </author>
      <link href="https://deploy-preview-1093--crystal-website.netlify.app/2026/05/26/http-request-smuggling-vulnerability-in-http-server/" rel="alternate" type="text/html" title="Post Mortem: HTTP Request Smuggling Vulnerability" />
      <published>2026-05-26T00:00:00+00:00</published>
      <updated>2026-05-26T00:00:00+00:00</updated>
      <id>https://deploy-preview-1093--crystal-website.netlify.app/2026/05/26/http-request-smuggling-vulnerability-in-http-server</id>
      <summary type="html">On 12 April 2026, we received a vulnerability report regarding an HTTP request smuggling vulnerability in HTTP::Server.</summary>
      <content type="html" xml:base="https://deploy-preview-1093--crystal-website.netlify.app/2026/05/26/http-request-smuggling-vulnerability-in-http-server/">&lt;p&gt;On 12 April 2026, we received a vulnerability report
regarding an HTTP request smuggling vulnerability in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP::Server&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The issue was caused by the HTTP request parser prioritizing the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt; header over the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer-Encoding&lt;/code&gt; header, which can lead to
desynchronization when a proxy that prioritizes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer-Encoding&lt;/code&gt; header
sits in front of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP::Server&lt;/code&gt; for example.&lt;/p&gt;

&lt;p&gt;The vulnerability was patched in &lt;a href=&quot;https://crystal-lang.org/2026/04/16/1.20.0-released/&quot;&gt;Crystal 1.20.0&lt;/a&gt; and &lt;a href=&quot;https://crystal-lang.org/2026/04/27/1.19.2-released/&quot;&gt;Crystal 1.19.2&lt;/a&gt;,
following the mitigation from &lt;a href=&quot;https://www.rfc-editor.org/info/rfc9112/#section-6.1&quot;&gt;RFC 9112, Section 6.1&lt;/a&gt; to always reject requests
with both headers and to prioritize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer-Encoding&lt;/code&gt; then close the
connection.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;timeline&quot;&gt;Timeline&lt;/h2&gt;
  &lt;a href=&quot;#timeline&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Timeline&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;2026-04-12&lt;/strong&gt;: Gabriel Rodrigues reported the vulnerability to &lt;a href=&quot;mailto:security@manas.tech&quot;&gt;security@manas.tech&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;2026-04-13&lt;/strong&gt;: The report was shared with the Crystal Core Team and
acknowledged to the reporter. The risk was assessed as low by team.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;2026-04-15&lt;/strong&gt;: The patch of choice (rejecting requests with both headers) was
confirmed as the mitigation. The reporter was informed about the assessment
and mitigation strategy.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;2026-04-16&lt;/strong&gt;: The &lt;a href=&quot;https://github.com/crystal-lang/crystal/commit/c948b31ee6d5414050e771f89955c7dc02883ebc)&quot;&gt;patch&lt;/a&gt; was merged and a &lt;a href=&quot;https://github.com/crystal-lang/crystal/security/advisories/GHSA-wqh5-7w63-pm68&quot;&gt;security advisory&lt;/a&gt; was published.
&lt;a href=&quot;https://crystal-lang.org/2026/04/16/1.20.0-released/&quot;&gt;Crystal 1.20.0&lt;/a&gt; was released with the fix.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;2026-04-27&lt;/strong&gt;: &lt;a href=&quot;https://crystal-lang.org/2026/04/27/1.19.2-released/&quot;&gt;Crystal 1.19.2&lt;/a&gt; was released with the backported patch.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;technical-details&quot;&gt;Technical Details&lt;/h2&gt;
  &lt;a href=&quot;#technical-details&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Technical Details&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;root-cause&quot;&gt;Root Cause&lt;/h3&gt;
  &lt;a href=&quot;#root-cause&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Root Cause&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;The issue resided in the HTTP Request parser, specifically in the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parse_headers_and_body&lt;/code&gt; method. The method used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elsif&lt;/code&gt; to
connect the checks for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer-Encoding&lt;/code&gt;, ensuring only
one branch would execute. This meant that if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt; was present, the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer-Encoding&lt;/code&gt; branch would never be evaluated, regardless of its value.&lt;/p&gt;

&lt;div class=&quot;language-crystal highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;code_section&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content_length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content_length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FixedLengthContent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content_length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Transfer-Encoding&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;chunked&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ChunkedContent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This behavior wasn’t compliant with the mitigation from &lt;a href=&quot;https://www.rfc-editor.org/info/rfc9112/#section-6.1&quot;&gt;RFC 9112, Section 6.1&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A server MAY reject a request that contains both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer-Encoding&lt;/code&gt; or process such a request in accordance with the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer-Encoding&lt;/code&gt; alone. Regardless, the server MUST close the connection
after responding to such a request to avoid the potential attacks.&lt;/p&gt;

  &lt;p&gt;A server or client that receives an HTTP/1.0 message containing a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer-Encoding&lt;/code&gt; header field MUST treat the message as if the framing is
faulty, even if a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt; is present, and close the connection after
processing the message.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;example&quot;&gt;Example&lt;/h3&gt;
  &lt;a href=&quot;#example&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Example&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;An attacker could craft a request like the following (no proxy required for
demonstration):&lt;/p&gt;

&lt;div class=&quot;language-http highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;code_section&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;POST&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;HTTP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1.1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example.com&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Content-Length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Transfer-Encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;chunked&lt;/span&gt;

43
GET /admin HTTP/1.1
Host: example.com

0

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This request is ambiguous: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt; declares a 4 bytes body (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;43\r\n&lt;/code&gt;)
while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer-Encoding&lt;/code&gt; would start reading. Since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP::Server&lt;/code&gt; favors
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt; it would execute the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;POST /&lt;/code&gt; request then continue with the
smuggled &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET /admin&lt;/code&gt; request.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;impact&quot;&gt;Impact&lt;/h3&gt;
  &lt;a href=&quot;#impact&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Impact&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;The vulnerability allowed attackers to inject arbitrary HTTP requests into the
connection between a reverse proxy and a Crystal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP::Server&lt;/code&gt;. This could
bypass authentication, rate limiting, or access control enforced at the proxy
layer for example. However, exploitation required a vulnerable or non-compliant
proxy, limiting the practical impact.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;severity-assessment&quot;&gt;Severity Assessment&lt;/h2&gt;
  &lt;a href=&quot;#severity-assessment&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Severity Assessment&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Can it be directly exploited? No.&lt;/li&gt;
  &lt;li&gt;Can it be exploited through a third party? Yes: vulnerable proxy or load balancer.&lt;/li&gt;
  &lt;li&gt;Are there possible exploits for the software flaw? Yes: CL.TE for example.&lt;/li&gt;
  &lt;li&gt;Are there known exploits for HTTP::Server + third party? No.&lt;/li&gt;
  &lt;li&gt;Are there known threats? No.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Risk: low.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;mitigation&quot;&gt;Mitigation&lt;/h2&gt;
  &lt;a href=&quot;#mitigation&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Mitigation&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;The vulnerability stemmed from non-compliance with RFC 9112, which explicitly
states that a server should either reject requests with both headers or
prioritize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer-Encoding&lt;/code&gt; to mitigate request smuggling.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP::Server&lt;/code&gt; thus now rejects requests with both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer-Encoding&lt;/code&gt; and the HTTP parser now prioritizes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer-Encoding&lt;/code&gt;
header before considering &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt;, aligning with the RFC 9112.&lt;/p&gt;

&lt;p&gt;This fix was included in Crystal 1.20.0 and 1.19.2.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;lessons-learned&quot;&gt;Lessons Learned&lt;/h2&gt;
  &lt;a href=&quot;#lessons-learned&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Lessons Learned&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;RFC Compliance Matters&lt;/strong&gt;: Adhering to RFCs is critical for security and
interoperability. Non-compliance can introduce vulnerabilities, even if they
seem theoretical.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Vulnerability in Chains&lt;/strong&gt;: A vulnerable server may not be at risk, but a
bug and a vulnerability in different software can lead to an exploitable
attack.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Training&lt;/strong&gt;: We treated this as a serious issue, even if the practical
impact was low, if only to prepare for more severe vulnerabilities in the
future.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
  &lt;a href=&quot;#references&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled References&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/crystal-lang/crystal/security/advisories/GHSA-wqh5-7w63-pm68&quot;&gt;GitHub Advisory: GHSA-wqh5-7w63-pm68&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.rfc-editor.org/info/rfc9112/#section-6.1&quot;&gt;RFC 9112, Section 6.1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://portswigger.net/web-security/request-smuggling&quot;&gt;PortSwigger: HTTP Request Smuggling&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://portswigger.net/research/http1-must-die&quot;&gt;PortSwigger: HTTP/1 Must Die&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h2&gt;
  &lt;a href=&quot;#acknowledgements&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Acknowledgements&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Thank you Gabriel Rodrigues for reporting this vulnerability!&lt;/p&gt;</content>
    </entry>
    <entry>
      <title>Crystal 1.20.2 is released!</title>
      <author>
        <name>Johannes Müller</name>
        <uri>https://github.com/straight-shoota/</uri>
      </author>
      <link href="https://deploy-preview-1093--crystal-website.netlify.app/2026/05/15/1.20.2-released/" rel="alternate" type="text/html" title="Crystal 1.20.2 is released!" />
      <published>2026-05-15T00:00:00+00:00</published>
      <updated>2026-05-15T00:00:00+00:00</updated>
      <id>https://deploy-preview-1093--crystal-website.netlify.app/2026/05/15/1.20.2-released</id>
      <summary type="html">We are announcing a new Crystal release 1.20.2 with a couple of regressions fixed.</summary>
      <content type="html" xml:base="https://deploy-preview-1093--crystal-website.netlify.app/2026/05/15/1.20.2-released/">&lt;p&gt;We are announcing a new Crystal release 1.20.2 with a couple of regressions fixed.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;/2026/04/16/1.20.0-released/&quot;&gt;the release notes of 1.20.0&lt;/a&gt; for all the
changes introduced in Crystal 1.20.&lt;/p&gt;

&lt;p&gt;Pre-built packages are available on &lt;a href=&quot;https://github.com/crystal-lang/crystal/releases/tag/1.20.2&quot;&gt;GitHub
Releases&lt;/a&gt; and our
official distribution channels. See
&lt;a href=&quot;https://crystal-lang.org/install/&quot;&gt;crystal-lang.org/install&lt;/a&gt; for installation
instructions.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;stats&quot;&gt;Stats&lt;/h2&gt;
  &lt;a href=&quot;#stats&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Stats&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;This release includes &lt;a href=&quot;https://github.com/crystal-lang/crystal/pulls?q=is%3Apr+milestone%3A1.20.2&quot;&gt;2 bug fixes since
1.20.1&lt;/a&gt;
by 1 contributor. We thank all the contributors for all the effort put into
improving the language! ❤️&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;changes&quot;&gt;Changes&lt;/h2&gt;
  &lt;a href=&quot;#changes&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Changes&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;randomness-in-rangesample&quot;&gt;Randomness in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range#sample&lt;/code&gt;&lt;/h3&gt;
  &lt;a href=&quot;#randomness-in-rangesample&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Randomness in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range#sample&lt;/code&gt;&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;This patch release brings the regression fix for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range#sample&lt;/code&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16909&quot;&gt;#16909&lt;/a&gt;) that could
eventually lose randomness to the 1.20 release branch.
This was previously released as a backport for 1.19 in Crystal 1.19.2 (&lt;a href=&quot;https://github.com/crystal-lang/crystal/issues/16853&quot;&gt;#16853&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks, &lt;a href=&quot;https://github.com/ysbaddaden&quot;&gt;@ysbaddaden&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;For more details, visit the &lt;a href=&quot;https://github.com/crystal-lang/crystal/releases/tag/1.20.1&quot;&gt;full
changelog&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;callout callout--thanks&quot;&gt;
  &lt;div class=&quot;callout-title&quot;&gt;Thanks
&lt;/div&gt;
&lt;p&gt;We have been able to do all of this thanks to the continued support of
 &lt;a href=&quot;https://www.84codes.com/&quot;&gt;84codes&lt;/a&gt; and every other &lt;a href=&quot;/sponsors&quot;&gt;sponsor&lt;/a&gt;. To
 maintain and increase the development pace, donations and sponsorships are
 essential. &lt;a href=&quot;https://opencollective.com/crystal-lang&quot;&gt;OpenCollective&lt;/a&gt; is
 available for that.&lt;/p&gt;

&lt;p&gt;Reach out to &lt;a href=&quot;mailto:crystal@manas.tech&quot;&gt;crystal@manas.tech&lt;/a&gt; if you’d like to
 become a direct sponsor or find other ways to support Crystal. We thank you in
 advance!&lt;/p&gt;


  &lt;a class=&quot;hex&quot; href=&quot;/sponsors#contribute&quot;&gt;Contribute&lt;/a&gt;
&lt;/div&gt;</content>
    </entry>
    <entry>
      <title>Crystal 1.20.1 is released!</title>
      <author>
        <name>Johannes Müller</name>
        <uri>https://github.com/straight-shoota/</uri>
      </author>
      <link href="https://deploy-preview-1093--crystal-website.netlify.app/2026/04/29/1.20.1-released/" rel="alternate" type="text/html" title="Crystal 1.20.1 is released!" />
      <published>2026-04-29T00:00:00+00:00</published>
      <updated>2026-04-29T00:00:00+00:00</updated>
      <id>https://deploy-preview-1093--crystal-website.netlify.app/2026/04/29/1.20.1-released</id>
      <summary type="html">We are announcing a new Crystal release 1.20.1 with a couple of regressions fixed.</summary>
      <content type="html" xml:base="https://deploy-preview-1093--crystal-website.netlify.app/2026/04/29/1.20.1-released/">&lt;p&gt;We are announcing a new Crystal release 1.20.1 with a couple of regressions fixed.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;/2026/04/16/1.20.0-released/&quot;&gt;the release notes of 1.20.0&lt;/a&gt; for all the
changes introduced in Crystal 1.20.&lt;/p&gt;

&lt;p&gt;Pre-built packages are available on &lt;a href=&quot;https://github.com/crystal-lang/crystal/releases/tag/1.20.1&quot;&gt;GitHub
Releases&lt;/a&gt; and our
official distribution channels. See
&lt;a href=&quot;https://crystal-lang.org/install/&quot;&gt;crystal-lang.org/install&lt;/a&gt; for installation
instructions.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;stats&quot;&gt;Stats&lt;/h2&gt;
  &lt;a href=&quot;#stats&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Stats&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;This release includes &lt;a href=&quot;https://github.com/crystal-lang/crystal/pulls?q=is%3Apr+milestone%3A1.20.1&quot;&gt;9 changes since
1.20.0&lt;/a&gt;
by 2 contributors. We thank all the contributors for all the effort put into
improving the language! ❤️&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;changes&quot;&gt;Changes&lt;/h2&gt;
  &lt;a href=&quot;#changes&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Changes&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;kernel-tls&quot;&gt;Kernel TLS&lt;/h3&gt;
  &lt;a href=&quot;#kernel-tls&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Kernel TLS&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Support for Kernel TLS was introduced in 1.20.0 but it showed issues in production. Some have been fixed (&lt;a href=&quot;https://github.com/crystal-lang/crystal/issues/16888&quot;&gt;#16888&lt;/a&gt;) but there are still some problems so it was disabled by default (&lt;a href=&quot;https://github.com/crystal-lang/crystal/issues/16897&quot;&gt;#16897&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;You can opt-in to Kernel TLS by adding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ENABLE_KTLS&lt;/code&gt; option:&lt;/p&gt;

&lt;div class=&quot;language-cr highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;code_section&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;ssl_context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;OpenSSL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SSL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ENABLE_KTLS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Thanks, &lt;a href=&quot;https://github.com/ysbaddaden&quot;&gt;@ysbaddaden&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;randomness-in-rangesample&quot;&gt;Randomness in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range#sample&lt;/code&gt;&lt;/h3&gt;
  &lt;a href=&quot;#randomness-in-rangesample&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Randomness in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range#sample&lt;/code&gt;&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;This patch release fixes a regression in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range#sample&lt;/code&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/issues/16853&quot;&gt;#16853&lt;/a&gt;) that could
eventually lose randomness.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks, &lt;a href=&quot;https://github.com/ysbaddaden&quot;&gt;@ysbaddaden&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;For more details, visit the &lt;a href=&quot;https://github.com/crystal-lang/crystal/releases/tag/1.20.1&quot;&gt;full
changelog&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;callout callout--thanks&quot;&gt;
  &lt;div class=&quot;callout-title&quot;&gt;Thanks
&lt;/div&gt;
&lt;p&gt;We have been able to do all of this thanks to the continued support of
 &lt;a href=&quot;https://www.84codes.com/&quot;&gt;84codes&lt;/a&gt; and every other &lt;a href=&quot;/sponsors&quot;&gt;sponsor&lt;/a&gt;. To
 maintain and increase the development pace, donations and sponsorships are
 essential. &lt;a href=&quot;https://opencollective.com/crystal-lang&quot;&gt;OpenCollective&lt;/a&gt; is
 available for that.&lt;/p&gt;

&lt;p&gt;Reach out to &lt;a href=&quot;mailto:crystal@manas.tech&quot;&gt;crystal@manas.tech&lt;/a&gt; if you’d like to
 become a direct sponsor or find other ways to support Crystal. We thank you in
 advance!&lt;/p&gt;


  &lt;a class=&quot;hex&quot; href=&quot;/sponsors#contribute&quot;&gt;Contribute&lt;/a&gt;
&lt;/div&gt;</content>
    </entry>
    <entry>
      <title>Crystal 1.19.2 is released!</title>
      <author>
        <name>Julien Portalier</name>
        <uri>https://github.com/ysbaddaden/</uri>
      </author>
      <link href="https://deploy-preview-1093--crystal-website.netlify.app/2026/04/27/1.19.2-released/" rel="alternate" type="text/html" title="Crystal 1.19.2 is released!" />
      <published>2026-04-27T00:00:00+00:00</published>
      <updated>2026-04-27T00:00:00+00:00</updated>
      <id>https://deploy-preview-1093--crystal-website.netlify.app/2026/04/27/1.19.2-released</id>
      <summary type="html">We are announcing a new Crystal release 1.19.2 with two regressions fixed.</summary>
      <content type="html" xml:base="https://deploy-preview-1093--crystal-website.netlify.app/2026/04/27/1.19.2-released/">&lt;p&gt;We are announcing a new Crystal release 1.19.2 with two regressions fixed.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;/2026/01/15/1.19.0-released/&quot;&gt;the release notes of 1.19.0&lt;/a&gt; for all the
changes introduced in Crystal 1.19.&lt;/p&gt;

&lt;p&gt;Pre-built packages are available on &lt;a href=&quot;https://github.com/crystal-lang/crystal/releases/tag/1.19.2&quot;&gt;GitHub
Releases&lt;/a&gt; and our
official distribution channels. See
&lt;a href=&quot;https://crystal-lang.org/install/&quot;&gt;crystal-lang.org/install&lt;/a&gt; for installation
instructions.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;stats&quot;&gt;Stats&lt;/h2&gt;
  &lt;a href=&quot;#stats&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Stats&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;This release includes &lt;a href=&quot;https://github.com/crystal-lang/crystal/pulls?q=is%3Apr+milestone%3A1.19.2&quot;&gt;3 changes since
1.19.1&lt;/a&gt;
by 2 contributors. We thank all the contributors for all the effort put into
improving the language! ❤️&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;changes&quot;&gt;Changes&lt;/h2&gt;
  &lt;a href=&quot;#changes&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Changes&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;security&quot;&gt;Security&lt;/h3&gt;
  &lt;a href=&quot;#security&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Security&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP::Server&lt;/code&gt; accepted requests containing both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer-Encoding&lt;/code&gt; headers and prioritized &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt;. This allowed HTTP
request smuggling as per &lt;a href=&quot;https://cwe.mitre.org/data/definitions/444.html&quot;&gt;CWE-444&lt;/a&gt; when the server is behind a vulnerable
frontend. Refer to the
&lt;a href=&quot;https://github.com/crystal-lang/crystal/security/advisories/GHSA-wqh5-7w63-pm68&quot;&gt;advisory&lt;/a&gt;
for more details.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP::Server&lt;/code&gt; now rejects requests where both headers are present. The HTTP
parser now ignores &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt; when the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer-Encoding&lt;/code&gt; header is
present (commit &lt;a href=&quot;https://github.com/crystal-lang/crystal/commit/c948b31ee6d5414050e771f89955c7dc02883ebc&quot;&gt;c948b31&lt;/a&gt;).&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;regressions&quot;&gt;Regressions&lt;/h3&gt;
  &lt;a href=&quot;#regressions&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Regressions&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;This patch release fixes a regression in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range#sample&lt;/code&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16866&quot;&gt;#16866&lt;/a&gt;) that could
eventually lose randomness.&lt;/p&gt;

&lt;p&gt;For more details, visit the &lt;a href=&quot;https://github.com/crystal-lang/crystal/releases/tag/1.19.2&quot;&gt;full
changelog&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;callout callout--thanks&quot;&gt;
  &lt;div class=&quot;callout-title&quot;&gt;Thanks
&lt;/div&gt;
&lt;p&gt;We have been able to do all of this thanks to the continued support of
 &lt;a href=&quot;https://www.84codes.com/&quot;&gt;84codes&lt;/a&gt; and every other &lt;a href=&quot;/sponsors&quot;&gt;sponsor&lt;/a&gt;. To
 maintain and increase the development pace, donations and sponsorships are
 essential. &lt;a href=&quot;https://opencollective.com/crystal-lang&quot;&gt;OpenCollective&lt;/a&gt; is
 available for that.&lt;/p&gt;

&lt;p&gt;Reach out to &lt;a href=&quot;mailto:crystal@manas.tech&quot;&gt;crystal@manas.tech&lt;/a&gt; if you’d like to
 become a direct sponsor or find other ways to support Crystal. We thank you in
 advance!&lt;/p&gt;


  &lt;a class=&quot;hex&quot; href=&quot;/sponsors#contribute&quot;&gt;Contribute&lt;/a&gt;
&lt;/div&gt;</content>
    </entry>
    <entry>
      <title>Crystal 1.20.0 is released!</title>
      <author>
        <name>Julien Portalier</name>
        <uri>https://github.com/ysbaddaden/</uri>
      </author>
      <link href="https://deploy-preview-1093--crystal-website.netlify.app/2026/04/16/1.20.0-released/" rel="alternate" type="text/html" title="Crystal 1.20.0 is released!" />
      <published>2026-04-16T00:00:00+00:00</published>
      <updated>2026-04-16T00:00:00+00:00</updated>
      <id>https://deploy-preview-1093--crystal-website.netlify.app/2026/04/16/1.20.0-released</id>
      <summary type="html">We are announcing a new Crystal release 1.20.0 with several new features and bug fixes.</summary>
      <content type="html" xml:base="https://deploy-preview-1093--crystal-website.netlify.app/2026/04/16/1.20.0-released/">&lt;p&gt;We are announcing a new Crystal release 1.20.0 with several new features and bug
fixes.&lt;/p&gt;

&lt;p&gt;Pre-built packages are available on &lt;a href=&quot;https://github.com/crystal-lang/crystal/releases/tag/1.20.0&quot;&gt;GitHub
Releases&lt;/a&gt; and our
official distribution channels. See
&lt;a href=&quot;https://crystal-lang.org/install/&quot;&gt;crystal-lang.org/install&lt;/a&gt; for installation
instructions.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;stats&quot;&gt;Stats&lt;/h2&gt;
  &lt;a href=&quot;#stats&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Stats&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;This release includes &lt;a href=&quot;https://github.com/crystal-lang/crystal/pulls?q=is%3Apr+milestone%3A1.20.0&quot;&gt;161 changes since 1.19.1&lt;/a&gt;
by 21 contributors. We thank all the contributors for all the effort put into
improving the language! ❤️&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;changes&quot;&gt;Changes&lt;/h2&gt;
  &lt;a href=&quot;#changes&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Changes&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Below we list the most remarkable changes in the language, compiler and stdlib.
For more details, visit the &lt;a href=&quot;https://github.com/crystal-lang/crystal/releases/tag/1.20.0&quot;&gt;full
changelog&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;breaking&quot;&gt;Breaking&lt;/h3&gt;
  &lt;a href=&quot;#breaking&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Breaking&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;We do not expect any breaking changes in existing code. We expect the few
bugfixes below to not negatively impact your programs. If you notice any
unexpected issues, please let us know in the &lt;a href=&quot;https://github.com/crystal-lang/crystal/issues&quot;&gt;issue tracker&lt;/a&gt; or &lt;a href=&quot;https://forum.crystal-lang.org/&quot;&gt;forum&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;OpenSSL sockets shouldn’t flush on read (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16650&quot;&gt;#16650&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Fix &lt;a href=&quot;https://crystal-lang.org/api/master/Process.html#wait:Process::Status-instance-method&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Process#wait&lt;/code&gt;&lt;/a&gt; to not close &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@input&lt;/code&gt; before waiting (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16620&quot;&gt;#16620&lt;/a&gt;, &lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16638&quot;&gt;#16638&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Ensure that heredoc lexing allows only valid identifiers (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16548&quot;&gt;#16548&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/straight-shoota&quot;&gt;@straight-shoota&lt;/a&gt;, &lt;a href=&quot;https://github.com/ysbaddaden&quot;&gt;@ysbaddaden&lt;/a&gt;, &lt;a href=&quot;https://github.com/Sija&quot;&gt;@Sija&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;security&quot;&gt;Security&lt;/h3&gt;
  &lt;a href=&quot;#security&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Security&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP::Server&lt;/code&gt; accepted requests containing both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer-Encoding&lt;/code&gt;
headers and prioritized &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt;. This allowed HTTP request smuggling as per
&lt;a href=&quot;https://cwe.mitre.org/data/definitions/444.html&quot;&gt;CWE-444&lt;/a&gt; when the server is behind a vulnerable frontend. Refer to the
&lt;a href=&quot;https://github.com/crystal-lang/crystal/security/advisories/GHSA-wqh5-7w63-pm68&quot;&gt;advisory&lt;/a&gt;
for more details.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP::Server&lt;/code&gt; now rejects requests where both headers are present. The HTTP parser now
ignores &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt; when the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer-Encoding&lt;/code&gt; header is present. (commit &lt;a href=&quot;https://github.com/crystal-lang/crystal/commit/c948b31ee6d5414050e771f89955c7dc02883ebc&quot;&gt;c948b31&lt;/a&gt;).&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;target-features&quot;&gt;Target features&lt;/h3&gt;
  &lt;a href=&quot;#target-features&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Target features&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/crystal-lang/rfcs/pull/20&quot;&gt;RFC 0020&lt;/a&gt; introduces a new &lt;a href=&quot;https://crystal-lang.org/api/master/TargetFeature.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@[TargetFeature]&lt;/code&gt;&lt;/a&gt; annotation that allows specifying
CPU features or a CPU model or variant for individual functions. It
complements the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--mattr&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--mcpu&lt;/code&gt; CLI arguments that target the whole
program. This allows embedding multiple optimized functions for different CPU
features into a single executable, for example a portable SIMD
implementation alongside AVX2 and AVX512 alternatives.&lt;/p&gt;

&lt;p&gt;The program is responsible for detecting which feature is available and calling the
proper function at runtime. Otherwise, the program might crash with SIGILL, for
example.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class=&quot;language-crystal highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;code_section&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flag?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:x86_64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@[TargetFeature(&quot;+avx2&quot;)]&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo_avx2&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;cpu_supports_avx2?&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;

&lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo_portable&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flag?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:x86_64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo_avx2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cpu_supports_avx2?&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;foo_portable&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While not strictly required, we still recommend wrapping architecture-specific
method definitions within macro flag checks.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add &lt;a href=&quot;https://crystal-lang.org/api/master/TargetFeature.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@[TargetFeature]&lt;/code&gt;&lt;/a&gt; annotation (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16717&quot;&gt;#16717&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/stakach&quot;&gt;@stakach&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;execution-contexts&quot;&gt;Execution contexts&lt;/h3&gt;
  &lt;a href=&quot;#execution-contexts&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Execution contexts&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Execution contexts from &lt;a href=&quot;https://github.com/crystal-lang/rfcs/pull/2&quot;&gt;RFC 0002&lt;/a&gt; continue as a final preview feature,
enabled with the compiler flags &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Dpreview_mt -Dexecution_context&lt;/code&gt;. We plan to
enable it by default in Crystal 1.21.&lt;/p&gt;

&lt;p&gt;In addition to fixing bugs, we implemented M:N scheduling that allows threads to
be attached to and detached from a context. This avoids blocking other
fibers on certain syscalls, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getaddrinfo&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fiber::ExecutionContext::ThreadPool&lt;/code&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/15885&quot;&gt;#15885&lt;/a&gt;, &lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16750&quot;&gt;#16750&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Detach execution context scheduler from running thread during blocking syscall (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/15871&quot;&gt;#15871&lt;/a&gt;, &lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16679&quot;&gt;#16679&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The parallel contexts now automatically start threads to adapt to the actual
workload and distribute fibers across more cores when needed.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add adaptive scaling to &lt;a href=&quot;https://crystal-lang.org/api/master/Fiber/ExecutionContext/Parallel.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecutionContext::Parallel&lt;/code&gt;&lt;/a&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16719&quot;&gt;#16719&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This effort is part of the &lt;a href=&quot;/2024/02/09/84codes-manas-mt/&quot;&gt;ongoing project to improve multi-threading support&lt;/a&gt;
with the help of &lt;a href=&quot;https://www.84codes.com/&quot;&gt;84codes&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/ysbaddaden&quot;&gt;@ysbaddaden&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;process-api&quot;&gt;Process API&lt;/h3&gt;
  &lt;a href=&quot;#process-api&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Process API&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;This release brings a new ergonomic, safe, and portable API for spawning sub-processes, as proposed in &lt;a href=&quot;https://github.com/crystal-lang/rfcs/pull/25&quot;&gt;RFC 0025&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A significant change is that the modern API treats the command line as an array of strings.
The first element is the program to execute, and the remaining elements are its arguments.&lt;/p&gt;

&lt;div class=&quot;language-cr highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;code_section&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# legacy API:&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;crystal&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;tool&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;format&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# modern API:&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;crystal&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;tool&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;format&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The new API also includes convenient methods for capturing process output:
&lt;a href=&quot;https://crystal-lang.org/api/master/Process.html#capture%28args%3AEnumerable%28String%29%2C%2A%2Cenv%3AEnv%3Dnil%2Cclear_env%3ABool%3Dfalse%2Cinput%3AStdio%3DRedirect%3A%3AClose%2Cerror%3AStdio%3DRedirect%3A%3APipe%2Cchdir%3APath%7CString%7CNil%3Dnil%29%3AString-class-method&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Process.capture&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://crystal-lang.org/api/master/Process.html#capture_result%28args%3AEnumerable%28String%29%2C%2A%2Cenv%3AEnv%3Dnil%2Cclear_env%3ABool%3Dfalse%2Cinput%3AStdio%3DRedirect%3A%3AClose%2Coutput%3AStdio%3DRedirect%3A%3APipe%2Cerror%3AStdio%3DRedirect%3A%3APipe%2Cchdir%3APath%7CString%7CNil%3Dnil%29%3AResult-class-method&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Process.capture_result&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The new API does not have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shell&lt;/code&gt; parameter. If you need shell behaviour, we recommend running a shell explicitly.&lt;/p&gt;

&lt;p&gt;These are the most significant individual changes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add overloads with combined &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;args&lt;/code&gt; parameter instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;command, args&lt;/code&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16681&quot;&gt;#16681&lt;/a&gt;, &lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16739&quot;&gt;#16739&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Add &lt;a href=&quot;https://crystal-lang.org/api/master/Process.html#run%3F%28args%3AEnumerable%28String%29%2C%2A%2Cenv%3AEnv%3Dnil%2Cclear_env%3ABool%3Dfalse%2Cinput%3AStdio%3DRedirect%3A%3AClose%2Coutput%3AStdio%3DRedirect%3A%3AClose%2Cerror%3AStdio%3DRedirect%3A%3AClose%2Cchdir%3APath%7CString%7CNil%3Dnil%29%3AProcess%3A%3AStatus%7CNil-class-method&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Process.run?&lt;/code&gt;&lt;/a&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16738&quot;&gt;#16738&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Add &lt;a href=&quot;https://crystal-lang.org/api/master/Process.html#capture%28args%3AEnumerable%28String%29%2C%2A%2Cenv%3AEnv%3Dnil%2Cclear_env%3ABool%3Dfalse%2Cinput%3AStdio%3DRedirect%3A%3AClose%2Cerror%3AStdio%3DRedirect%3A%3APipe%2Cchdir%3APath%7CString%7CNil%3Dnil%29%3AString-class-method&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Process.capture&lt;/code&gt;&lt;/a&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16773&quot;&gt;#16773&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All new methods and overloads are experimental.
We expect to stabilize the API for the next release.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/straight-shoota&quot;&gt;@straight-shoota&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;io_uring&quot;&gt;io_uring&lt;/h3&gt;
  &lt;a href=&quot;#io_uring&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled io_uring&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;An io_uring event loop is available for Linux targets and can be selected by
specifying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Devloop=io_uring&lt;/code&gt; when compiling. The event loop is highly
experimental and its performance benefits will differ for every program. We don’t
expect it to be faster than epoll, and it may even be slower, except on some
benchmarks with SQPOLL enabled.&lt;/p&gt;

&lt;p&gt;SQPOLL can be selected by specifying the idle time for the kernel threads with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Dio_uring_sq_thread_idle=200&lt;/code&gt; (for 200ms). It is recommended to keep the idle
time low (below 2s), otherwise your CPU cores will regularly spin at 100% usage
when doing nothing.&lt;/p&gt;

&lt;p&gt;An interesting but potentially surprising behavior is that any I/O call that &lt;em&gt;could&lt;/em&gt;
yield the calling fiber will now &lt;em&gt;always&lt;/em&gt; yield. One benefit is that an always
ready socket won’t block other fibers from progressing. A downside is that there
might be lots of context switches.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add io_uring event loop (linux) (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16264&quot;&gt;#16264&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/ysbaddaden&quot;&gt;@ysbaddaden&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;kernel-tls&quot;&gt;Kernel TLS&lt;/h3&gt;
  &lt;a href=&quot;#kernel-tls&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Kernel TLS&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;div class=&quot;callout callout--note&quot;&gt;
  &lt;div class=&quot;callout-title&quot;&gt;Note
&lt;/div&gt;
&lt;p&gt;Kernel TLS is opt-in &lt;a href=&quot;/2026/04/29/1.20.1-released/#kernel-tls&quot;&gt;since 1.20.1&lt;/a&gt; due to unresolved issues.&lt;/p&gt;

&lt;/div&gt;

&lt;p&gt;Kernel TLS is now supported by default on Linux and FreeBSD as long as support
has been compiled into OpenSSL (which should be the default) and enabled on the
system (likely disabled by default), for example with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;modprobe tls&lt;/code&gt; on Linux.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add Kernel TLS support to custom &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OpenSSL::BIO&lt;/code&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16646&quot;&gt;#16646&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/ysbaddaden&quot;&gt;@ysbaddaden&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;macros&quot;&gt;Macros&lt;/h3&gt;
  &lt;a href=&quot;#macros&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Macros&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#select&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#reject&lt;/code&gt; to &lt;a href=&quot;https://crystal-lang.org/api/master/Crystal/Macros/HashLiteral.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HashLiteral&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://crystal-lang.org/api/master/Crystal/Macros/NamedTupleLiteral.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NamedTupleLiteral&lt;/code&gt;&lt;/a&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16558&quot;&gt;#16558&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Refine error message for unsupported named arguments in macros (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16576&quot;&gt;#16576&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/Blacksmoke16&quot;&gt;@Blacksmoke16&lt;/a&gt;, &lt;a href=&quot;https://github.com/hahwul&quot;&gt;@hahwul&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;standard-library&quot;&gt;Standard library&lt;/h3&gt;
  &lt;a href=&quot;#standard-library&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Standard library&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://crystal-lang.org/api/master/OptionParser.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OptionParser&lt;/code&gt;&lt;/a&gt; now supports option bundling and can parse &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-ncfoo&lt;/code&gt;
as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-n -c foo&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add short option bundling for &lt;a href=&quot;https://crystal-lang.org/api/master/OptionParser.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OptionParser&lt;/code&gt;&lt;/a&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16770&quot;&gt;#16770&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/Qard&quot;&gt;@Qard&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://crystal-lang.org/api/master/OAuth.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OAuth&lt;/code&gt;&lt;/a&gt; module expected a success response on HTTP OK statuses, but multiple
OAuth providers send error responses with an HTTP OK status (sic).&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Detect &lt;a href=&quot;https://crystal-lang.org/api/master/OAuth.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OAuth&lt;/code&gt;&lt;/a&gt; error in payload (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16634&quot;&gt;#16634&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/jgaskins&quot;&gt;@jgaskins&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://crystal-lang.org/api/master/HTTP/WebSocket.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP::WebSocket&lt;/code&gt;&lt;/a&gt; can now negotiate sub-protocols.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sec-WebSocket-Protocol&lt;/code&gt; checks to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP::WebSocket::Protocol&lt;/code&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16600&quot;&gt;#16600&lt;/a&gt;, &lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16671&quot;&gt;#16671&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Add support for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sec-WebSocket-Protocol&lt;/code&gt; to &lt;a href=&quot;https://crystal-lang.org/api/master/HTTP/WebSocketHandler.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP::WebSocketHandler&lt;/code&gt;&lt;/a&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16574&quot;&gt;#16574&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/antondalgren&quot;&gt;@antondalgren&lt;/a&gt;, &lt;a href=&quot;https://github.com/straight-shoota&quot;&gt;@straight-shoota&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://crystal-lang.org/api/master/StringScanner.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StringScanner&lt;/code&gt;&lt;/a&gt; saw multiple improvements, ranging from performance to subtle
niceties for debugging.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add &lt;a href=&quot;https://crystal-lang.org/api/master/StringScanner.html#scan(len:Int):String|Nil-instance-method&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StringScanner#scan&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://crystal-lang.org/api/master/StringScanner.html#check%28len%3AInt%29%3AString%7CNil-instance-method&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#check&lt;/code&gt;&lt;/a&gt;, and &lt;a href=&quot;https://crystal-lang.org/api/master/StringScanner.html#skip(len:Int):Int32|Nil-instance-method&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#skip&lt;/code&gt;&lt;/a&gt; overloads for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16557&quot;&gt;#16557&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Add &lt;a href=&quot;https://crystal-lang.org/api/master/StringScanner.html#peek_behind(len):String-instance-method&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StringScanner#peek_behind&lt;/code&gt;&lt;/a&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16593&quot;&gt;#16593&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Add convenience methods to &lt;a href=&quot;https://crystal-lang.org/api/master/StringScanner.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StringScanner&lt;/code&gt;&lt;/a&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16595&quot;&gt;#16595&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Improve cursor window format in &lt;a href=&quot;https://crystal-lang.org/api/master/StringScanner.html#inspect%28io%3AIO%29%3ANil-instance-method&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StringScanner#inspect&lt;/code&gt;&lt;/a&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16594&quot;&gt;#16594&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/jneen&quot;&gt;@jneen&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The memory management model for libxml2 changed in Crystal 1.17 to become manual
instead of integrating the GC. The change introduced another memory leak that is
now fixed.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xmlFree&lt;/code&gt; for the string pointer from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xmlNodeGetContent&lt;/code&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16688&quot;&gt;#16688&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/toddsundsted&quot;&gt;@toddsundsted&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Some additional niceties:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add &lt;a href=&quot;https://crystal-lang.org/api/master/IO.html#read_greedy(slice:Bytes):Int32-instance-method&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IO#read_greedy&lt;/code&gt;&lt;/a&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16535&quot;&gt;#16535&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Add &lt;a href=&quot;https://crystal-lang.org/api/master/FileUtils.html#rm_f(path:Path|String):Nil-instance-method&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FileUtils#rm_f&lt;/code&gt;&lt;/a&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/12832&quot;&gt;#12832&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Add &lt;a href=&quot;https://crystal-lang.org/api/master/Pointer.html#align_up(boundary:UInt64):Pointer(T)-instance-method&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pointer#align_up&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://crystal-lang.org/api/master/Pointer.html#align_down(boundary:UInt64):Pointer(T)-instance-method&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#align_down&lt;/code&gt;&lt;/a&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16585&quot;&gt;#16585&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Add &lt;a href=&quot;https://crystal-lang.org/api/master/HTTP/Server/Response.html#content_type:String%7CNil-instance-method&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP::Server::Response#content_type&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://crystal-lang.org/api/master/HTTP/Server/Response.html#content_length:Int64|Nil-instance-method&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#content_length&lt;/code&gt;&lt;/a&gt; as convenient accessors (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16712&quot;&gt;#16712&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/BlobCodes&quot;&gt;@BlobCodes&lt;/a&gt;, &lt;a href=&quot;https://github.com/CTC97&quot;&gt;@CTC97&lt;/a&gt;, &lt;a href=&quot;https://github.com/zw963&quot;&gt;@zw963&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;compiler&quot;&gt;Compiler&lt;/h3&gt;
  &lt;a href=&quot;#compiler&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Compiler&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Prefer modern linker (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mold&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lld&lt;/code&gt;) (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16696&quot;&gt;#16696&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/straight-shoota&quot;&gt;@straight-shoota&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Parse &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MacroVar&lt;/code&gt; with empty expressions: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%var{}&lt;/code&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16772&quot;&gt;#16772&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Parse &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProcNotation&lt;/code&gt; with empty arg parenthesis: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;() -&amp;gt;&lt;/code&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16741&quot;&gt;#16741&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--base-path&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;crystal docs&lt;/code&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16091&quot;&gt;#16091&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/straight-shoota&quot;&gt;@straight-shoota&lt;/a&gt;, &lt;a href=&quot;https://github.com/matiasgarciaisaia&quot;&gt;@matiasgarciaisaia&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;dependencies&quot;&gt;Dependencies&lt;/h3&gt;
  &lt;a href=&quot;#dependencies&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Dependencies&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Support for LLVM 22.1 and 23.0 (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16631&quot;&gt;#16631&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/HertzDevil&quot;&gt;@HertzDevil&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h3 id=&quot;deprecations&quot;&gt;Deprecations&lt;/h3&gt;
  &lt;a href=&quot;#deprecations&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Deprecations&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;There is a single deprecation in this release, and it is a trivial one: rename
&lt;a href=&quot;https://crystal-lang.org/api/master/Mutex.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mutex&lt;/code&gt;&lt;/a&gt; to &lt;a href=&quot;https://crystal-lang.org/api/master/Sync/Mutex.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sync::Mutex&lt;/code&gt;&lt;/a&gt; to use the new algorithm introduced in Crystal 1.19.&lt;/p&gt;

&lt;p&gt;We’re experimenting with a two-step mechanism to deprecate a feature. First, we
soft deprecate the method in the documentation with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DEPRECATE:&lt;/code&gt; callout, then
after a few releases we’ll hard deprecate by adding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@[Deprecated]&lt;/code&gt;
annotation.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Soft deprecate &lt;a href=&quot;https://crystal-lang.org/api/master/Mutex.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mutex&lt;/code&gt;&lt;/a&gt; in favor of &lt;a href=&quot;https://crystal-lang.org/api/master/Sync/Mutex.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sync::Mutex&lt;/code&gt;&lt;/a&gt; (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16737&quot;&gt;#16737&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks &lt;a href=&quot;https://github.com/ysbaddaden&quot;&gt;@ysbaddaden&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;callout callout--thanks&quot;&gt;
  &lt;div class=&quot;callout-title&quot;&gt;Thanks
&lt;/div&gt;
&lt;p&gt;We have been able to do all of this thanks to the continued support of
 &lt;a href=&quot;https://www.84codes.com/&quot;&gt;84codes&lt;/a&gt; and every other &lt;a href=&quot;/sponsors&quot;&gt;sponsor&lt;/a&gt;. To
 maintain and increase the development pace, donations and sponsorships are
 essential. &lt;a href=&quot;https://opencollective.com/crystal-lang&quot;&gt;OpenCollective&lt;/a&gt; is
 available for that.&lt;/p&gt;

&lt;p&gt;Reach out to &lt;a href=&quot;mailto:crystal@manas.tech&quot;&gt;crystal@manas.tech&lt;/a&gt; if you’d like to
 become a direct sponsor or find other ways to support Crystal. We thank you in
 advance!&lt;/p&gt;


  &lt;a class=&quot;hex&quot; href=&quot;/sponsors#contribute&quot;&gt;Contribute&lt;/a&gt;
&lt;/div&gt;</content>
    </entry>
    <entry>
      <title>Official Linux ARM64 builds</title>
      <author>
        <name>Julien Portalier</name>
        <uri>https://github.com/ysbaddaden/</uri>
      </author>
      <link href="https://deploy-preview-1093--crystal-website.netlify.app/2026/04/07/official-linux-arm64-builds/" rel="alternate" type="text/html" title="Official Linux ARM64 builds" />
      <published>2026-04-07T00:00:00+00:00</published>
      <updated>2026-04-07T00:00:00+00:00</updated>
      <id>https://deploy-preview-1093--crystal-website.netlify.app/2026/04/07/official-linux-arm64-builds</id>
      <summary type="html">This has been a long awaited feature: how to run Crystal on ARM64 CPUs?</summary>
      <content type="html" xml:base="https://deploy-preview-1093--crystal-website.netlify.app/2026/04/07/official-linux-arm64-builds/">&lt;p&gt;This has been a long awaited feature: how to run Crystal on ARM64 CPUs?&lt;/p&gt;

&lt;p&gt;Crystal has supported ARM64 as a tier 1 architecture for many years now, and
we already distribute an universal build for macOS, but still no ARM64 builds
for Linux.&lt;/p&gt;

&lt;p&gt;The wait is over! During the development of Crystal 1.19 we bootstrapped a
1.18.2 compiler for ARM64 that was then used to bootstrap official builds for
nightlies and the 1.19 release.&lt;/p&gt;

&lt;p&gt;The builds are available everywhere we provide an AMD64 build of the compiler
for Linux: &lt;a href=&quot;https://crystal-lang.org/install/nightlies/&quot;&gt;nightly builds&lt;/a&gt;, &lt;a href=&quot;https://github.com/crystal-lang/crystal/releases&quot;&gt;release tarballs&lt;/a&gt;, &lt;a href=&quot;https://hub.docker.com/r/crystallang/crystal&quot;&gt;Docker images&lt;/a&gt;, &lt;a href=&quot;https://snapcraft.io/crystal&quot;&gt;Snap&lt;/a&gt;, as well
as the &lt;a href=&quot;https://github.com/crystal-lang/install-crystal/&quot;&gt;install-crystal&lt;/a&gt; GitHub action — just select an ubuntu arm runner.&lt;/p&gt;</content>
    </entry>
    <entry>
      <title>Crystal talk at FOSDEM 2026</title>
      <author>
        <name>Johannes Müller</name>
        <uri>https://github.com/straight-shoota/</uri>
      </author>
      <link href="https://deploy-preview-1093--crystal-website.netlify.app/2026/01/23/crystal-talk-fosdem/" rel="alternate" type="text/html" title="Crystal talk at FOSDEM 2026" />
      <published>2026-01-23T00:00:00+00:00</published>
      <updated>2026-01-23T00:00:00+00:00</updated>
      <id>https://deploy-preview-1093--crystal-website.netlify.app/2026/01/23/crystal-talk-fosdem</id>
      <summary type="html">I’m giving a talk about Crystal at FOSDEM 2026 in Brussels: Crystal: A language for humans and computers. It’s in the Declarative and Minimalistic Computing track, on Sunday, 1 February 2026 at 09:00 in room UB4.136.</summary>
      <content type="html" xml:base="https://deploy-preview-1093--crystal-website.netlify.app/2026/01/23/crystal-talk-fosdem/">&lt;p&gt;I’m giving a talk about Crystal at FOSDEM 2026 in Brussels:
&lt;a href=&quot;https://fosdem.org/2026/schedule/event/N3AFSF-crystal/&quot;&gt;&lt;em&gt;Crystal: A language for humans and computers&lt;/em&gt;&lt;/a&gt;.
It’s in the &lt;a href=&quot;https://fosdem.org/2026/schedule/track/declarative-and-minimalistic-computing/&quot;&gt;Declarative and Minimalistic Computing track&lt;/a&gt;,
on Sunday, 1 February 2026 at 09:00 in room UB4.136.&lt;/p&gt;

&lt;p&gt;The talk is going to be an introduction into some concepts of Crystals.
If you are already familiar with the language, I hope it will still be worthwhile.&lt;/p&gt;

&lt;p&gt;If a couple of people are interested in a Crystal meetup, maybe
we can arrange to gather somewhere during FOSDEM. Let me know in the comments.
I’ll bring some Crystal merch.&lt;/p&gt;

&lt;p&gt;Hope to see you in Brussels!&lt;/p&gt;

&lt;p&gt;In case you can’t make it, the talk is being recorded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; The talk recording is now available. Thanks to the video team at FOSDEM!&lt;/p&gt;

&lt;video preload=&quot;none&quot; controls=&quot;controls&quot; width=&quot;75%&quot; style=&quot;aspect-ratio: 16/9;&quot; poster=&quot;/assets/blog/2026/fosdem-talk-screenshot.jpg&quot;&gt;
  &lt;source src=&quot;https://video.fosdem.org/2026/ub4136/N3AFSF-crystal.av1.webm&quot; type=&quot;video/webm; codecs=&amp;quot;av01.0.08M.08.0.110.01.01.01.0&amp;quot;&quot; /&gt;
  &lt;source src=&quot;https://video.fosdem.org/2026/ub4136/N3AFSF-crystal.mp4&quot; type=&quot;video/mp4&quot; /&gt;
&lt;/video&gt;</content>
    </entry>
    <entry>
      <title>Crystal 1.19.1 is released!</title>
      <author>
        <name>Julien Portalier</name>
        <uri>https://github.com/ysbaddaden/</uri>
      </author>
      <link href="https://deploy-preview-1093--crystal-website.netlify.app/2026/01/20/1.19.1-released/" rel="alternate" type="text/html" title="Crystal 1.19.1 is released!" />
      <published>2026-01-20T00:00:00+00:00</published>
      <updated>2026-01-20T00:00:00+00:00</updated>
      <id>https://deploy-preview-1093--crystal-website.netlify.app/2026/01/20/1.19.1-released</id>
      <summary type="html">We are announcing a new Crystal release 1.19.1 with two regressions fixed.</summary>
      <content type="html" xml:base="https://deploy-preview-1093--crystal-website.netlify.app/2026/01/20/1.19.1-released/">&lt;p&gt;We are announcing a new Crystal release 1.19.1 with two regressions fixed.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;/2026/01/15/1.19.0-released/&quot;&gt;the release notes of 1.19.0&lt;/a&gt; for all the changes introduced in Crystal 1.19.&lt;/p&gt;

&lt;p&gt;Pre-built packages are available on &lt;a href=&quot;https://github.com/crystal-lang/crystal/releases/tag/1.19.1&quot;&gt;GitHub
Releases&lt;/a&gt; and our
official distribution channels. See
&lt;a href=&quot;https://crystal-lang.org/install/&quot;&gt;crystal-lang.org/install&lt;/a&gt; for installation
instructions.&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;stats&quot;&gt;Stats&lt;/h2&gt;
  &lt;a href=&quot;#stats&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Stats&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;This release includes &lt;a href=&quot;https://github.com/crystal-lang/crystal/pulls?q=is%3Apr+milestone%3A1.19.1&quot;&gt;2 changes since
1.19.0&lt;/a&gt;
by 1 contributor. We thank all the contributors for all the effort put into
improving the language! ❤️&lt;/p&gt;

&lt;div class=&quot;header-wrapper&quot;&gt;
  &lt;h2 id=&quot;changes&quot;&gt;Changes&lt;/h2&gt;
  &lt;a href=&quot;#changes&quot;&gt;
    &lt;span aria-hidden=&quot;true&quot;&gt;&lt;svg height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill=&quot;currentcolor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
    &lt;/span&gt;
    &lt;span class=&quot;visually-hidden&quot;&gt;Section titled Changes&lt;/span&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;This patch release fixes regressions in timer conversions from absolute to relative
time (&lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16581&quot;&gt;#16581&lt;/a&gt;, &lt;a href=&quot;https://github.com/crystal-lang/crystal/pull/16583&quot;&gt;#16583&lt;/a&gt;) that led &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sleep(seconds)&lt;/code&gt; to immediately trigger instead
of waiting on some platforms (Darwin, BSDs, Windows) — both introduced in 1.19.0.&lt;/p&gt;

&lt;p&gt;For more details, visit the &lt;a href=&quot;https://github.com/crystal-lang/crystal/releases/tag/1.19.1&quot;&gt;full
changelog&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;callout callout--thanks&quot;&gt;
  &lt;div class=&quot;callout-title&quot;&gt;Thanks
&lt;/div&gt;
&lt;p&gt;We have been able to do all of this thanks to the continued support of
 &lt;a href=&quot;https://www.84codes.com/&quot;&gt;84codes&lt;/a&gt; and every other &lt;a href=&quot;/sponsors&quot;&gt;sponsor&lt;/a&gt;. To
 maintain and increase the development pace, donations and sponsorships are
 essential. &lt;a href=&quot;https://opencollective.com/crystal-lang&quot;&gt;OpenCollective&lt;/a&gt; is
 available for that.&lt;/p&gt;

&lt;p&gt;Reach out to &lt;a href=&quot;mailto:crystal@manas.tech&quot;&gt;crystal@manas.tech&lt;/a&gt; if you’d like to
 become a direct sponsor or find other ways to support Crystal. We thank you in
 advance!&lt;/p&gt;


  &lt;a class=&quot;hex&quot; href=&quot;/sponsors#contribute&quot;&gt;Contribute&lt;/a&gt;
&lt;/div&gt;</content>
    </entry>
</feed>
