2026년 10월의 Laravel 뉴스를 한데 모았습니다. 코어는 13.35부터 13.39까지의 네 가지 릴리스(13.37은 Laravel News에 기사 없음)를 다루었습니다. 이번 달에는 보안 관련 공지가 두드러졌습니다. PHP 본체의 긴급 릴리스, Laravel의 token 가드 인증 우회, AI SDK 및 MCP 수정, NativePHP for Mobile 공지 등 총 7건이 집중되었습니다. 대상은 34개 항목입니다. 10월에 공개된 39개 항목 중 5개(영상 연재 소개 2건, 다음 날 공식 기사로 내용이 이관될 예정인 예고 1건, 유료 강좌 공지 1건, 개인 제품 감사 기고 1건)를 제외한 수치입니다.
위에서부터 순서대로 읽는 것이 아니라, 표로 빠르게 훑어보고 관심 있는 부분만 본문이나 출처 링크로 이동할 수 있도록 구성했습니다. 주요 섹션의 맨 위에는 목록표가 배치되어 있으므로, 여기만 보고 끝내도 괜찮습니다.
출처는 모두 Laravel News의 각 기사입니다. 버전 번호나 메서드명은 원문에 맞추었습니다.
-
코어는 4가지 릴리스였습니다. 읽기 복제본(read replica)을 사용하는 앱을 위한 기능이 이어졌습니다. 쓰기 직후의 읽기를 쓰기 측으로 보내는 PreventStaleDatabaseReads와 미들웨어 및 DB::usingWritePdo()가 있습니다.
-
(13.38) 큐 워커(queue worker) 작업 간에 Sticky 상태를 제거하는 Worker::$flushStickyConnections 기능이 추가되었습니다.
-
(13.36) PlanetScale의 행 수 제한을 해제하고 집계하는 DB::olap() 기능이 있습니다.
-
(13.36) 검증(Validation)은 모든 문자열 규칙에 Rule:: 빌더가 추가되었습니다. 쉼표를 포함한 값이 두 개로 분리되지 않게 합니다. 또한, Rule::array()에는 min()이나 max()도 포함되었습니다 (13.39).
-
스케줄러 및 세션 운영 관련 기능입니다. 모든 작업을 단일 서버에서 실행하는 Schedule::alwaysOnOneServer()와 긴 커맨드가 배포 중단 여부를 확인하는 hasBeenInterruptedSince()가 있습니다 (13.35). 만료된 세션을 정리하는 session:garbage-collect도 추가되었습니다 (13.39).
-
올라가기 전에 살펴볼 만한 동작 변경 사항은 3곳입니다. Mercure로의 브로드캐스트가 기본적으로 동기(synchronous) 방식으로 바뀌었고 (13.36), 자식 모델의 #[Connection]이 부모의 $connection보다 우선시되며 (13.38), 테스트에서 Mail::html()이 가짜화되고 assertSeeText('0')가 무시되지 않게 되었습니다 (13.39).
-
보안 관련 내용입니다. PHP 본체에 인증 없이 RCE(Remote Code Execution)로 이어질 수 있는 심각한 취약점 2건(CVSS 9.2)이 발견되었습니다. Laravel의 token 가드에는 인증 우회 문제(9.2, 8월 25일자 12.68.0 및 13.29.0에서 수정 완료), AI SDK 1.0.1 및 MCP 1.0.1, NativePHP for Mobile 4.6.1 등도 다루어졌습니다.
-
주변 환경에서는 Laravel AI SDK 1.1이 Agent Skills를 지원합니다. Inertia는 3.8과 3.9에서 SSR(Server Side Rendering)용 WhenMounted와 백그라운드 탭에서의 폴링 중지 기능을 제공합니다. Filament 5.8은 스키마의 지연 로딩을 구현했습니다. Laravel News의 Eric Barnes가 Matt Stauffer와 함께 PHP 전반을 다루는 PHP News를 개설했습니다.
| 버전 | 핵심 기능 | 사용 시 주의사항 |
|---|---|
| 13.35 | Route::query() / 모델의 defaults() (트레이트로 opt-in) / 가짜 배열 단언(fake array assertion) / queue:work --memory=60% / Schedule::alwaysOnOneServer()와 hasBeenInterruptedSince()
|
| 출처에 동작 변경 명시 없음. --memory에 비율을 전달할 때는, memory_limit이 -1이면 워커가 멈추지 않음 |
| 13.36 | 모든 규칙의 Rule:: 빌더 / DB::olap()와 isVitess() / Worker::$flushStickyConnections / 큐에 넣는 Mailable의 #[DeleteWhenMissingModels]와 #[FailOnTimeout]
|
| Mercure의 브로드캐스트가 기본적으로 동기(synchronous)로 변경됨. 큐로 되돌리려면 MERCURE_ASYNC=true 설정 필요 |
| 13.38 | PreventStaleDatabaseReads 미들웨어 / DB::usingWritePdo() / 리스너, Mailable, 알림 모두에 #[CountCrashesAsExceptions] / lazy()의 메모리 절반 감소
|
| 부모 클래스가 $connection을 가질 때, 자식의 #[Connection]이 무시되던 버그 수정. 자식 쿼리의 목적지가 변경됨 |
| 13.39 | session:garbage-collect / #[Table(key: false)] / JobAttempted의 duration / Rule::array()->min() 계열 / #[WithoutMigrationEvents] / config:cache 같은 캐시 파일을 원자적(atomic)으로 작성
|
| MailFake가 Mail::html()과 Mail::plain()도 포착함. assertSeeText('0')이 무시되지 않게 됨. RefreshDatabase가 열린 트랜잭션을 모두 롤백함 |
13.37은 Laravel News에 릴리스 기사가 없으므로, 여기서는 다루지 않습니다 (13.38의 기사에 “13.37에서 dispatch()와 큐 삽입 리스너의 unique 잠금 해제 수정”이라고 언급되어 있음).
Route::query()
HTTP의 QUERY 메서드를 받는 라우트를 등록합니다. QUERY는 요청 본문(request body)을 가질 수 있는 안전한 메서드로, 쿼리 문자열에 담기지 않는 필터를 가진 검색 엔드포인트에 적합합니다. 13.19에서 Http::query()와 테스트용 query()가 있었으나, 라우트 정의는 Route::match(['QUERY'], ...)로 작성해야 했습니다. QUERY가 라우터의 동사 목록(verb list)에 추가됨에 따라, Route::any()와 Route::redirect()도 QUERY 요청과 일치하게 됩니다.
Route::query('/products/search', SearchProductsController::class);
Laravel 14용으로 병합된 버전과 달리, Registrar 컨트랙트는 변경되지 않았으며, CSRF 보호는 POST와 마찬가지로 QUERY를 검증합니다. web 미들웨어 그룹의 QUERY 라우트에는 토큰 또는 except 등록이 필요합니다.
모델의 defaults()는 $attributes 속성의 메서드 버전입니다. PHP의 프로퍼티 초기값은 상수식으로만 제한되므로, config()나 now(), 피처 플래그로 결정되는 기본값은 작성할 수 없었습니다. 이는 Laravel 14 기능으로서 먼저 기사가 나오고, 13.35에 opt-in 트레이트 형태로 추가되었습니다. 13 버전에서는 HasDefaultAttributes를 사용한 모델에서만 작동합니다.
class Subscription extends Model
{
use HasDefaultAttributes;
...
트레잇(Trait)을 통해 구현한 이유는 이미 defaults()라는 이름의 메서드를 가진 모델이 영향을 받는 것을 방지하기 위해서입니다. defaults()의 값은 $attributes보다 우선하며, 캐스팅이나 뮤테이터를 거치지 않은 원시 값으로 처리됩니다.
페이크(Fake) 어설션이 콜백 대신 속성 배열을 받도록 변경되었습니다. 대상은 Queue, Bus, Event, Notification 네 가지입니다.
Queue::assertPushed(ProcessPodcast::class, [
'podcast' => $podcast,
'user' => $user,
...
비교는 엄격 동등(strict equality)이며, Eloquent 모델 간에만 is()로 비교합니다. 페이크가 외부에서 읽기 때문에 대상은 public 속성으로 한정됩니다.
queue:work --memory가 PHP의 memory_limit 대비 비율을 받습니다. --memory=60%인 경우, memory_limit이 512M일 때 작업(job) 단위로 약 307 MB에서 중지됩니다. 컨테이너 크기에 맞춰 워커 상한선이 조정됩니다. memory_limit이 -1 (CLI에서 흔함)이면 비율이 음수가 되어 메모리 측면에서는 워커가 멈추지 않습니다. 비율을 사용하려면 워커 프로세스에 memory_limit을 설정해야 합니다.
스케줄러의 다중 서버 지원 기능이 두 가지 추가되었습니다. Schedule::alwaysOnOneServer()는 모든 작업에 onOneServer()를 적용합니다. 이전에는 routes/console.php 전체를 Schedule::onOneServer()->group()으로 감싸야 했습니다. 이름 없는 클로저 작업은 락 키(lock key)를 생성할 수 없어 대상에서 제외되며, 모든 서버에서 계속 실행됩니다.
// AppServiceProvider::boot()
Schedule::alwaysOnOneServer();
Schedule::hasBeenInterruptedSince()는 runInBackground()로 실행되는 긴 명령이 schedule:interrupt를 감지할 수 있는 수단입니다. 이전까지 schedule:interrupt는 schedule:run이 초 단위 작업 때문에 수행하는 1분 미만의 루프만 중지시킬 뿐, 백그라운드에서 실행되는 명령어에는 도달하지 못했습니다. 이제 queue:restart와 같이 타임스탬프를 저장하는 방식으로 변경되어, 명령은 시작 시간과 비교하여 배치(batch) 단위로 중지될 수 있습니다.
기타 추가 사항입니다.
- :
response()->markdown() text/markdown 응답을 반환합니다. 요청 측의 wantsMarkdown()과 대응됩니다.
- :
lazy_root_creation local 디스크의 루트 디렉토리를 디스크 구축 시가 아닌 첫 쓰기 시점에 생성하는 옵션입니다.
- 수정 사항 (릴리스 노트 기반): 캐스팅된 기본 키(primary key) 모델에서
chunkById()와 lazyById()가 무한 루프를 일으키는 문제, 알 수 없는 필드(unknown field)로 실패하게 설정했을 때 _token과 _method를 알 수 없는 필드로 간주하는 문제가 있었습니다. 그 외 내용은 릴리스 노트 참조 바랍니다.
문자열로만 작성할 수 있던 모든 유효성 검사(Validation) 규칙에 Rule:: 메서드가 추가되었습니다. required_without, accepted_if, url, uuid, distinct 등이 IDE 자동 완성으로 작성 가능합니다.
$request->validate([
'phone' => [Rule::requiredWithout('email')],
'website' => ['nullable', Rule::url()->protocols(['https'])],
...
Rule::required()처럼 매개변수가 없는 규칙은 그대로 문자열을 반환합니다. 필드 이름이나 값을 가져오는 규칙은 매개변수를 배열 상태로 Validator에 전달하는 객체를 반환합니다. 문자열 형식에서는 쉼표(comma)로 분리되었기 때문에, accepted_if:plan,Team, Annual과 같은 값은 두 개로 나뉘어 일치하지 않았습니다. 빌더(Builder)라면 쉼표를 유지할 수 있습니다. 동일한 PR에서 Rule::date()
에쿼리 메서드에 equals()가 추가되었습니다.
DB::olap()은 PlanetScale과 같은 Vitess 계열 데이터베이스에서 콜백이 실행되는 동안만 워크로드를 OLAP으로 전환합니다. PlanetScale의 기본 OLTP는 1개 쿼리의 결과가 최대 100,000 행까지이며, 이 상한선에서 집계나 내보내기(export) 작업이 실패할 수 있습니다. 읽기 및 쓰기 연결 모두에 워크로드를 설정하고, finally 블록을 사용하여 OLTP로 되돌립니다. Vitess가 아닌 경우 콜백만 호출하면 되므로, 로컬 MySQL에서도 동일한 코드가 작동합니다. 같은 PR에서 MySQL 연결에 isVitess()도 추가되었습니다.
$revenue = DB::olap(fn () => Order::query()
->selectRaw('customer_id, sum(total) as revenue')
->where('created_at', '>=', now()->subYears(3))
...
Worker::$flushStickyConnections는 큐 워커가 작업을 가져오기 전에 sticky 상태를 폐기하는 opt-in 플래그입니다. sticky를 활성화한 읽기/쓰기 분리 연결에서는 쓰기 작업 후의 읽기가 쓰기 서버로 전송됩니다. 웹 요청이라면 응답이 끝날 때 끝나지만, 워커는 1개의 프로세스에서 수천 개의 작업을 처리하므로, 하나의 작업이 데이터를 쓰면 이후 모든 작업의 읽기가 계속해서 쓰기 서버를 향하게 됩니다.
Worker::$flushStickyConnections = true;
이는 기본적으로 비활성화되어 있는데, 같은 워커의 이전 작업이 작성한 데이터를 읽는 것을 전제로 하는 작업이 있을 수 있기 때문입니다.
Mailable을 큐에 넣을 때 #[DeleteWhenMissingModels]와 #[FailOnTimeout] (및 해당 속성)을 무시하던 문제가 수정되었습니다. 주문 삭제 후 발송되는 이메일 작업은 더 이상 ModelNotFoundException으로 실패하지 않습니다. Markdown 메일에서는 링크의 텍스트에 포함된 사용자 입력에 역슬래시로 닫는 괄호를 이스케이프하여 링크 대상을 변경할 수 있는 문제가 수정되었습니다.
주의 사항: Mercure로의 브로드캐스트가 큐에 넣지 않고 즉시 전송되도록 변경되었습니다. Mercure 연결만을 대상으로 하는 이벤트는 ShouldBroadcastNow와 동일하게 처리되며, 다른 연결을 대상으로 하는 이벤트는 이전처럼 큐에 들어갑니다. 이전 동작으로 되돌리려면 MERCURE_ASYNC=true를 설정해야 합니다. 비동기로 설정하면 워커가 HTTP로 발행하므로 Mercure의 url이 필수입니다.
PreventStaleDatabaseReads는 읽기 레플리카(read replica)를 사용하는 애플리케이션을 위한 opt-in 미들웨어입니다. 요청이 기본 연결에 쓰기를 수행하면 세션에 타임스탬프를 저장합니다. 해당 사용자의 다음 2초간의 읽기는 쓰기 서버로 전송되며, 시간이 지나면 레플리카로 돌아갑니다. sticky는 같은 요청 내에서만 유효하므로, PUT 이후 GET으로 리다이렉트하는 폼에서는 레플리카 지연으로 인해 오래된 데이터가 보이는 경우가 있었습니다.
->withMiddleware(function (Middleware $middleware) {
$middleware->web(append: [
PreventStaleDatabaseReads::class,
...
추적할 초는 PreventStaleDatabaseReads::for(10)와 같이 지정할 수 있습니다. 세션과 기본 연결만 추적합니다. 데이터를 작성한 본인의 읽기만 대상이므로, 다른 사용자는 레플리카의 오래된 데이터를 읽을 수 있습니다.
DB::usingWritePdo()는 콜백 내부의 모든 읽기를 쓰기 연결로 보냅니다. 기존의 onWriteConnection()은 시작 쿼리에만 영향을 미쳤고, 결과에서 읽은 관계(relation)는 레플리카를 읽었습니다. 콜백이 예외를 발생시켜도 설정은 원래대로 복구됩니다.
$posts = DB::usingWritePdo(fn () => User::query()
->where('email', $email)
->first()
...
13.34의 #[CountCrashesAsExceptions] 기능은 큐에 투입되는 리스너, Mailable, 알림에서도 작동하도록 개선되었습니다. 이전까지는 Job만 대상이었으며, $tries가 0인 리스너의 경우 워커가 메모리 부족으로 다운되어도 maxExceptions에 카운트되지 않고 무한 재시도되고 있었습니다.
lazy()와 lazyById()는 다음 청크를 가져오기 전에 이전 청크를 해제합니다. 이전에는 2개의 청크가 동시에 메모리에 올라와 피크 사용량이 필요한 양의 약 2배에 달했습니다. chunk()와 chunkById()는 원래부터 이러한 동작을 가지고 있었습니다.
그 외 추가된 내용:
unique Job: Schedule::job()으로 투입되는 unique Job이 큐 push에 실패해도 잠금을 계속 잡고 있는 문제가 수정되었습니다. uniqueFor가 기본값인 0일 경우 잠금이 풀리지 않아, 큐가 돌아와도 이후 실행 전체가 건너뛰어지던 현상이 있었습니다. 또한, ShouldBeUnique한 Broadcast Event도 스킵 시점에 UniqueJobSkipped을 발생시킵니다.
수정 사항 (릴리스 노트 기반): 머신 간에 캐싱된 라우트에서 Health Route가 작동하지 않던 문제, 날짜 외의 값으로 날짜 비교 규칙이 TypeError를 발생시키던 문제가 수정되었습니다. 그 외 내용은 릴리스 노트를 참고해 주세요.
업그레이드 시 주의사항: 부모 클래스가 $connection 속성을 가질 경우, 자식 모델의 #[Connection] 속성이 무시되던 문제가 있었습니다. 자식의 쿼리는 오류 없이 부모의 연결(connection)로 흘러갔습니다. 수정 후에는 자식의 속성이 우선권을 가지므로, #[Connection('reporting')]을 붙인 자식 모델의 쿼리는 reporting 연결로 향합니다. 두 가지를 모두 작성한 모델이 있다면, 어느 연결로 동작했는지 확인한 후에 업그레이드하는 것이 좋습니다.
session:garbage-collect는 세션 드라이버의 가비지 컬렉션을 실행하는 Artisan 명령어입니다. Laravel은 config/session.php의 lottery 설정에 따라 무작위 요청(random request) 속에서 만료된 세션을 삭제하고 있었습니다. 이 명령어를 스케줄에 등록하고, lottery를 [0, 100]으로 설정하면 Web Request가 청소를 기다릴 필요가 없어집니다.
Schedule::command('session:garbage-collect')->hourly();
#[Table(name: 'activity_log', key: false)]를 사용하여 모델의 기본 키(Primary Key)를 비활성화할 수 있게 되었습니다. 이전에는 key에 null을 전달하면 $primaryKey 속성(기본값은 id)으로 폴백했기 때문에, 이 속성을 명시해야 했습니다. 후속 PR에서 이 모델은 non-incrementing으로 처리되어, create()가 insert 후에 예외를 던지지 않게 되었습니다.
JobAttempted 이벤트에 duration이 추가되었습니다. 이전에는 JobProcessed에만 존재했기 때문에, 실패한 Job이나 재시도를 위해 방출된 Job의 소요 시간을 측정할 수 없었습니다. 단위는 밀리초(milliseconds)입니다. dispatchSync()로 동작하는 sync 큐에도 동일한 값이 포함됩니다.
Event::listen(function (JobAttempted $event) {
if (! $event->successful()) {
Log::warning('Job failed', ['duration_ms' => $event->duration]);
...
}
Rule::array()에 min(), max(), between(), exactly()가 추가되어 Rule::string()과 통일되었습니다. [Rule::required(), Rule::array()->min(1)->max(10)]와 같이 작성할 수 있으며, Rule::array(['a', 'b'])->min(1)는 array:a,b|min:1로 변환됩니다.
테스트 관련 수정 사항들이 모여서 적용되었습니다.
⚠️ [IMG:N] 형식 토큰은 이미지 placeholder 입니다. 번역하지 말고 원래 위치에 그대로 유지하세요.
:#[WithoutMigrationEvents]
테스트 중에 실행되는 마이그레이션 쿼리를 DB::listen()과 expectsDatabaseQueryCount()에서 제외합니다. -
:다른 Job은 가짜(fake) 상태로 유지하면서, after-response Job을 실행시킵니다. BusFake::withoutDispatchingAfterResponses()
프로세스 가짜(Process fake): 종료 코드와 예외의 단축형이 start()와 pool()에서도 사용 가능합니다.
관계(Relation) 생성 관련 기능도 수정되었습니다. BelongsToMany에 forceCreate()와 forceCreateQuietly()가 추가되었습니다. 이전에는 Query Builder를 통해 모델이 생성되기는 했으나 attach되지 않았습니다. restoreOrCreate()와 createOrRestore() 역시 관계를 거치도록 변경되었으며, has-many에서 외부 키가 들어가지 않거나 belongs-to-many에서 다른 모델을 복원하는 문제가 수정되었습니다. HasManyThrough와 HasOneThrough도 대상입니다.
config:cache, route:cache, event:cache가 임시 파일에 작성된 후 이름이 변경됩니다(rename). 명령어 실행 도중에 시작된 요청이 빈 캐시 파일을 읽고, opcache.validate_timestamps=0인 경우 PHP-FPM을 재시작할 때까지 모든 요청에서 오류가 발생하던 문제가 있었습니다.
업그레이드 시 주의사항: 테스트 동작 방식이 3가지 변경됩니다. Mail::html()과 Mail::plain()이 MailFake으로 포착됩니다(이전에는 테스트 중에 실제 메일이 전송되었습니다). assertSeeText('0')가 응답을 확인하지 않고 통과하던 문제가 수정되었습니다. RefreshDatabase는 각 테스트 후에 열려 있는 트랜잭션을 모두 롤백하므로, 하나의 테스트가 열어둔 트랜잭션이 후속 테스트에 영향을 주지 않게 됩니다. 통과하던 테스트가 실패하기 시작하면 이 세 가지를 의심해 보세요.
핵심 기능 중 8가지에 대해서는 Laravel News 측에 개별 설명 기사가 있습니다. 구현할 때 이곳을 참고하는 것이 빠릅니다.
| 대상 | 설명 기사 | 내용 |
|---|
| 13.35 | 모델의 defaults() | $attributes와 인자 중 어느 것이 승리하는지, 원시 값(캐스팅을 거치지 않음), 가져온 행마다 실행되는 점, 기존 defaults() 메서드와 충돌하지 않는지 확인 |
| 13.35 | 가짜 배열 어설션 | 엄격 동등 비교와 is(), Carbon과 같은 값 객체는 콜백이 필요하며, 중첩된 키는 지정할 수 없음 |
| 13.35 | 다중 서버 스케줄러 | 이름 없는 클로저는 대상에서 제외되며, Schedule::useCache()로 공유 저장소를 지정하고, hasBeenInterruptedSince()를 사용하는 명령어 구현 예시와 배포 스크립트 |
| 13.36 | Rule 빌더 | 매개변수 없음, 필드나 값을 가져옴, 옵션이 있는 세 가지 분류 전체 목록, ParameterizedRule과 쉼표 처리 |
| ... | | |
| PHP 본체, Laravel 본체, 공식 패키지, NativePHP 등 계층이 다른 공지가 같은 달에 나열되었습니다. 영향 여부를 확인할 순서대로 표로 정리했습니다. | | |
| 대상 | 심각도 | 영향을 받는 조건 | 수정 버전 |
|---|
| PHP 본체의 RCE 2건 | Critical (CVSS 4.0 기준 9.2) | Web 요청을 수신하는 모든 구성(PHP-FPM, mod_php, php-cgi, FrankenPHP, LiteSpeed) | 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 |
Laravel의 token 가드 인증 우회 | Critical (9.2) | config/auth.php에 driver => 'token' 가드가 있고 MySQL 또는 MariaDB를 사용하는 경우 | 12.68.0 / 13.29.0 (8월 25일 공개) |
| 동일 기사: JSON:API 리소스 데이터 파괴 | Medium (CVSS 3.1 기준 6.5) | 12.45에서 도입된 JSON:API 리소스를 사용하는 경우 | 12.68.0 / 13.27.0 |
| Laravel AI SDK의 SSRF | Moderate (5.3) | 1.0.0 버전의 Vercel 또는 AG-UI 어댑터를 신뢰할 수 없는 클라이언트에게 공개하는 경우 | 1.0.1 |
| 동일 기사: Laravel MCP의 OAuth 리다이렉트 검증 | Low | 0.9.6 미만이거나 1.0.0 버전이며, 설정에 따라 달라지는 경우 | 0.9.6 / 1.0.1 |
| NativePHP for Mobile의 7건 | High 5건 (7.4~8.1), Moderate 2건 | nativephp/mobile 전체 시리즈(1.x 및 2.x는 EOL로 수정 없음). 대부분은 Web View에서 JavaScript를 실행할 수 있는 공격자를 전제로 함 | 4.6.1 / 3.3.11, nativephp/mobile-file 1.0.3 |
10월 21일에 PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35가 출시되었습니다. 수정된 취약점은 두 건 모두 인증되지 않은 원격 코드 실행(Remote Code Execution)으로 이어지는 Critical 등급입니다 (CVSS 4.0 기준 9.2). PHP 팀은 완벽한 완화책이 없다고 밝히며 즉각적인 업데이트를 요청하고 있습니다. 전날 '익일 14:00 UTC에 배포'라는 예고가 있었으며, Forge와 Cloud도 동시에 대응을 공지했습니다.
CVE-2026-109618 (OOM으로 인한 손상): 메모리 부족(Out Of Memory) 처리 과정에서 요청의 내부 데이터가 부분적으로만 초기화된 시점에 PHP가 중단되고, 후처리 과정이 해당 부정확한 데이터를 올바른 것으로 간주하는 취약점.
- CVE-2026-109619 (잔존 글로벌 상태): 요청이 가진 내부 상태가 메모리 해제 후에도 남아있어, 동일 워커의 다음 요청이 초기화되기 전에 이를 사용하는 취약점.
mod_php가 가장 위험하며, 애플리케이션 코드가 실행되기 전에 인증되지 않은 요청으로부터 발동될 수 있다는 시연 사례가 있습니다. PHP 8.1 이전 버전은 PHP 프로젝트로부터 업데이트가 없지만, 심각도를 고려하여 7.4, 8.0, 8.1용 최소한의 소스 백포트가 브랜치로 공개되었습니다. 이는 자원봉사자들이 유지하는 rpms.remirepo.net입니다.
해당 레포지토리는 당일에 업데이트되지 않으므로, 배포판 패키지 또는 소스 빌드로 전환할 것을 안내하고 있습니다.