Bringing post-quantum cryptography to geographically fenced key management

Post Syndicated from Chetan Agrawal original https://blog.cloudflare.com/post-quantum-geo-key-manager/

Today, Cloudflare is launching a post-quantum geographically restricted key manager in support of our Data Localization Suite (DLS) in closed beta. This new PQ GeoKey Manager is a cornerstone of Cloudflare’s data sovereignty solutions, making sure that a customer's decryption keys are only accessible in their chosen geography. GeoKey Manager implements this by wrapping each decryption key such that it can only be decrypted by Cloudflare servers that are located in the allowed geography.

While general availability (GA) is planned for Q1 2027, today’s launch is an important milestone on our journey to support our customers’ data sovereignty goals while also migrating all Cloudflare products to post-quantum (PQ) cryptography.

Governments, financial institutions, healthcare providers, and defense organizations process highly sensitive data that can remain sensitive for years or decades after it is produced. Encryption is often required to protect this data. When classical, public-key encryption is used, adversaries do not immediately need a quantum computer today to put that data at risk: they can store the ciphertext and retain them until quantum computers can break the public key cryptography protecting it — an attack strategy known as harvest now, decrypt later.

For organizations with geographic requirements, resisting that threat is only half the challenge. At Cloudflare's scale, high availability requires replicating customer data across many servers across our global network. However, many data sovereignty regulations require that certain types of data be processed only within a given geographical region. We must therefore ensure the data is end-to-end encrypted such that only servers within the region have access to the plaintext. In this post, we describe the system that makes this work.

The evolution of GeoKey Manager

Cloudflare pioneered the concept of geo-restricted transport layer security (TLS) keys back in 2017 with GeoKey Manager. This gave customers control over the locations where their private TLS keys could be unwrapped on Cloudflare’s anycast network to provide stronger technical guarantees of which region their requests are decrypted into. For instance, a customer could choose to only unwrap their private keys in India. So instead of allowing decryption across Cloudflare’s entire global network, GeoKey Manager makes sure TLS signing for each customer request happens in our India network.

GeoKey Manager evolved again in 2022 with ciphertext policy attribute based encryption (ABE). Instead of tying encrypted keys to a fixed set of data centers, ABE expressed geographic requirements using attributes such as country or region, like “region = European Union” or “region = Canada + United States + Mexico”. Newly authorized servers could receive matching decryption capabilities without rewrapping every customer key.

That flexibility created a challenge and opportunity for the post-quantum transition. No production-ready post-quantum ABE scheme is available today, and customers do not need a large number of regions. A simpler design meets the requirement and is easier to maintain and operate. Cloudflare therefore uses hybrid ML-KEM-768 and X25519 protection with two kinds of keys, out of which ML-KEM-768 is a NIST standard that also opens doors to highly sensitive customers. A regional root key is a symmetric secret tied to one region, and an application-specific key pair is derived from it for a single service, such as Gateway or Tunnel. This protects private-key material against harvest now, decrypt later while preserving regional key-use boundaries.

Global ciphertext, regional key unwrapping

In its new form, GeoKey Manager is the key foundation for Cloudflare’s data sovereignty solutions. It controls which region protected decryption keys can be used from and when. Separate workstreams determine where tunnels terminate, where traffic is inspected, how it is routed, and where plaintext processing occurs. But all of them depend on the region where a customer’s private key can be unwrapped, because TLS traffic can only be decrypted where that key is available.

During initialization, the edge key service (the component on each Cloudflare edge server that unwraps customer private keys and uses them to serve requests) verifies that it has loaded every regional root key required by its configuration. If a configured key is missing or malformed, the service does not start. After initialization, an individual request also fails closed (Cloudflare rejects it rather than risk unwrapping a key out of region) if its metadata identifies a regional root key that is not locally available. If a request for Germany was somehow trying to decrypt in Spain or France it would fail, since neither Spain nor France have the regional root key for Germany. This guarantees that a regional root key never leaves its region, no matter what.

Cloudflare needs to maintain high performance while keeping our customers’ regionalized data secure at scale. This is where the next version of GeoKey Manager comes in. We are enabling fast performance while logically separating our network by using post-quantum cryptography to restrict where customers’ private keys are unwrapped. Most of our regions will be available for customers to regionalize their workflow, and there may be product specific caveats. Customers select a region and Cloudflare manages everything else needed to unwrap their private keys within the region’s boundary.

How GeoKey Manager ensures that keys are only available in a region

GeoKey Manager controls where wrapped private keys can be unwrapped and used on the data plane. It does not control where requests are forwarded or routed (that’s Regional Services), where tunnels terminate, or where traffic inspection happens (also Regional Services).

GeoKey Manager separates globally distributed wrapped private keys from the regional root key required to unwrap it. Quicksilver, our global configuration distribution system, distributes wrapped private keys and its metadata across our network. It does not distribute regional root keys; that happens through a separate provisioning service that stores regional root keys and delivers them only to edge servers authorized for each region. Regional root keys follow a separate, controlled path. On the data plane, a node’s regional configuration, which region a node belongs to, determines which nodes can receive which regional root keys.

Defining key hierarchy and application-specific keys

Every wrapped customer private key carries metadata identifying its service context, regional boundary, and epoch.

The service context is the Cloudflare service that uses the key, such as Tunnel or Gateway. The regional boundary is the approved set of Cloudflare data centers where the key may be unwrapped and used, such as data centers in Germany or the European Union. The epoch identifies which generation of the regional root key the key belongs to; each rotation creates a new epoch. 

For example, Acme Co. might have one key for Tunnel in Germany (acme0001) and another for Gateway in Germany (acme0002). Road Runner Inc. might have one key for Tunnel in Germany (runner0001) and another for Gateway in the European Union (runner0002).

Keys with the same service context, regional boundary, and epoch use the same application-specific key pair. Therefore, compromising the Tunnel-Germany application-specific private key could expose both acme0001 and runner0001, but not the Gateway keys. Compromising the Germany regional root key could affect every application-specific key derived from that root for the same epoch, including acme0001, acme0002, and runner0001.

In the current architecture, the application-specific key pair is asymmetric. The public component wraps the customer's private key material, while the private component is required to unwrap it. The resulting wrapped private key is distributed with its service context (Access, Gateway, Tunnel, Cloudflare One client), region, and epoch.

Provisioning regional root keys

When Cloudflare/Admin configures a region for a CF1 use case, key management service (which also derives application-specific key pairs and wraps customer private keys) creates a regional root key and associates it with a regional boundary and epoch and sends it to provisioning service for storage and distribution which under the hood uses Vault, which is managed by us on-premises.

Authorizing edge servers for a region

Before an edge server can receive a regional root key, provisioning service evaluates three inputs:

  1. Trusted Platform Module (TPM) proves that the server possesses a registered hardware identity
  2. Zinc, Cloudflare's server inventory system, maps that identity to a data center and location 
  3. Provisioning service determines which regional root keys the server may access

Zinc updates its membership records for each edge server. This asynchronous process adds new servers as the network grows and removes servers when they are decommissioned. As Cloudflare performs maintenance on data centers in Germany, the definition of which data centers belong in Germany changes in Zinc. That definition is swiftly propagated through our network with Quicksilver so that our edge is up to date. The reverse also works. As we add capacity to our network, the definition of Germany, or any other region, is updated in Zinc and that is also swiftly propagated through our network with Quicksilver.

Zinc also associates a registered hardware identity with a server and physical location, which supports FIPS 140-3 compliance. TPM-backed identity, server inventory data, and regional configurations determine which region an edge server belongs to and what regional root keys it can access.

Each edge server calls the control plane’s provisioning service, and provides its registered hardware identity. After verifying the server’s hardware identity and regional membership, the provisioning service issues a token that permits the server to retrieve only the regional root keys authorized for its location. Each edge server receives its token and uses it to fetch the regional root keys.

Authorized edge servers load regional root keys into the kernel keyring rather than persisting them on disk. Process level access controls limit which services can use them. Because this memory is volatile, a machine restart removes the keys and the server must authenticate and provision them again. This adds operational complexity in exchange for reducing persistent key material which could be an attack vector for adversaries.

Wrapping private keys for global distribution

When the key-management service receives a customer's private key material with a service context and regional boundary, it will use the request’s regional boundary to get the regional root key and its latest configured epoch. It will then derive the corresponding asymmetric application key pair and use its public component to wrap the private key. The result is a wrapped private key and its metadata.

Quicksilver will then distribute the wrapped private key and metadata across our network. Since the wrapped key requires the specified region to decrypt, global wrapped key distribution does not grant edge servers global access to the private key because unwrapping still requires the corresponding regional root key and service context.

Unwrapping using application-specific keys on the data plane

Why we chose this cryptographic design

Symmetric roots with asymmetric key wrapping

Regional root keys are 256-bit symmetric secrets. GeoKey Manager derives application-specific keys from each regional root key. For the current Cloudflare One path, the control plane’s key management service derives an application-specific Hybrid Public Key Encryption (HPKE) key pair.

HPKE with hybrid post-quantum KEM

The Cloudflare One path uses HPKE, as defined in RFC 9180. Its key-encapsulation mechanism (KEM) combines ML-KEM-768 with X25519, while HKDF-SHA-256 provides key derivation and AES-256-GCM provides authenticated encryption. Combining post-quantum and classical components preserves confidentiality as long as at least one component remains secure.

Designing for rotation 

The validated design supports two types of key rotation: soft rotation and hard rotation.

A soft rotation creates a new epoch for the regional root key while retaining controlled access to a limited number of previous regional root-key epochs — let’s say one previous generation, as an example. The customer’s new private-key material is wrapped using the latest epoch, while older wrapped private keys are still usable during the transition. This is a similar concept to when a credit card company allows you to use a previous version of your credit card for recurring payments from an authorized retailer. In this case, the number of epochs we support determine how many generations of previously wrapped private keys — credit cards — are usable. This allows customers to preserve their service uptime while they transition.

A hard rotation instead rewraps affected customers’ wrapped private keys under a replacement epoch so access to the previous epoch can be removed. In this case, it would be like the credit card company not allowing you to use the previous credit card for a transaction under any circumstances.

Security and availability tradeoffs

Failing closed is a very intentional design choice. Failing open would mean unwrapping a customer’s private key outside its allowed region rather than rejecting the request. We never do that: if any required check fails (service context, region, epoch, etc.), the request is rejected. At startup, each edge’s key service loads every configured regional root key from its Linux kernel keyring. Missing or malformed root keys prevent the edge key service from initializing. Once running, the edge key service uses in-memory copies so that it can’t be tampered with, preventing out of region or cross-region unwrapping. In practice, an edge server serves requests for a region only once its configuration and key provisioning are complete.

The trust boundary (all services that can access the regional root key) includes the key-management service, the provisioning service, and authorized edge key services because each can access regional root keys. The key-management service uses them to derive application-specific keys, the provisioning service stores and distributes them, and edge key services use locally authorized copies of them. Quicksilver remains outside this boundary because it receives only wrapped private keys and associated metadata.

Operating GeoKey Manager

Cloudflare’s network is constantly changing. As servers enter or leave service, Cloudflare’s fleet inventory updates regional membership. This means the list of data centers that make up a region like Spain is not static. GeoKey Manager’s provisioning layer refreshes that membership several times each day, granting or removing access to regional root keys as the network changes. This process is separate from key rotation and requires no customer action.

When regional membership changes, the provisioning service immediately synchronizes the server’s Linux kernel keyring with the latest authorized regional root keys. The edge key service caches these keys in process memory until it restarts or the cache expires. It then reloads the current authorized set from the kernel keyring.

What’s next: Cloudflare One integration and CDN

GeoKey Manager is the basis for an improved Regional Services offering for Cloudflare One; these new capabilities will be announced in a few months.

Older versions of GeoKey Manager already provide geographic controls for private keys associated with CDN certificates. We are developing a separate integration that will bring this new post-quantum GeoKey Manager described here to that existing CDN capability. We will share testing and transition details when that work is ready.

Getting started

If you are a current DLS customer who is regionalizing CDN traffic, you can register intent to test this feature before it’s generally available for CDN traffic here.

Thank you to everyone who made this product a reality. It was a huge effort across the Data Localization Suite, Cloudflare One, and Cloudflare Research teams.

Ще гласувам с #4 за Гюров и Кандев

Post Syndicated from Боян Юруков original https://yurukov.net/blog/2026/gurov/

В неделя ще гласувам за Гюров и Кандев.

Не защото не искам някой друг, а защото искам точно те двамата да са президент и вицепрезидент. Знам какви са правомощията им, каква е пряката и непряката роля на поста. Вярвам, че са правилните хора за тези позиции и ще върнат президентската институция от политически инструмент за заграбване на власт в нещо, което всъщност работи за България. Вярвам, че са хора с план, а не със схема и са го показали през кариерата си.

Затова ще гласувам с номер 4.

Седмият президент и сделките за властта

Post Syndicated from Емилия Милчева original https://www.toest.bg/sedmiyat-prezident-i-sdelkite-za-vlastta/

Седмият президент и сделките за властта

„Не съм гуру, не съм водач“, заявява Жан-Люк Меланшон през 2017 г., когато го притискат да каже за кого да гласуват близо седемте милиона французи, подкрепили кандидатурата му за президент. Самият той, останал на четвърто място на първия тур тогава, гласува на балотажа между Еманюел Макрон и Марин Льо Пен, но не разкри избора си. Защото след президентските избори идваха парламентарни, а той нямаше намерение да подарява политическото си влияние на друг кандидат.

Девет години по-късно Меланшон отново се бори за президентския пост. Социолозите вече разглеждат възможността самият той да се изправи срещу Льо Пен на балотаж идната пролет и тогава ще му е нужна помощ. 

Кой всъщност печели повече от подкрепата на балотажа – кандидатът, който я получава, или политикът, който я дава? 

В България този въпрос ще тежи особено много на 1 ноември, когато се очаква да бъде избран седмият президент на републиката. 

Истинската битка за властта обаче е отвъд Президентството. Изборите за държавен глава ще покажат дали България върви към ново политическо противопоставяне, или ще се затвърди прехвърлянето на влияние и ресурси от старите към новите управляващи – и още повече силата на Румен Радев.

Залогът

Няма избори, за които да не се сключват политически сделки, и предстоящите не правят изключение. Две от парламентарно представените формации нямат свои кандидати за президент – ГЕРБ с над 430 хиляди гласа зад гърба си на последните парламентарни избори през април т.г. и ДПС с над 230 хиляди. Техните избиратели или голяма част от тях все пак ще участват в предстоящия вот, а социологическите агенции ще покажат как се е разпределил той. 

Според Димитър Ганев от агенция „Тренд“ на президентските избори ще гласуват едва 150–200 хиляди избиратели на ГЕРБ и не повече от 60–70 хиляди на ДПС. Той свързва неучастието на ГЕРБ със състоянието на партийната организация и риска от демобилизация преди местните избори през 2027 г. 

В студиото на „24 часа“ Геновева Петрова от „Алфа Рисърч“ посочи, че по техни данни на старта на кампанията половината от избирателите на ГЕРБ и половината от тези на ДПС няма да гласуват на първия тур. А след последните акции срещу знакови кметове на ДПС отливът може да е и по-голям.

За лидерите на ГЕРБ Бойко Борисов и на ДПС Делян Пеевски залогът е да съхранят влиянието си – поне частично, за Румен Радев – да го разшири, а за „Продължаваме промяната“ и „Демократична България“ – да останат силна опозиция и политически фактор.

Битката за властта обаче продължава след президентския балотаж. 

Предстоят местните избори през 2027 г., а също и изборът на нов състав на Висшия съдебен съвет (ВСС), който трябва да приключи три седмици след балотажа – на 21 ноември. Новият ВСС ще трябва да избере главен прокурор и председател на Върховния административен съд (ВАС) – два ключови поста, от които зависи бъдещото разпределение на влияние в съдебната власт.

Президентът има роля в назначаването на главния прокурор и председателите на ВАС и на Върховния касационен съд, които утвърждава с указ – включително правото да откаже първото предложение на ВСС. Законът обаче му дава право само на еднократно вето, не и на окончателно блокиране на кандидатура чрез втори отказ. Затова пък не е длъжен да подпише указа за назначението в определен срок.

Докато партиите пресмятат цената на подкрепата си за президент, 

Пеевски получи сигнал, че собствените му позиции вече не са неприкосновени. 

Дни преди първия тур на президентските избори трима кметове, двама от които са и зам.-председатели на ДПС, станаха обект на полицейски акции. Доскоро подобни действия срещу хора от най-близкото политическо обкръжение на олигарха изглеждаха немислими. 

В рамките на три дни кметовете на Сунгурларе Димитър Гавазов и на Белица Радослав Ревански бяха задържани и обвинени в престъпен сговор за търговия с влияние. Полицейските действия стигнаха и до Кърджали, където за разпит беше отведен кметът Ерол Мюмюн, но по-късно бе пуснат на свобода. Оставка пък подаде друг кмет, свързан с Пеевски – Николай Рашков, избран с листата на неизвестната ПП „Пряка демокрация“. 

Арестите и разпитите на високопоставени лица в ДПС променят картината за първия тур – но и за балотажа. Пеевски трябва да реши кого да подкрепи в момент, когато самият той е изправен пред въпроса колко власт и влияние му остават. А политическата подкрепа струва толкова, колкото тежи този, който я предлага.

Съвпадението на акциите с последните дни на президентската кампания няма как да бъде приписано на приключени точно в този момент разследвания.

Още по-показателно е, че самият премиер Румен Радев побърза да направи политически прочит. От Министерския съвет той обяви, че Борисов и Пеевски губят контрол върху финансовите потоци, а техните „лейтенанти“ вече не определят обществените поръчки. Радев посочи задържането на кмета на Сунгурларе като пример и заяви, че досега усилията на МВР и ДАНС са се проваляли в прокуратурата, но вече се намират прокурори, готови да действат.

Така министър-председателят свърза конкретно наказателно разследване с преразпределението на политическото и икономическото влияние. Прокуратурата започва ли да се освобождава от политическите зависимости, или се обръща по посоката, в която духа вятърът на прогреса? Първото би било добра новина за правовата държава. Второто би означавало, че зависимостите остават, но се сменят онези, които се възползват от тях.

Злоупотребите с обществени поръчки не са единствено в общини, контролирани от ДПС. Корупцията в България не е етнически оцветена, нито е запазена територия на една партия. А и къде е Борисов, след като няма свързан с ГЕРБ управник в последните акции, макар че партията е монополист в местната власт? 

Политическите сметки изпускат обаче непредвиденото. 

Три дни преди първия тур служител на Националната служба за охрана (НСО) блъсна на земята журналистката Соня Колтуклиева, след като тя отвори вратата на служебния автомобил на председателката на парламента Михаела Доцова. Лимузината потегли и никой не помогна на Колтуклиева, която остана да лежи по гръб на тротоара. Видеото обиколи социалните мрежи и предизвика лавина от коментари и искания за оставка на Доцова от опозицията и от граждани. 

Инцидентът пред централата на „Прогресивна България“ предизвика бърза реакция от президентката Илияна Йотова, която осъди действията на охранителя като „недопустима и прекомерна реакция“. Тя поиска и оставката на шефа на НСО генерал-майор Емил Тонев, а самата служба започна проверка и сезира Военната прокуратура. Гардът Мартин Варадинов е арестуван, след като е отишъл доброволно във Военната прокуратура да даде показания. 

Този случай поставя неудобни за управляващите въпроси не само за демонстрацията на сила, но и за това 

как председател на парламента може да не забележи насилието, извършено от собствената му охрана,

и да се извини едва след като видеото предизвика обществено възмущение. Доцова се оправда, че не е видяла какво е извършил гардът. Реалността я опровергава – и това се вижда от видеото. В парламента ГЕРБ събра подписи за свикване на извънредно заседание за нейната оставка.

Този случай ще окаже влияние върху резултатите от първия тур, но никой не се наема да прогнозира с колко. На финала на кампанията последни данни показват, че дистанцията се скъсява, макар разликата да остава двуцифрена. Преднината на Йотова пред Гюров спадна до под 13%, установи проучване на „Алфа Рисърч“, направено преди инцидента със Соня Колтуклиева.

Борисов и гласовете, които не притежава

Отказът на ГЕРБ да издигне собствена кандидатпрезидентска двойка спести на Борисов риска от поредна изборна загуба. Но го постави пред друг риск – да се окаже, че вече не може да разполага с гласовете на собствените си избиратели така, както е свикнал. Дори да обяви подкрепа за един от двамата претенденти на балотажа, няма гаранция, че избирателите на ГЕРБ ще го последват.

Проучването на „Алфа Рисърч“ от началото на октомври не само показа, че близо половината симпатизанти на ГЕРБ няма да гласуват. От останалите близо 30% предпочитат Андрей Гюров, а двойно по-малко – Илияна Йотова. При избирателите на ДПС съотношението е в полза на Йотова.

Борисов вече обяви Йотова за свой идеологически противник, но отказа да даде непоискана подкрепа на Гюров. Самият Гюров очаква подкрепа от симпатизанти на ГЕРБ, но не иска да я договаря с партийната централа. Така Борисов се оказва в необичайно положение: иска подкрепата му да бъде поискана, но не е ясно с колко гласа може да „тежи“ в подобни преговори. 

Политическите сметки на Пеевски

Председателят на ДПС каза, че няма да подкрепя кандидат на първия тур, а за балотажа ще решава впоследствие. Междувременно атакува правителството на Румен Радев с обвинения в корупция и неспособност да управлява, но намери повод да похвали Илияна Йотова за свикването на Консултативния съвет за национална сигурност. 

Възможно е поведението му да е не само предизборно позициониране, а опит да запази пространство за договаряне с новата власт. Тогава предметът на евентуалната сделка няма да бъдат единствено гласовете за Йотова, а и кръгът на влияние на ДПС – особено в общините, където местните избори през 2027 г. ще покажат дали партията успява да запази позициите си. Те обаче очевидно ерозират, а свързаните с предишния кръг на Доган с нетърпение очакват реабилитацията си. Техни кадри бяха назначени в няколко министерства. 

Останалите

След първия тур решения ще трябва да вземат не само Борисов и Пеевски, но и останалите кандидати, които няма да стигнат до балотажа. Гласовете за тях няма как да бъдат автоматично прибавени към Йотова или Гюров.

Най-голям е залогът за лидера на „Възраждане“ Костадин Костадинов. Според последни проучвания председателят на „Възраждане“, чийто кандидат за вицепрезидент е евродепутатът Петър Волгин, събира 9–11% подкрепа. Другите двама партийни лидери и също кандидати за президентския пост – Радостин Василев (МЕЧ) и Ивелин Михайлов („Величие“), остават значително след него.

За тези формации президентските избори са възможност да измерят собствената си подкрепа преди местния вот догодина.

Появата на „Прогресивна България“ изцеди „Възраждане“, но несъмнено част от избирателите на Костадинов ще подкрепят Йотова. Василев и Михайлов са хлъзгави – от една страна, те градят политическата си идентичност върху противопоставянето на статуквото и модела Пеевски–Борисов, а от друга, споделят немалко от евроскептичните и благосклонни към Москва позиции на „Възраждане“, без да афишират открито проруска идентичност. 

Лидерите на МЕЧ и на „Величие“ избягват ясното назоваване на Русия като агресор във войната срещу Украйна, оспорват европейската политика по отношение на Москва и представят дистанцирането от общите позиции на ЕС като защита на българския национален интерес. Така те си оставят пространство да привличат избиратели от различни политически лагери, без да поемат ясни ангажименти към нито един от тях.

За Румен Радев президентските избори са възможност да затвърди политическото си влияние и извън изпълнителната и законодателната власт. Победа на Йотова би означавала политически близък държавен глава, с когото управляващото мнозинство комфортно ще съжителства през следващите години.

За Андрей Гюров и подкрепящите го ПП и ДБ балотажът е изпитание с двоен залог.

Те трябва да привлекат избиратели отвъд собствената си политическа общност, без да превръщат подкрепата на Борисов или Пеевски в бъдещо задължение. Защото има разлика между гласовете на симпатизантите на ГЕРБ и ДПС и политическа сделка с техните лидери. Първите могат да бъдат спечелени, за втората ще трябва да се плати висока цена.

Няколко събития показват, че ГЕРБ може да помогне за резултата на балотажа. Заедно с още трима бивши премиери – Иван Костов, Кирил Петков и Николай Денков, Бойко Борисов подписа писмо с призив за категорична позиция, която да потвърди евроатлантическата принадлежност на България. А в декларация, одобрена от ЕП, евродепутатите на ГЕРБ в Европейската народна партия заедно с колегата си Радан Кънев, както и Илхан Кючук от либералите на АЛДЕ поискаха София да отговори на руската заплаха в Черно море.

През 2002 г. част от френските леви избиратели отидоха на балотажа с щипки за пране на носа и с гумени ръкавици. Не понасяха Жак Ширак, но гласуваха за него, за да спрат крайнодесния Жан-Мари Льо Пен. Двайсет и четири години по-късно българските избиратели не просто ще решат кой да е президент, а дали да съсредоточат цялата власт в едни и същи ръце. Големият залог за този вот е посоката на България, но също и границите на властта. 

Защото кой иначе ще възпира властта, когато тя започне да не забелязва кого е проснала на земята, за да защити себе си?

Compromised TLS Certificates

Post Syndicated from Bruce Schneier original https://www.schneier.com/blog/archives/2026/10/compromised-tls-certificates.html

The Indian CA eMudhra Limited has eight TLS certificates with laughably weak private keys:

The compromised eMudhra keys were defective at a level that’s challenging the imagination of many of the engineers studying the incident. A normal size for a NIST P-384 elliptic curve cryptography private key contains roughly 384 bits of entropy, a size allowing almost 2384, or a number with 116 digits, different possibilities. The private key sizes of the compromised keys ranged from 3 to 8 bits. Astonishingly, the private keys were 4, 56, 66, 115, 155, 156, 230, 237.

“That is extremely in the ‘this should not be possible’ category,” Valdorda said. “Maybe some horribly dangerous key generation interface has a ‘size’ parameter and they set it to 1 by mistake???”

Ben Cartwright-Cox, director of BGP.tools, said: “My guess is that it’s example code that accidentally leaked to production, but hard to know. But it’s bonkers that no one noticed.”

At this early stage, the most immediate threat appears to be for those using VPNs, especially in countries with governments likely to maliciously intercept traffic. There are likely many other cases for concern. End users largely have no recourse other than to hold off using many non-browser forms of TLS communication until they receive assurances updates are in place.

The whole certificate regime has long been a mess:

The incident is the latest to expose a fatal flaw in the TLS regimen. It’s only as strong as its weakest link, which in this case was eMudhra. Fortunately, transparency logs account for much of that failure, but this measure requires parties to actively monitor massive feeds and works only after unauthorized certificates have been issued. eMudhra representatives weren’t immediately available to answer questions.

One caveat: exploiting compromised certificates requires an active adversary-in-the-middle attack, meaning the attacker must act as a proxy between two TLS parties and receive encrypted traffic, decrypt it, reencrypt it, and send it to the other party. Such capabilities, in some cases, are usually limited to only the most well-resourced attackers. People with control of a local network­at a coffee shop, university, or other organization­face much less of a challenge.

Cleanup of this is going to be another mess—and it’s right on top of the PHP vulnerabilities.

Some more information.

Президентски избори 2026 – гласувайте!

Post Syndicated from Боян Юруков original https://yurukov.net/blog/2026/pr2026-vote/

В неделя 25-ти октомври българите живеещи зад граница, тези на почивка или в командировка ще могат да гласуват в 613 секции на 556 места по света. 280 от тях са с машинно гласуване. Призовавам всички да излязат да гласуват рано. Секциите отварят в 7:00. Споделете къде ще гласувате с близки и познати, за да им припомните, че имат тази възможност. Много хора все още не знаят, че имат това право без да са подавали заявление или че могат в друга секция от тази в заявлени

В последната седмица около 30 секции в чужбина бяха с нов адрес. Изпратих допълнителен мейл с промяната на всеки засегнат. Все пак, препоръчвам да сверите секцията си преди деня на вота. След като гласувате може да отбележите с бутоните на картата дали е било натоварено. Напомням, че този път декларациите, че не сме гласували другаде, се попълват лично пред самата комисия. Повече за процеса на гласуване ще намерите в мейла ми преди две седмици или в тази статия. Още информация ще намерите на сайта на ЦИК, МВнР, както и в предишните ми статии.

Този път ще има доста машини в страната и в чужбина, но все пак много секции ще са само с хартиено гласуване. Ако искате да помогнете със засичане на нередности с броенето на тези, има време да се включите в инициативата на Ти Броиш.

Single-tenant Titus: VM-level isolation on a multi-tenant container platform

Post Syndicated from Netflix Technology Blog original https://netflixtechblog.com/single-tenant-titus-vm-level-isolation-on-a-multi-tenant-container-platform-6d8b1909d163

Samartha Chandrashekar & Nick Parker

You click play on a Friday night, and in the second that follows, dozens of services answer in milliseconds. Most of them run on Titus, our internal container platform. Titus is, in essence, a Kubernetes-based container hosting platform: we keep both the control plane and the data plane (the container hosts that actually run containers) patched and up to date, so application teams get a consistent and reliable container experience. They hand us a container, and we run it, with no host, cluster, or kernel to own. Titus launches millions of containers every week across tens of thousands of EC2 instances in multiple AWS regions. It is multi-tenant by default: many containers from many teams share each host. That density is what makes container compute efficient, and it is why Titus has been the default home for so much of Netflix’s compute for years.

For most workloads, sharing a host works well. For a few, it does not, and those few include some of the most demanding real-time systems we run. This post is about them, and about single-tenant Titus, a mode that gives a task its own virtual machine while keeping everything else about Titus the same: the API, the deployment path, and the managed experience where the Compute/Platform team, not the application team, owns the host.

We will walk through why shared-kernel isolation runs out of road for certain workloads, how we measure isolation rather than asserting it, the options we weighed (microVMs, gVisor, EC2, and more shared-kernel tuning) and why a dedicated VM inside Titus won, how the mode is built on the Titus federation layer and autoscaling, and what we have seen along three axes: isolation, fleet efficiency, and the operational cost of keeping the fleet patched.

The cost of good neighbors

Multi-tenancy is a tradeoff. Packing many containers onto a large bare-metal instance keeps utilization high, but it also means those containers share a single Linux kernel and the underlying hardware. Titus isolates them with the tools the kernel provides: cgroups cap CPU, memory, and disk; namespaces give each container its own view of the system; seccomp and AppArmor restrict the system calls a container can make; the Completely Fair Scheduler divides CPU time; the iocost controller meters disk IO; and traffic shaping meters each container’s slice of the network. Each container also gets its own identity, IAM role, and security groups, so tenants are isolated for security and resource management.

These mechanisms provide isolation for what the kernel can partition. They cannot fully partition what is shared in hardware. A group of cores shares a last-level cache and a path to memory, so a container that suddenly pulls a lot of data from RAM evicts a neighbor’s cache lines and slows it down, even when both stay inside their CPU limits. There is no cgroup for memory bandwidth or cache residency, as there is for CPU shares. The interference is real, it is hardware, and it does not show up as either container exceeding its quota.

A noisy neighbor and a co-located app each stay within their cgroup CPU and memory limits, but both draw on a shared last-level cache and memory bandwidth that lack cgroup fences. The noisy neighbor takes most of it, so the co-located app stalls and its tail latency rises even though no one exceeded a quota.

We have written about this before. Predictive CPU isolation of containers at Netflix moved some placement decisions out of the kernel and into a service that forecasts each container’s CPU demand and re-pins containers to cores to reduce cache interference, formulated as a combinatorial optimization solved every minute. Noisy Neighbor Detection with eBPF instruments the kernel scheduler to surface per-container run-queue latency, so we can see a victim being starved in close to real time. And Mount Mayhem traced container-startup slowness to a global kernel lock amplified by modern CPU cache topology. Each of these raised the floor for everyone on the platform, and we are continuing that work.

A decade of shared-kernel isolation, at Netflix and across the industry, has not made co-tenancy invisible, because a noisy neighbor is not one problem but a family of them. Almost every physical resource a host shares is its own axis of interference, and a cgroup can fence very few of them:

  • CPU performance indeterminacy. Co-located threads contend for the run queue, so scheduling latency rises even while a container remains within its CPU quota. Separately, a neighbor with a large working set evicts a tenant’s last-level cache lines and saturates memory bandwidth, neither of which a CPU share can partition.
  • Network bandwidth and packets per second. Per-container shaping competes for link bandwidth, and receives processing runs in softirq context, charging one container’s packet work to whatever CPU a neighbor is running on. A flood of small packets exhausts a core’s softirq budget long before any bandwidth cap is reached.
  • Storage bandwidth and IOPS. A neighbor saturating a device’s queue serializes everyone’s I/O, and on cloud block storage, the per-volume and per-instance throughput ceilings are a shared budget in their own right.
  • Long tail. Page-cache reclaim, NUMA and cross-socket interconnect traffic, TLB-shootdown interrupts, PCIe and GPU contention, package-level power and thermal throttling, and contention on kernel global locks (the class of problem behind Mount Mayhem) each degrade neighbors in their own way.

What unites them is that they are physical, shared, and below the level a quota can reach. A platform can cap how much CPU time or memory a container is granted; it cannot hand each tenant its own slice of the memory bus, its own softirq budget, or its own portion of the last-level cache.

Of these, the network dimension has bitten hardest in our experience. Per-container bandwidth shaping uses a hierarchical token bucket (HTB) queueing discipline that serializes traffic with a global lock to account for each container’s bytes and packets. Under a flood of small packets from a single container, contention for that lock can burn kernel CPU and starve co-located containers of the time they need to process their own traffic, resulting in TCP retransmits and tail-latency spikes on services that did nothing wrong. The mechanism meant to prevent noisy neighbors becomes one.

The workloads most exposed to this are stateful, high-throughput streaming jobs: real-time data pipelines and stream processors that continuously move large volumes of data and maintain in-memory state. When one of these is perturbed, recovery is not cheap. A stream processor that falls behind or loses its place may have to restore from a checkpoint and pause processing for many minutes to catch up. For these jobs, intermittent interference from a neighbor is not a small slowdown that averages out; it is a stop-the-world event that pages an on-call engineer. The same teams report, accurately, that they never saw this on a plain EC2 instance.

Why we kept coming back to the VM

Full VM isolation, where a workload gets its own host and kernel, is the standard our customers are already happy with. The question was not whether VM isolation works; it was how to offer it without giving up what makes Titus worth using. We weighed four paths.

  1. Keep improving shared-kernel isolation. This helps every workload on the platform, needs no opt-in, and we are still investing in it (more on the roadmap below). Its limitation is structural. Each round of tuning narrows the gap without closing it, because the underlying hardware remains shared. Cache, memory bandwidth, and the kernel’s own shaping and scheduling locks are not things a container boundary can fully contain. Shared-kernel isolation is the right default and the wrong promise for a workload that cannot tolerate a bad minute.
  2. microVMs (Firecracker, Kata Containers). Lightweight VMs boot in about 150 milliseconds by emulating far less hardware than traditional VMs, which is why they power serverless platforms. They were the most appealing alternative on paper, and we carefully reviewed them. Three things made the cost hard to justify. First, the hardware virtualization they rely on is available only on bare-metal instances or through nested virtualization, and nested virtualization was not ready on the instance types we run at Netflix at the time, so adopting microVMs broadly would have constrained us to a narrow slice of the fleet. Second, there is no managed microVM service we could build on, which means we would have to run and maintain a virtualization layer ourselves: patching the hypervisor, live-migrating guests, and qualifying emulated devices. That is exactly the kind of operational surface we prefer not to own when we can avoid it. Third, even setting those aside, microVMs add virtualization overhead on CPU- and IO-bound work and do not support GPUs. Excellent isolation, but at a price in flexibility and operational load we were not willing to pay.
  3. gVisor. A user-space kernel that intercepts system calls provides sandbox-grade isolation without a hypervisor, thereby avoiding the bare-metal constraint. The catch is performance and dependency. Intercepting syscalls in user space adds overhead on IO-heavy paths, which are precisely the workloads we most need to protect, and the open-source project lags behind its internal counterpart in fixes and is effectively maintained by a single vendor. The isolation we would gain came with a throughput tax on the exact jobs we were trying to help.
  4. Move the workload to EC2. It is possible to run containers directly on EC2 instances. The problem is that the application team takes back the operational load that Titus exists to carry: choosing instance types, patching hosts, and sizing and scaling the fleet. For a team that came to Titus precisely to avoid those things, this is a regression in the experience, and the move between Titus and EC2 has historically been a one-way door that teams are reluctant to cross.

Spectrum of isolation options from lighter and more shared to stronger isolation: shared-kernel containers, then gVisor, then microVMs (Firecracker or Kata), then a full VM as used by single-tenant Titus, which is highlighted. Each option is annotated with its launch latency, overhead, and the entity that operates it; single-tenant Titus is a dedicated EC2 instance with no additional virtualization overhead.

There is also a question of what kind of isolation we actually need. microVMs and gVisor are built for security isolation between mutually distrusting tenants, the case where one tenant might actively try to attack or escape into another. Among Netflix teams, that threat model is more than the situation warrants. What these workloads need is resource and performance isolation: a guarantee that a neighbor cannot steal their CPU, cache, memory bandwidth, or network, not protection from a hostile co-tenant. A dedicated EC2 VM delivers exactly that, with hardware we do not have to emulate and a kernel we do not have to sandbox. We pay for the isolation we need rather than for a stronger security boundary.

microVMs and gVisor asked for a large, bespoke investment with real risk in order to approximate something we could get directly: a VM. Using EC2 to run containers provides the VM, but takes away the managed experience. So we took the direct route and brought single-tenant VM isolation into Titus itself, under the existing API and the existing shared-responsibility model.

How single-tenant Titus works

The idea is simple to state: a single-tenant task runs on its own EC2 instance, sized to fit it, with nothing else scheduled alongside. That instance is still a Titus container host that the Compute/Platform team owns and patches. The team running the workload sees the same Titus API and the same deployment path. Nothing about how they package or ship the job changes.

Side-by-side anatomy of a multi-tenant Titus, where multiple teams’ containers share one Linux kernel and the hardware beneath it and contend with one another, versus a single-tenant node where one task plus its platform sidecars owns the whole machine with no co-tenants.

Most of the work happens in the federation layer, the part of Titus that decides where a job runs (which cell, which capacity) before it is scheduled onto a node.

When a job is eligible for single tenancy, three things happen.

  1. Federation decides eligibility and the envelope. Eligibility is governed by an allowlist maintained by the Compute/Platform team; a team opts in by targeting a single-tenant workload group rather than flipping a flag in the public API. For an eligible task, federation tags it as single-tenant and records the set of instance families it may run on, ensuring consistent performance across the workload. Consolidating this decision in federation follows the same principle we use for routing in general: placement intelligence belongs in one place, above the individual cells, where it can account for capacity and availability across the region.
  2. Autoscaling provisions a dedicated node. Given a pending single-tenant task, our autoscaling implementation launches the smallest instance that satisfies the task’s requested CPU, memory, and GPU from the allowed families for the task just in time. Taking the tightest fit keeps the unused remainder of each dedicated node small. The next section covers this in detail.
  3. The scheduler enforces one task per node. Single-tenant pods are configured with pod anti-affinity to prevent colocation with other pods, along with a priority class that exempts the task from preemption. Single-tenant nodes are also tainted to prevent unrelated workloads from being placed there, with only single-tenant workloads tolerating this taint. We also disable defragmentation/repacking for these nodes, so a single-tenant task is never relocated to repack the fleet. Together, these mean a single-tenant task has its host to itself for its entire life, undisturbed by a neighbor or by the platform’s own bin-packing.

Two design choices are worth dwelling on. First, single tenancy is allowlisted on purpose. If it were a free checkbox in the API, most teams would tick it, because who wouldn’t want a quieter host? And the efficiency that multi-tenancy exists to provide would erode across the fleet. Keeping the Compute/Platform team in control lets us direct dedicated isolation to workloads that need it and steer the rest toward shared capacity, while keeping the public API surface small as we learn. Second, we do not silently resize anyone’s job to fill its node. The job keeps the resources it requested; we recommend sizing it close to a node shape so the dedicated instance is well utilized, while keeping the workload portable and running identically whether in single-tenant mode or not, regardless of the host’s dimensions. Moving in and out of the mode is a configuration change, not a rewrite.

A few perpetrators, a lot of collateral damage

Noisy-neighbor pain is not spread evenly. In practice, a small number of workloads cause most of the disruption: a job that floods the host with small packets, churns the page cache, or saturates memory bandwidth degrades the performance of every other container unlucky enough to share its host. Some of these are also among the workloads most affected by contention, because a job can be both a source of interference and sensitive to it. The shape of the problem is a few perpetrators and many victims.

That shape is what makes single tenancy a precise lever rather than a blunt one. We do not need to give every workload its own machine. We need to pull the handful of perpetrators and the most disruption-sensitive victims onto dedicated nodes. Doing so protects their former neighbors directly and removes the reason the platform was spreading sensitive workloads apart with anti-affinity placement in the first place. The hosts left behind are quieter, and because they no longer have to be kept partly empty to honor spread rules, they pack more densely.

Before-and-after view of the Titus fleet. Before: a few red perpetrators are scattered across shared hosts, the amber workloads beside them are disrupted, and anti-affinity spreading leaves dashed stranded capacity. After: each perpetrator runs on its own dedicated single-tenant node, the remaining shared hosts are fully loaded with healthy workloads, and one host’s worth of capacity is reclaimed.

On the left is the fleet before: perpetrators sit on shared hosts, the workloads next to them suffer, and anti-affinity rules leave gaps that cannot be filled. On the right is the same fleet after: each perpetrator has its own right-sized node where it can be as noisy as it likes, with no one to disturb; the remaining hosts run full of undisturbed workloads; and the capacity that used to be stranded comes back. A few dedicated nodes buy isolation for the perpetrators and a calmer, denser fleet for everyone else.

Provisioning many small nodes

Single tenancy trades fewer large, shared instances for more small, dedicated ones, and that shift has consequences across the stack.

The first is the control-plane load. More nodes mean more for the Titus control plane to track and more VM launches against the EC2 control plane, the latter mattering most during a regional failover, when we scale up the fastest and can least afford a throttle. Titus is already a federated system: each region is divided into independent cells, which limit how large any single control plane can get, and let us add capacity by adding cells rather than growing a single stack without limit. We migrate workloads in stages rather than all at once, and we exercise the launch-rate path under controlled load on a schedule rather than discovering its limits during an incident.

The second consequence is capacity management, where the design changed the most. With one task per node, the fleet now spans many instance shapes whose demand shifts continuously as jobs come and go. Pre-staging static pools of every shape would be slow to manage and wasteful, so we instead provision single-tenant nodes on demand. It handles provisioning end-to-end, and several of its features line up with exactly what single tenancy needs:

  • Just-in-time, right-sized provisioning. Single-tenant jobs are configured with a list of supported instance families based on their performance requirements. At launch, they are mapped to the best-fit node size by comparing requested resources against the selected instance families. New nodes of that instance type are brought up by the autoscaler to meet the pending demand. Single-tenant pods are configured with anti-affinity to all other pods, so the scheduler naturally lands one pod per autoscaled node. Newly vacated nodes may be reused by any pending deploys before they’re automatically torn down. The node pools themselves are shared across single-tenant workloads and describe a catalog of available instance families and sizes.
  • Single tenant node pools. Single tenant may run in separate clusters or be shared with multitenant clusters. The pools are configured with a list of supported instance-type permutations and are pinned to a Titus container host AMI. This is where the managed experience lives: the host image and its configuration are ours, declared once and applied to every node created.
  • Consolidation management. In multi-tenant environments, we default to a repack/defrag behavior that periodically relocates workloads. This doesn’t apply in single tenant, where nodes are explicitly each running at most one workload. We therefore reclaim only nodes vacated by workloads that have scaled in or terminated. Node termination is performed in two stages, allowing nodes to be reused for pending workloads before they are fully terminated.
  • Drift-based patching. When we publish a new container host AMI, we support a “mutable” deploy to existing nodes without affecting any hosted containers, and an “immutable” deploy that updates the target AMI for newly created nodes. This means that many node upgrades don’t require disrupting workloads, but we reserve the right to roll the fleet with our users if needed.

The launch-latency tax, and why warm pools are harder here

Provisioning on demand does not make a node appear instantly, and launch latency is the tradeoff single tenancy asks us to manage most carefully. Bringing a single-tenant task to the point where it can serve traffic has two parts: standing the node up (booting a fresh EC2 instance, then pulling and extracting the container image, which is the largest part of host setup for most jobs) and the application’s own startup (a JVM loading and JIT-compiling its classes, a cache filling, and so on). A fresh instance takes tens of seconds before the image pull even begins.

In multi-tenant Titus, most of this is hidden. A new task usually lands on a Titus container host that is already running and already has the image layers cached, so starting it takes only a few seconds rather than minutes; the host boot was paid for once, long ago, and amortized across every task that has run there since. Single tenancy gives up that hiding place. Every single-tenant task waits for its own machine to boot and pull its image.

The usual remedy is a warm pool: keep some instances booted and idle so a pending task lands on one immediately. This works well for the multi-tenant fleet precisely because that fleet is close to homogeneous. A handful of large shapes cover almost everything, since any task can be packed onto a big shared host. A small amount of warm capacity in a few shapes gives a high hit rate, and its cost is spread across the many tasks that will use it.

Single tenancy inverts those economics, and this is the part worth being explicit about.

Press enter or click to view image in full size

Because every task gets a right-sized node, the fleet spans many instance shapes (several families across many sizes), and a warm instance only helps a pending task whose shape matches it. A warm r7i.2xlarge does nothing for a task that needs an m7a.8xlarge. To achieve a good hit rate, we would need to hold idle capacity in every family-and-size bucket, and idle capacity in a bucket with no task to fill is pure cost. The very property that makes single tenancy efficient at steady state, tight best-fit sizing, works against warm-pool reuse: more distinct shapes mean more buckets and a lower hit rate per dollar of standing capacity. And the pressure peaks exactly when it is least welcome. During a regional failover or a live event, when many tasks need fresh nodes at once, a thin warm pool spread across many shapes drains immediately, and the rest of the demand pays the full cold-boot cost.

So we treat warm capacity as a small, targeted lever rather than a default. We keep a little pre-warmed capacity for the most latency-sensitive single-tenant starts, and we deliberately narrow the menu of shapes to a curated set of sizes rather than the full continuum, so warm capacity concentrates into fewer buckets and trades a little best-fit efficiency for a better hit rate. Everything else provisions just-in-time and accepts the boot.

The more durable wins are in cutting the launch cost itself rather than pre-paying for it, and they help both single- and multi-tenant nodes, which is the better place to spend the effort:

  • Faster image distribution. The image pull dominates the host setup, so newer OCI image formats and lazy-pulling snapshotters such as stargz and SOCI, which fetch only the bytes a container actually reads at startup rather than the whole image up front, reduce the largest component of the gap.
  • Checkpoint and restore. For processes that are slow to initialize, snapshotting a warmed-up application with a tool like CRIU and restoring it, rather than cold-starting it, removes most of the second half of launch latency.
  • Instance type selection. In multitenant configurations, we have historically used metal instances, which offer slightly better performance but come with a slower startup time. In a single-tenant configuration, node startup latency is more important, so we have moved away from these instances.
  • Scheduling optimization. Through regular stress testing of fleet scaling, we found a scheduling bottleneck caused by Kubernetes preemption logic, leading to nodes being scaled up quickly but then left idle while waiting for workloads to be scheduled on them. This was ultimately unnecessary, as our single-tenant pools do not run preemptible workloads. Disabling preemption greatly improved scheduling performance when under strain.

None of this makes the tradeoff disappear, and it is worth stating plainly: a single-tenant node is slower to stand up than a slot on an already-warm shared host, and hiding that with warm pools costs more per node here than it does on the multi-tenant fleet, because the warm pool cannot be as homogeneous. But for the long-running services that single tenancy targets, paying that cost once at launch in exchange for a quiet life afterward is a trade these teams are glad to make.

Measuring the difference

Isolation claims are easy to assert and hard to trust, so we measure them with a repeatable benchmark and a single score.

The method is a differential one. We run a reference container, a healthy and representative application, and record its throughput and tail latency while it runs alone. Then we run it again next to a havoc container engineered to be a bad neighbor: a UDP flood through XDP to stress the network-shaping path, pointer-chasing and STREAM to pollute the last-level cache and saturate memory bandwidth, fsync storms against the disk, stress-ng to abuse the scheduler, and GPU-burn to monopolize an accelerator. We only trust a run once the host has reached a steady state, which we confirm with the kernel’s Pressure Stall Information: we wait until cpu_some or mem_some shows that tasks are actually stalling on a contended resource, not merely that the resource is busy. Each scenario is run many times with fixed seeds, and we report the median with a bootstrapped confidence interval, because noisy-neighbor distributions are heavy-tailed and a simple average can mask the spikes that matter.

From the reference container’s numbers, we derive a simple measure of how well isolation held. Throughput efficiency is the fraction of operations per second the app retains under attack; latency efficiency is the ratio of its undisturbed P99 to its P99 under pressure. A neighbor that doubles the reference app’s P99 drops the latency efficiency. As an illustration, a reference app whose P99 latency goes down next to a havoc container achieves a certain latency efficiency, and one whose throughput falls from a to b operations per second achieves a certain throughput efficiency. The composite score is a weighted blend of the two, with a latency-sensitive preset that gives greater weight to tail latency for interactive and streaming-path services. A perfectly isolated system scores 100%, and a single hard failure invalidates the run regardless of the average.

Noisy-neighbor isolation

cgroups container isolation isn’t perfect, and applications may experience worse performance due to sharing a machine with a determined neighbor. This could extend to disk and/or network IO where the same volumes or interfaces may be shared across workloads. For a distributed workload, this can lead to measurable inconsistencies in performance depending on where the replicas are placed. For more sensitive workloads, this variance can mean the difference between stability and getting paged.

The single-tenant option makes it possible to better isolate workloads that cause problems for their neighbors and/or are more sensitive to such problems. This can be used as a stopgap until the specific regression problem is resolved and consistency is restored, or kept permanent for load patterns that aren’t worth supporting in a shared environment.

Efficiency

The second effect is fleet efficiency, and it is the one people expect to go the wrong way. Dedicating a node to a single task consumes that node’s slack, so the naive expectation is that utilization falls. In aggregate, it can move the other way, for a reason related to how we dealt with poor isolation before single tenancy existed.

To protect sensitive workloads on shared hosts, the platform used anti-affinity placement, scattering them across the fleet to reduce colocation of the same workload on the same nodes. Spreading fights bin-packing: it strains capacity, because a host kept partly empty to honor an anti-affinity rule cannot be filled by a workload that would otherwise have fit there. When isolation-sensitive workloads move to dedicated nodes, the need for spreading and fragmentation goes away, and the remaining multi-tenant fleet can pack more densely.

Another source of fragmentation is services that are sensitive to disruption. These are typically stateful services where recovery is expensive. As these services become more common in a given population, they can lead to nodes being held up by pods with strict disruption requirements. This can lead to an inability to defrag and recompact the pool during off-peak times. The symptoms and resulting drop in fleet efficiency caused by disruption-sensitive workloads mirror what’s observed for workloads with anti-affinity rules.

Depending on the magnitude of the anti-affinity and/or disruption budget problem, moving such workloads to single-tenant pools can result in equivalent or even improved placement when all costs have been accounted for. It also becomes easier to quantify the cost to end-users. Rather than trying to attribute fleet-wide fragmentation to individual workloads, we can directly quantify waste as single-tenant node overhead.

The theory and the practice diverge here, and it was the practice that decided it. In principle, the efficiency ceiling is higher for multi-tenant bin-packing: pack enough tasks together, and a host fills almost completely. We do not reach that ceiling. AWS offers a discrete set of instance sizes, so a large shared host rarely matches the exact sum of the requests we place on it, and the gap between a host’s capacity and what we can actually pack onto it is a bin-packing hole we cannot fill. At the granularity of large instances, those holes are sizable. Right-sizing an instance to a single workload, picking the closest fit from many shapes instead of draping many workloads over one big host, captured more of the available efficiency in our experience than the higher theoretical ceiling ever delivered. The clean theory favored multi-tenancy; our measured fleet favored right-sizing.

Container-host maintenance

The third effect is operational, and it shows up in how we keep the fleet patched. A multi-tenant host is hard to take down for maintenance precisely because it is full: draining it means relocating many tenants at once, several of which carry disruption budgets that limit how fast they can move, so a routine patch becomes a careful, coordinated evacuation. A single-tenant host runs exactly one task, with consolidation and defragmentation turned off, so draining it means relocating only the one workload, and we can automatically handle that when a new AMI ships. The remaining multi-tenant hosts are easier to maintain, too, because the workloads that were most sensitive to disruption are no longer stranded on them.

What it changes, and what it doesn’t

Single-tenant mode is a configuration, not a migration. A team moves a workload onto a dedicated node, and back, with a labeling change, without rewriting anything and without leaving Titus. That turns the isolation decision into a reversible setting, which is the opposite of the one-way door between Titus and EC2 that teams used to face. A team can try single tenancy for a quarter, measure it, and step back if the trade-off isn’t worth it for them.

What does not change is the contract. The Compute/Platform team still selects the instance type, patches the host, and sizes and scales the fleet underneath. The application team still uses the Titus API, the same delivery pipeline, and the same observability. Single tenancy is a new point on the isolation axis offered within the existing managed experience, not a separate product that the team has to learn and operate.

When a dedicated node is the wrong call

A dedicated node is a real cost, and single tenancy is not free isolation. Two things are worth weighing before reaching for it.

First, a single-tenant task does not get the whole machine; it gets the machine minus overhead. Every Titus container host, dedicated or shared, runs the platform sidecars, system services, the kubelet, and the host environment itself, and that overhead is a roughly fixed slice of CPU and a few gigabytes of memory. On a shared host, that slice is paid once and amortized across the many tasks running there. On a dedicated node, a single task handles it. Because the cost is fixed rather than proportional, it is punishing as a fraction of a small instance and negligible on a large one: a small dedicated node can lose tens of percent of its resources to overhead, while on the largest shapes it rounds to a couple of percent.

Second, because a task is placed on the smallest instance that fits it, there is usually a gap between what the task asked for and the next available shape, and on a dedicated node, that gap is pure waste, with no neighbors to soak it up. The two effects compound: fixed overhead plus the best-fit remainder set a ceiling on how much of a dedicated node a workload can actually use, and that ceiling is lowest exactly where people are tempted to reach for isolation casually, on small instances. However, this sizing waste can be reduced through coordination with the service owner as needed.

The guidance follows from the arithmetic. Single tenancy pays off for large, long-running, performance-sensitive, disruption-sensitive workloads, sized close to a node shape and run as fewer, larger replicas rather than many small ones. It is the wrong call for small, bursty, or highly elastic workloads, where the overhead fraction is high, the dedicated node sits mostly idle, and multi-tenant packing is both cheaper and faster to scale. This is also why the mode is allowlisted rather than a self-serve checkbox: the platform can keep workloads on the side of that line where they belong, and leave the ones that would gain little from a node of their own on the shared fleet, where they are cheaper to run.

Who’s using it

The first adopters are the workloads that motivated the work: real-time data infrastructure. Managed Apache Flink stream processing, streaming data connectors, and telemetry and logging pipelines were both the most frequent sources of network contention and the most damaged by it, because their recovery is expensive and their disruption budgets are tight. These are stateful, high-throughput jobs where a few seconds of starvation can cascade into minutes of catch-up, and where the platform’s own repacking used to be a source of disruption in its own right.

Moving them onto dedicated nodes removed the class of problem rather than mitigating it. The teams running them report stable operation, having previously seen intermittent, hard-to-attribute interference, and their jobs are no longer relocated by fleet repacking, removing a second, self-inflicted source of disruption. Latency-sensitive serving paths and a handful of GraphQL and edge services have followed for the same reason: a predictable tail matters more to them than a few points of bin-packing efficiency.

This is an ongoing rollout, not a finished one. We are widening the set of eligible workloads as we learn, using the largest production jobs as the stress test for the platform’s scaling assumptions, and watching the control-plane and EC2 launch-rate metrics as the count of small nodes grows. We have also been running periodic stress tests to exercise scaling ahead of real user workload, and making improvements to autoscaling and scheduling logic along the way.

What’s next

We are not done on either side of the tradeoff. On single tenancy, we are reducing launch latency with smarter pre-warming of common shapes, broadening the allowlist as scaling data holds up, and extending the model beyond long-running services as cost attribution and capacity stories mature. On the multi-tenant side, which remains the right default for most workloads, we are addressing the dimensions that hurt the most. The largest is the network: replacing HTB’s global-lock shaping with an eBPF-based Expected Departure Time approach that rate-limits by timestamping packets rather than contending on a lock, and pairing it with a lower-overhead container network device. We are also evaluating hardware cache and memory-bandwidth partitioning (Intel RDT and AMD PQoS) to give the kernel a real lever on the last-level cache, hardware GPU partitioning (NVIDIA MIG) for accelerator isolation, and continued work on the cgroup v2 IO controller for disk. This isolation benchmark lets us rank these by return on effort rather than by intuition, and show customers, in the numbers, that the shared fleet is getting quieter over time.

Single-tenant Titus is also a step toward something larger. Netflix’s Platform teams offer two ways to get compute: virtual machines on EC2 & containers on Titus. We want to replace that with a single Compute API that takes intent rather than mechanism into account: how much isolation a workload needs, how quickly it must launch, how long it can run without disruption, and what business domain it belongs to. The platform then makes placement and runtime choices, and can make globally optimal ones because it sees the whole picture.

Conclusion

Multi-tenancy is the right default for a container platform, and we will keep making it better for everyone. But the right default is not right for everything. Single-tenant Titus gives the workloads that need it the isolation of a dedicated VM, provisioned and patched by our existing node management, under the same API and the same managed experience, without taking away the freedom to change their mind. We can now point to the difference rather than describe it: a tail that stops moving under a noisy neighbor, a fleet that packs more densely once spreading is retired, and hosts that are faster and safer to patch. For the streaming and data systems at the heart of Netflix’s real-time platform, a room of one’s own turned out to be the feature that mattered.


Single-tenant Titus: VM-level isolation on a multi-tenant container platform was originally published in Netflix TechBlog on Medium, where people are continuing the conversation by highlighting and responding to this story.

AWS Continuum for code vulnerabilities is now generally available

Post Syndicated from Esra Kayabali original https://aws.amazon.com/blogs/aws/aws-continuum-for-code-vulnerabilities-is-now-generally-available/

Today, we’re announcing the general availability of AWS Continuum for code vulnerabilities. AWS Continuum is a security service that finds and validates code vulnerabilities, then delivers fixes as patches you can automate or as pull requests in your repositories. AWS Continuum for code vulnerabilities confirms which findings are exploitable in your environment, ranks the resulting issues by business impact, and proposes a fix for each one. Every remediation starts in a mode where Continuum proposes the fix and a person approves it before it ships. In the future, you will be able to decide which actions Continuum can take on its own, within the guardrails you define.

Using frontier artificial intelligence (AI) models, threat actors can turn a vulnerability disclosure into working exploit code in minutes, and the same tools that speed up development also increase the volume of findings your teams must process. If your organization runs a large application estate, your scanners likely produce thousands of findings a day, and many of them need no action. A finding can be unreachable, unexploitable, or already mitigated by a runtime control. Generic severity scores don’t tell you which resources a threat actor can actually reach, so a critical score on a dev-only utility looks the same as a medium score on a service one step away from a payments database. Previously, confirming whether a finding was exploitable took hours of manual investigation, and shipping a fix with confidence took days of coordination across security, infrastructure, and application teams, because the blast radius of a change is hard to assess without business context. To close that gap, Continuum proves which findings are exploitable and bounds the risk of each fix it proposes.

Continuum builds a context graph from two primary sources: your code repositories and your AWS environment. For AWS, you set up a collector in the account and Region where your code runs. The collector gathers resource details such as AWS Config resources and network configuration so Continuum can judge whether a vulnerability is reachable over the network and what a threat actor could reach from it. From this graph, Continuum learns which systems are business-critical, who owns them, how services depend on one another, and which data each one touches. It uses that picture to identify your highest-value systems, such as customer data stores, payment pipelines, and authentication services, and then ranks each resulting issue by how close its attack path runs to those systems.

Continuum analyzes each finding against your code and its environment context and assigns an evidence level, such as a verdict proven by static analysis of the vulnerable code path. For findings it can reproduce, Continuum runs the exploit in an isolated sandbox and attaches proof-of-concept code with the reproduction steps. It produces the attack path, the supporting source analysis, and a blast radius assessment instead of a risk score alone. It also evaluates whether your existing defenses would detect and stop the validated path.

For each confirmed issue, Continuum generates a fix (a code patch, a dependency upgrade, or a configuration change) and opens it as a pull request in your connected repository, ready to review. Every fix requires human approval: you review and merge the pull request, so the final decision stays with your team. In the future, you will be able to build confidence in specific remediation classes and let Continuum apply those fixes automatically once its confidence gates pass, such as test coverage, scope bounds, and historical success rate.

AWS Continuum for code vulnerabilities in action
To show how this works, I open AWS Continuum in the console and go to Code vulnerabilities. Before I can review issues, I set up an environment. I connect a code source, either a GitHub integration or an Amazon S3 bucket, and then create an environment that scans it on a schedule I choose. An Amazon S3 source has a couple of prerequisites: the bucket sits in the same account and AWS Region where I turn on AWS Continuum, and I grant access through an AWS Identity and Access Management (IAM) role that AWS Continuum assumes. I can optionally add AWS infrastructure context by setting up an AWS Continuum collector in the account and Region where my code runs and authorizing my environment to use it. For the full requirements and steps, see the AWS Continuum User Guide.

The Overview page brings these pieces together in one place, showing my Code integrations, the Environments built on them, and the status of any AWS collector that supplies AWS resource context.

I open one of my environments. The Issues tab lists validated, prioritized issues rather than raw scanner output, each with a severity, a status, and the time it was created. I choose one of the issues.

The Overview rates it High severity, with the status Completed and the remediation already Delivered to GitHub. The Risk assessment explains why. Continuum rates its Exploitability as Exploitable, with an evidence level of Static proven and a validation run status of Completed. Likelihood is High, since the service is reachable from an attacker, requires no authentication, and needs no user interaction. Impact is Moderate, which means an attacker gains the ability to modify business data, with a blast radius reaching other users in the same tenant. A Proof section includes the source analysis behind the verdict.

The Remediation section shows a fix already delivered as a pull request in GitHub, changing four files, with 50 lines added and 24 removed across the cart service. Continuum opens the fix as a pull request titled Continuum fix, and I choose View pull request to open it in GitHub. The console is explicit that a generated patch does not mean the issue is fixed. I still review and merge it, which keeps the final decision with my team. A Contributing findings section lists the specific scanner finding this issue was built from.

The pull request description carries the same risk assessment, remediation summary, and proof from the console, so whoever reviews it in GitHub sees the evidence without leaving their workflow.

The Findings tab lists the raw scanner findings across the environment, the evidence that issues are built from.

The Scans tab shows the history of each scan with its status, origin, and request and completion times, and I use Configure scan frequency to change the cadence or Queue scan to run one on demand. The Configuration tab is where I manage the environment: the code and context sources it reads from, its code integrations, environment settings such as whether Continuum creates remediation patches, and the AWS collectors it uses for AWS context.

In a single workflow, I work through the validated issues in priority order with each scan, reviewing the evidence and scope behind each one before I approve and merge the fixes I trust. Every fix waits for my approval, so the backlog keeps shrinking while my team keeps control of what ships.

Now available
AWS Continuum for code vulnerabilities is available today in US East (N. Virginia) and US West (Oregon) Regions. For pricing, visit the pricing page.

To learn more, visit the AWS Continuum for code vulnerabilities product page and the User Guide. Give it a try in the AWS Continuum console today, and send us feedback through your usual AWS Support contacts.

— Esra

OS patching and upgrades with Amazon EC2 root volume replacement

Post Syndicated from Akshaya Shah original https://aws.amazon.com/blogs/compute/os-patching-and-upgrades-with-amazon-ec2-root-volume-replacement/

Customers running stateful workloads on Amazon Elastic Compute Cloud (Amazon EC2) need to patch operating systems, upgrade OS versions, remediate vulnerabilities quickly, and patch applications in user space. These workloads are connected to resources such as Elastic IP addresses, secondary network interfaces, attached data volumes, AWS Identity and Access Management (IAM) instance profiles, and DNS records. For OS upgrades or patches that require downtime, a common approach is to replace the instance with a new one launched from a newer Amazon Machine Image (AMI). That approach means moving each of these resources to the new instance. With Amazon EC2 Replace Root Volume (RRV) using Amazon Elastic Block Store (Amazon EBS), you can prepare and validate a replacement root volume in advance. You then swap it onto a running production instance with a single API call. The interruption is limited to the reboot that RRV performs and the time your application takes to restart.

In this post, we show how to use the existing EBS volume option of root volume replacement on a Linux instance to upgrade the operating system generation and apply patches, while the instance keeps its production identity. We also cover instances in Amazon EC2 Auto Scaling groups.

Constraints and considerations

RRV has the following requirements and considerations:

  • The replacement volume must be in the same Availability Zone as the instance.
  • The replacement volume must be in the available state and must not be attached to any instance at the time of the request.
  • If the original root volume is encrypted, the replacement volume must also be encrypted. You can move from an unencrypted volume to an encrypted one, but not from encrypted to unencrypted.
  • For AWS Marketplace instances, the product codes and billing codes on the replacement volume must match those on the instance.
  • The target instance must be in the running state.
  • The instance is automatically rebooted during the process. Memory contents and running processes do not survive the reboot.
  • The delete-on-termination attribute of the original root volume doesn’t transfer to the replacement volume.
  • At this time, root volume replacement supports virtualized instance types and EC2 Mac bare metal instances. Other bare metal instance types aren’t currently supported. Check the Amazon EC2 documentation for the latest list of supported instance types.
  • To avoid a failed boot, make sure the replacement volume has the Elastic Network Adapter (ENA) and NVMe drivers that Nitro-based instances require. Use the same CPU architecture and boot mode (UEFI or legacy BIOS) as the target instance.
  • To avoid an SSH host-key change, copy the existing host keys to the new volume before the swap.
  • Review your cloud-init configuration, since a volume from a fresh AMI snapshot can re-run user data on its first boot.
  • As a best practice, keep application-specific data and configuration on a separate (non-root) volume, so it is not impacted when the root volume is replaced.

Benefits of root volume replacement compared to instance replacement

Benefits of root volume replacement include:

  • Preparation of the replacement volume: You build and validate the replacement volume on a separate instance, so the production instance is untouched until the swap.
  • Reduce the downtime: Reduce the downtime to an in-place reboot instead of replacing the instance and reassociating its attached resources.
  • Test before commitment: You validate the replacement volume in non-production first. If validation fails, you discard it without ever touching production.
  • Resource preservation: The swap retains network interfaces (ENIs), Elastic IP addresses, EBS data volumes, instance store data, IAM instance profiles, security groups, placement groups, and DNS names. As a result, you avoid the re-association, re-attachment, and reconfiguration steps that instance replacement requires.
  • Rollback path: If you keep the original root volume, you can swap back to it.

How it works

It’s a two-phase process: in the preparation phase you build the new root volume, and in the replacement phase you call the root volume replacement API, which swaps the volume and reboots the instance.

Step 1 – Preparation phase: On a separate preparation instance, you create a new volume from a newer OS AMI, patch and configure it in a chroot, and test a copy on a non-production instance.

Preparation phase: on a separate preparation instance, a new root volume is created from a newer OS AMI, patched and configured in a chroot, then validated on a non-production instance.

Figure 1: Preparation phase. You build and validate the replacement root volume on a separate instance before touching production.

Step 2 – Replacement phase: The create-replace-root-volume-task call starts a task that, during one reboot, detaches the original root volume and attaches the prepared one. Network interfaces, data volumes, and Elastic IP addresses stay in place, and the instance returns at the same IP address after the application restarts.

Replacement phase: the replace root volume task detaches the original root volume and attaches the prepared one during a single reboot, while network interfaces, data volumes, and Elastic IP addresses stay in place.

Figure 2: Replacement phase. A single API call swaps the prepared volume onto the running instance, which returns at the same IP address.

What is preserved during the reboot

The reboot clears memory and running processes but preserves the instance’s identity and attached resources:

Resource Preserved Notes
Instance ID Yes Same instance. No termination occurs
Private IP address Yes Retained. The instance keeps its private IP address across the replacement
Public IP / Elastic IP address Yes Remains associated with the instance
Network interfaces (ENIs) Yes All ENIs retain their IP addresses, identifiers, and attachment IDs
EBS data volumes Yes Non-root volumes remain attached
Instance store volumes Usually Volumes stay attached and their data normally survives the reboot, but this isn’t guaranteed. A failed reboot or a problem with the underlying host can cause instance store data to be lost. Keep data you need on EBS volumes.
IAM instance profile Yes Role and policies (including tag-based policies) remain enforced
Security groups Yes All security group associations are retained
DNS names Yes Public and private DNS names are unchanged
Placement group Yes Instance remains in the same placement
Tags Yes Instance tags are unchanged
Memory (RAM) contents No Volatile memory is wiped during the reboot
Running processes No Applications must restart as part of the boot sequence

Solution walkthrough

The walkthrough has four steps:

  1. Create the replacement volume.
  2. Prepare and install patches on the volume.
  3. Test the prepared volume.
  4. Swap it onto the running instance.

Replace placeholder values (such as the instance ID, volume ID, and Availability Zone).

Prerequisites

Before you begin, make sure that you have:

  • AWS Command Line Interface (AWS CLI) v2.36.0 or later that supports the --volume-id parameter on create-replace-root-volume-task, configured with credentials that have permissions for Amazon EC2 and Amazon EBS operations (for encrypted volumes, including the AWS Key Management Service (AWS KMS) permissions to detach the original volume and to attach and decrypt the replacement).
  • A running Linux target instance with an Amazon EBS root volume that you want to replace.
  • A preparation instance in the target’s Availability Zone, launched from a different AMI than the replacement volume’s base so their root filesystems are less likely to share a UUID. If they do share one on XFS, mount the volume with -o nouuid.
  • A non-production test instance of the same instance type, launched from the target instance’s AMI so that it has the same boot mode.

Step 1: Create the replacement root volume

Create the replacement volume in the target instance’s Availability Zone, typically from the root snapshot of a newer OS AMI. If the original root volume is encrypted, encrypt the new one, and make it at least as large as the current root volume. A volume restored from a snapshot loads its blocks from Amazon Simple Storage Service (Amazon S3) on first read, so its first boot can be slower than a normal reboot. Setting the --volume-initialization-rate parameter, or enabling fast snapshot restore on the snapshot, reduces this. Both are billed separately.

First, confirm that the base AMI supports the instance’s boot mode and find the AMI’s root snapshot. The instance reports uefi or legacy-bios. The AMI reports uefi, legacy-bios, or uefi-preferred (which supports both). An AMI with no boot mode uses the instance type’s default.

aws ec2 describe-instances \
    --instance-ids <target-instance-id> \
    --query 'Reservations[0].Instances[0].CurrentInstanceBootMode'

aws ec2 describe-images \
    --image-ids <base-ami-id> \
    --query 'Images[0].{BootMode:BootMode,RootDevice:RootDeviceName,Snapshot:BlockDeviceMappings[0].Ebs.SnapshotId}'

Use the snapshot ID this returns as <base-snapshot-id> in the next command.

aws ec2 create-volume \
    --availability-zone <az> \
    --snapshot-id <base-snapshot-id> \
    --volume-type gp3 \
    --size <size-in-GiB> \
    --encrypted \
    --kms-key-id <kms-key-id> \
    --volume-initialization-rate <MiB-per-second>

Expected outcome: An available EBS volume with a bootable OS, ready to attach to the preparation instance.

Step 2: Prepare and install patches on the volume

Attach the volume to the preparation instance as a secondary disk:

aws ec2 attach-volume \
    --volume-id <new-root-volume-id> \
    --instance-id <prep-instance-id> \
    --device /dev/sdf

Mount the root partition and bind-mount /proc, /sys, /dev, and /dev/pts so that package managers inside the chroot install into the new volume. Use lsblk to find the device. On Nitro-based instances it appears as an NVMe device (for example, /dev/nvme1n1), not /dev/sdf. Copy /etc/resolv.conf so DNS works inside the chroot.

lsblk
sudo mkdir -p /mnt/newroot
sudo mount <root-partition> /mnt/newroot
sudo mount --bind /proc /mnt/newroot/proc
sudo mount --bind /sys /mnt/newroot/sys
sudo mount --bind /dev /mnt/newroot/dev
sudo mount --bind /dev/pts /mnt/newroot/dev/pts
sudo cp --remove-destination /etc/resolv.conf /mnt/newroot/etc/resolv.conf

Inside the chroot, apply OS security patches, install or upgrade application software, and apply configuration. Because the volume is detached from production, you can take as long as you need.

sudo chroot /mnt/newroot /bin/bash
# Inside the chroot, for example:
# - apply OS security updates with your package manager
# - install or upgrade application packages
# - write application and service configuration
# - enable services to start on boot
# - if you upgrade the kernel, rebuild the initramfs and update the GRUB configuration
# - on SELinux-enabled distributions, schedule a relabel (touch /.autorelabel)
# - validate configuration (for example, a service's own config test)
exit

Before detaching, create mount points for the target’s data volumes and add /etc/fstab entries on the new volume. Use UUID= or LABEL= entries rather than device names, which can change between boots on Nitro-based instances.

Then unmount and detach the volume:

sudo umount /mnt/newroot/dev/pts /mnt/newroot/dev /mnt/newroot/sys /mnt/newroot/proc
sudo umount /mnt/newroot

aws ec2 detach-volume --volume-id <new-root-volume-id>

Expected outcome: An available, patched EBS volume that has not been attached to the production instance.

Step 3: Test the prepared volume

Snapshot the prepared volume, create a test volume from the snapshot in the test instance’s Availability Zone, and replace the test instance’s root volume with it. Confirm that the instance boots, the application starts, and the data volumes mount.

aws ec2 create-snapshot \
    --volume-id <new-root-volume-id> \
    --description "Prepared root volume"

aws ec2 create-volume \
    --availability-zone <test-az> \
    --snapshot-id <prepared-snapshot-id> \
    --volume-type gp3 \
    --encrypted \
    --kms-key-id <kms-key-id>

aws ec2 create-replace-root-volume-task \
    --instance-id <test-instance-id> \
    --volume-id <test-volume-id> \
    --delete-replaced-root-volume

Expected outcome: The test instance boots and the application passes your checks. If it doesn’t, fix the prepared volume and repeat this step.

Step 4: Run the root volume replacement

Before you run the replacement, record the current root volume ID and snapshot it as a fallback. Amazon EC2 keeps the original root volume by default. This example also sets --no-delete-replaced-root-volume explicitly. Use --delete-replaced-root-volume only if you don’t need a rollback path.

aws ec2 describe-instances \
    --instance-ids <target-instance-id> \
    --query 'Reservations[0].Instances[0].[RootDeviceName,BlockDeviceMappings]'

aws ec2 create-snapshot \
    --volume-id <original-root-volume-id> \
    --description "Root volume before replacement"
# Then run the replacement:

aws ec2 create-replace-root-volume-task \
    --instance-id <target-instance-id> \
    --volume-id <new-root-volume-id> \
    --no-delete-replaced-root-volume

Monitor the task. It moves through pending, in-progress (when the instance reboots), and succeeded.

aws ec2 describe-replace-root-volume-tasks \
    --replace-root-volume-task-ids <task-id> \
    --query 'ReplaceRootVolumeTasks[0].TaskState'

Expected outcome: The task reports succeeded, and the instance comes back on the patched root volume with its instance ID, IP addresses, network interfaces, data volumes, and IAM instance profile retained. Disruption is roughly one reboot plus your application’s start time.

If the task doesn’t succeed:

  • failed: The instance was rebooted with its original root volume attached. Fix the volume (repeat Step 3), then retry.
  • failed-detached: The instance doesn’t have a root volume attached. Contact AWS Support before you take further action on the instance.

A task can report succeeded even if the instance fails to boot on the new volume, for example because of a boot mode or driver mismatch. Confirm that the instance passes its status checks after every replacement. If it doesn’t, check the console output or the EC2 serial console, then roll back.

aws ec2 describe-instance-status \
    --instance-ids <target-instance-id> \
    --include-all-instances

aws ec2 get-console-output \
    --instance-id <target-instance-id> \
    --latest

Finally, set delete-on-termination on the new root volume to match the original:

aws ec2 modify-instance-attribute \
    --instance-id <target-instance-id> \
    --block-device-mappings '[{"DeviceName":"<root-device-name>","Ebs":{"DeleteOnTermination":<true-or-false>}}]'

Rolling back

To roll back, run another replacement with the original root volume. If you deleted it, pass the snapshot from Step 4 with --snapshot-id instead of --volume-id (the two are mutually exclusive). Root volume replacement accepts snapshots of the instance’s previous root volumes.

aws ec2 create-replace-root-volume-task \
    --instance-id <target-instance-id> \
    --volume-id <original-root-volume-id> \
    --no-delete-replaced-root-volume

Then validate the instance as you did after the swap and set delete-on-termination again. Changes written to the new root volume after the swap aren’t carried back, so keep data that must survive a rollback on a data volume.

If the instance is in an Auto Scaling group, roll back before you exit Standby.

Using root volume replacement with Auto Scaling groups

Instances in an Amazon EC2 Auto Scaling group need different handling, because the group’s health checks and scaling can terminate or replace an instance mid-swap. Choose the approach that matches what you’re updating.

One instance at a time: Put the instance in Standby first, reducing the desired capacity so the group doesn’t launch a replacement. Standby temporarily takes the instance out of service. Then create, validate, and run the root volume replacement, update the launch template so future instances use the new OS, and return the instance to service. For the Standby steps, see Temporarily remove instances from your Auto Scaling group in the Amazon EC2 Auto Scaling User Guide.

A whole fleet: To update every instance in a group from a new AMI, use the ReplaceRootVolume strategy within instance refresh, where the Auto Scaling group replaces each instance’s root volume in stages while preserving network interfaces, data volumes, and instance store data. It applies the same AMI to every instance, so it suits fleet-wide OS updates rather than a volume prepared for one stateful instance. For details, see Replace root volumes during instance refresh in the Amazon EC2 Auto Scaling User Guide.

Clean up

To avoid ongoing charges, delete the resources that you no longer need.

The original root volume and its fallback snapshot, when you no longer need them for rollback:

aws ec2 delete-volume --volume-id <old-root-volume-id>

aws ec2 delete-snapshot --snapshot-id <original-root-snapshot-id>

The preparation instance:

aws ec2 terminate-instances --instance-ids <prep-instance-id>

The test instance, the test volume, and the Step 3 snapshot:

aws ec2 terminate-instances --instance-ids <test-instance-id>

aws ec2 delete-volume --volume-id <test-volume-id>

aws ec2 delete-snapshot --snapshot-id <prepared-snapshot-id>

If an Auto Scaling group uses an AMI registered from the snapshot, deregister the AMI before you delete the snapshot. If you launched a target instance only to try out this workflow, terminate it as well.

Conclusion

Amazon EC2 Replace Root Volume with the direct EBS volume option separates volume preparation from the production interruption. When you need to upgrade an operating system or apply a critical patch, you prepare and validate the change on a separate instance, then swap it in with a single API call. The instance keeps its IP addresses, ENIs, data volume attachments, and DNS names across the swap, so you avoid re-association and re-mounting, and the interruption is limited to the single reboot that RRV performs. Before adopting this approach in production, validate it against your own workload, including boot time and any personalized data on the root volume. To get started, see Replace the root volume for an Amazon EC2 instance without stopping it in the Amazon EC2 User Guide.

 

New Serious PHP Vulnerabilities Released and Patched

Post Syndicated from Bruce Schneier original https://www.schneier.com/blog/archives/2026/10/new-serious-php-vulnerabilities-released-and-patched.html

PHP maintainers have released fixes for two critical vulnerabilities:

PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 fix two critical vulnerabilities that can allow unauthenticated remote code execution. All PHP users are strongly encouraged to update immediately.

Who is at risk: all PHP installations serving web requests, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. We consider the risk highest for mod_php, with a demonstrated exploit where an unauthenticated request can trigger the attack before any application code runs.

The vulnerabilities:

  • RCE via OOM corruption, CVE-2026-109618 (GHSA-w8hw-w9fx-j79w): out-of-memory handling can interrupt PHP while internal request data is only partially initialized. Request cleanup may then treat the invalid data as valid.
  • RCE via stale global state, CVE-2026-109619 (GHSA-6wmf-4rv5-p3rp): request-owned internal state can survive after its backing memory has been freed. A later request handled by the same worker may use that stale state before normal initialization resets it.

Updating PHP is the only way to regain security. Do it now.

More news.

Good explanations.

Localizing compliance at scale: achieving South Korea’s ISMS certification

Post Syndicated from Kabin Calan original https://blog.cloudflare.com/k-isms/

For ten days, auditors appointed by the Korea Internet & Security Agency (KISA) sat together with us and worked through 80 controls. That is what it took for a company headquartered in the United States, operating a global network serving Korean users, to be certified in South Korea. Cloudflare has now obtained South Korea's Information Security Management System (ISMS) certification under the ISMS-P framework.

For customers in Korea, this is more than a compliance checkbox. It is evidence that Cloudflare's security and privacy program has been examined not only for whether our controls exist, but for how they operate in the context of Korean law, the Korean language, and the particular expectations of Korean regulators.

What a Korean user sees when they sign up

The most visible result of this work is the Cloudflare account sign-up page. In most parts of the world, the line that sits above the sign-up button reads: "By continuing, I agree to Cloudflare's terms, privacy policy, and cookie policy."

A user signing up from South Korea sees something different. The Korean experience is triggered by the country selected at sign-up and by IP geolocation from within South Korea, and it breaks the same agreement into four separately labeled items, each marked required or optional, each linking to its full text, with an option to agree to all of them at once:

  • 모두 동의 (Agree to all)
  • [필수] 서비스 약관 ([Required] Terms of Service)
  • [필수] 개인정보 수집 및 이용 ([Required] Collection and use of personal information)
  • [필수] 제한된 범위의 개인정보 해외 이전 ([Required] Transfer of a limited amount of personal information overseas)
  • [선택] 제한된 범위의 개인정보 제3자 제공 ([Optional] Sharing a limited amount of personal information with marketing third parties)

The three required items are hard gates. The sign-up button stays disabled until all three are checked, so there is no path through the form that creates an account without an affirmative action on each one. The optional item governs marketing permission only, and leaving it unchecked has no effect on the account creation (it merely opts the user out of receiving marketing communications).

The hard part: sign-up paths that never show a form

Itemizing consent on a form we control is straightforward. The difficulty was the sign-up paths that skip that form entirely.

Globally, you can create a Cloudflare account with Google, Apple, or GitHub. Those flows hand the user to an identity provider and return with an authenticated identity, and they never render our own sign-up form, which is precisely where the four consent items live. There is no step in that handoff where we can present three required items, link each to its full Korean text, and require an affirmative action on each before the account exists. The identity provider's screen is not ours to change.

We could either build a separate post-authentication consent gate for one country, or remove the paths that bypass the gate we already had. We chose the second. Social sign-up is not offered in South Korea, so every account created there goes through Cloudflare’s sign-up form, which enforces the required consents.

The country signal is the same one available to any Cloudflare customer. Cloudflare derives a two-letter country code from the client IP address and exposes it on the request, as the CF-IPCountry header at the origin and as request.cf.country inside a Worker. Reduced to its essentials, the branch is a string comparison:

// Illustrative: the shape of the check, not Cloudflare's own dashboard code.
export default {
  async fetch(request) {
    // Two-letter country code derived from the client IP.
    // Same value as the CF-IPCountry request header.
    // Cloudflare's network populates this on the incoming request, so there is
    // no geolocation database, lookup service, or extra round trip of our own.
    const country = request.cf?.country;

    if (country === "KR") {
      return renderSignUp({
        locale: "ko-KR",
        consent: "itemized",  // four separate items, three of them required
        socialLogin: false,   // no path that skips the consent form
      });
    }

    return renderSignUp({ locale: "en-US", consent: "combined", socialLogin: true });
  },
};

What that does not show is why the country code is not the whole trigger. We document the limits of IP geolocation: it is an estimate rather than an exact science, addresses rotate and change ownership, and it should not be the only signal where the use case is critical to meeting the objectives of a local requirement. A Korean resident traveling abroad, or behind a VPN or a mobile carrier's NAT, may not arrive with a Korean address. So IP-based geolocation decides which form appears by default, but the country a user selects at sign-up overrides that and carries the decision from there. The IP address tells us where a request came from; only the user can tell us where they reside. Keeping those two apart is what makes the consent meaningful rather than presumed.

It is a small feature. It took a country-level product decision, and a change to the account creation path.

What ISMS is and why it matters

ISMS is a detailed, localized certification standard. It covers security policy, access control, authentication and permission management, encryption, incident response, risk management, and disaster recovery, all assessed against how personal data actually moves through an organization's systems, and against Korea's Personal Information Protection Act and its associated regulatory guidelines.

Certification requires an independent audit by an auditor appointed by KISA, a governmental institution affiliated with the Ministry of Science and ICT (MSIT), followed by review from a special committee. It is valid for three years, with an annual audit required to maintain it.

The ISMS certification is primarily established under Article 47 of Korea's Act on Promotion of Information and Communications Network Utilization and Information Protection, etc., with the certification criteria and procedure set out in its Enforcement Decree and in the public notification on ISMS certification issued by MSIT.

What the audit examined

Cloudflare is already certified against ISO/IEC 27001, ISO/IEC 27701, ISO/IEC 27017, ISO/IEC 27018 and many other globally recognized frameworks. ISMS does not replace any of them. It is a localization of the same principles, layered with Korean regulatory requirements, and that changes what auditors look for and how they look for it.

The controls in scope started with the review of data flows. We presented detailed data flow diagrams showing every path by which employees could access personal information that Cloudflare collects, processes, and stores. The flows themselves are not Korea-specific. What was different was the form the evidence had to take: the auditors were not willing to work from a narrative description of how data moves, they wanted diagrams they could read and interrogate. For each one, they examined every access control layer and tested its effectiveness, across our internal systems, our public-facing websites, event pages, and the Cloudflare dashboard, covering the full lifecycle of a user's data from first interaction through to destruction. Those diagrams are not published here due to confidentiality.

The audit also scrutinized the language and terminology of our consent collection: the exact wording at sign-up, the structure of each notification, and whether the items were presented separately and clearly. That is the kind of detail the ISMS framework is designed to surface.

Why the timeline ran to a year and a half

Part of the answer is how audit cycles work. An ISMS audit covers a single annual period, and all evidence, documentation, and systems must reflect that period. Our preparation ran past one audit year and into the next, which meant retranslating updated policies for the new audit year, re-collecting and reassessing evidence, republishing an updated privacy policy, and absorbing formatting and design changes our marketing and website teams had introduced in the meantime.

What the certificate covers

KISA defines the certified scope as a service boundary rather than as an enumerated list of in-scope products. The Statement of Scope submitted to KISA describes that boundary in three parts:

  • the organizational and operational perimeter: the Cloudflare entities, teams, and processes that operate the service;
  • the infrastructure perimeter: the network and platform the certified service runs on;
  • the information assets and personal information flows that fall inside the boundary under the ISMS control set.

If a customer-consumed Cloudflare product is delivered through that certified service boundary, meaning it runs on the same certified platform, is operated by the same certified teams, and is governed by the same ISMS, it is covered by the certificate. The certificate is held by Cloudflare, Inc.

That is a different shape from the reports most procurement teams work with. A SOC 2 report or an ISO 27001 certificate describes the system it covers and names the services included, so coverage is confirmed by finding the product in that list. The ISMS certificate carries no such list. Coverage follows the delivery path instead, whether or not a product is named anywhere.

What this means for customers

For organizations operating in Korea, this gives legal, security, and procurement teams a local assurance benchmark alongside Cloudflare's broader compliance portfolio. ISO/IEC 27001 and SOC 2 demonstrate a general security posture. ISMS reflects Korea-specific legal and regulatory expectations. That distinction matters in third-party risk reviews and in preparing for a team’s own compliance assessments.

Cloudflare’s entry can be found on KISA's public register of certified organizations, which is the independent, verifiable confirmation to cite in a risk review. Broader privacy and data protection material sits on the Cloudflare Trust Hub.

The question that usually stalls a vendor review of Cloudflare is whether a particular product in use is in scope. The certificate does not answer that by name, because it lists no products. It answers by boundary, meaning that the product is in scope if it is delivered through the certified service.

For multinational teams managing security across regions, the certification confirms that Cloudflare's program has been reviewed against local requirements in one of Asia's most important digital markets, not just designed for global scale.

Building a better Internet, for everyone

ISMS is not a harder certification than the other assurance audits we go through. It is a more nuanced one. It is built around the regulatory needs of one specific region, and it asks for genuine investment in understanding and embedding those needs, rather than mapping them onto a common control framework.

Going through it made Cloudflare more global, not less. It pushed us to think carefully about what it means to serve users in a specific local context, with local language, local consent expectations, and local data protection requirements, and to put that into how the product behaves rather than only into a document.

That is consistent with what we are working toward: helping build a better Internet for everyone, not just in the regions where regulatory requirements are straightforward, but everywhere.

To learn more about Cloudflare's compliance and assurance programs, visit our Trust Hub.

Професия: Съдебен заседател (първа част)

Post Syndicated from Стефан Иванов original https://www.toest.bg/profesiiua-sudeben-zasedatel-purva-chast/

Професия: Съдебен заседател (първа част)

Преди повече от десет години, на някаква вечеря, чиито подробности отдавна са се изпарили, приятел, който тогава още не беше съдия, спомена мимоходом, че в България има съдебни заседатели. Изненадах се и тази реакция сама по себе си е малък диагностичен материал. Кой не е чувал за съдебните заседатели? Те живеят в романите на Джон Гришам, където адвокатите изучават биографиите им като карти таро, в „Дванайсет разгневени мъже“ на Сидни Лъмет, където един-единствен упорит глас обръща въздуха в задушната от жега и предразсъдъци стая, както и в „Да убиеш присмехулник“ на Харпър Лий – там заседателите се оказват огледало на цял един град.

Познавах институцията „съдебен заседател“ отлично като литература и кино. Само не подозирах, че тя съществува на няколко трамвайни спирки от дома ми.

Българският модел, както постепенно разбрах и не само от Станислав Стратиев, следва друга логика. Американските заседатели се оттеглят сами, за да произнесат „виновен“ или „невинен“, докато съдията чака решението им. Българските седят на една маса със съдията и заедно с него решават всичко. Вината, наказанието и всеки въпрос по делото. Наказателно-процесуалният кодекс им дава права, равни на тези на съдиите. По по-тежките наказателни дела първоинстанционният състав включва един съдия и двама заседатели и при престъпленията, за които се предвижда петнайсет години лишаване от свобода или повече, участват двама съдии и трима заседатели.

Аритметиката е ясна и все пак смайваща. Гражданите в състава винаги са повече от професионалистите. Те гласуват наравно, могат да надделеят над съдията и когато не са съгласни с присъдата, имат право да я подпишат с особено мнение и да изложат мотивите си. Могат да задават въпроси на подсъдимия, на свидетелите и на вещите лица, да се запознаят с материалите по делото и да участват в тайната на съвещанието.

Мандатът е четиригодишен и не може да се заема повече от два поредни пъти. Изискванията са сравнително скромни. Да имаш българско гражданство, да си на възраст между 21 и 68 години, да си с поне средно образование и чисто съдебно минало, с адрес в района на съда и да нямаш психично заболяване. Кандидатите се предлагат от общините и изборът се прави от общото събрание на съдиите от по-горния по степен съд. Цяла малка институционална машина, за чието съществуване повечето хора научават случайно, ако изобщо научат.

С годините разговарях и с други приятели съдии и все по-често стигахме до една и съща мисъл. Институцията „съдебен заседател“ се нуждае от видимост. Тя има голяма сила или поне потенциал за такава, защото е практически единственото място, където гражданинът влиза в съдебната власт отвътре и решава. Парадоксално, най-рядко си спомняха за нея мои приятели юристи. Повечето работеха в гражданското, търговското или административното право и съдебните заседатели просто не попадаха в професионалния им хоризонт. Някои дори искрено се учудваха, сякаш говоря за изчезнал вид.

Мен ме занимаваше и нещо по-лично. Толкова години бях слушал за проблемите на съдебната власт. Протестирал бях пред Съдебната палата, писал бях, изказвал бях мнение и бях подписвал отворени писма и петиции. И все пак

не бях стъпвал в нито една съдебна зала. Говорех за съда така, както човек говори за държава, в която никога не е пътувал.

Бях уверен, използвах източници и цитати, без да знам как мирише коридорът. Не знаех как протича едно заседание, кой къде седи и колко време се чака. Не знаех дори че имам право да бъда там като част от гражданското общество и със законов глас.

Беше още времето около ковид, когато светът се беше свил до екрани и всички решения изглеждаха отложени за неопределеното бъдеще. Исках да направя нещо практическо и конкретно, нещо с адрес, дата и час, колкото и суетно или претенциозно да звучи това днес. Представях си нещо впечатляващо. Тогава отново приятел съдия ми каза, че е открита процедура за нов мандат. Условията бяха делнични. Четиригодишен ангажимент, възнаграждение за всеки ден участие в заседание, никак не високо, и поемане на транспортните разходи. Трябваше да подам автобиография, мотивационно писмо и няколко удостоверения.

Мотивационното писмо е жанр, в който човек неизбежно се разкрива повече, отколкото възнамерява. Само като си помисля, че цитирах Нилс Кристи и Одън, и ме обзема лека неловкост, сякаш съм се явил на събеседване във фрак. Изборът обаче не беше случаен. Кристи, норвежкият криминолог, твърди, че модерната държава е отнела конфликтите от хората, на които принадлежат, и ги е предала на професионалистите – на адвокати, прокурори и съдии.

Съдебният заседател ми изглеждаше като малка, почти символична възможност част от тази собственост да се върне при общността, за да може тя сама да осъществява помиряването помежду си. Одън от своя страна в стихотворението „Подобно любовта“ изрежда как градинари, свещеници, съдии и учени определят закона всеки посвоему, за да се стигне до плахото сравнение от заглавието, когато законът, подобно на любовта, е нещо, което не можем да дефинираме докрай, но сме длъжни да търсим и да пазим. Тогава ми звучеше точно. Днес звучи и малко смешно, което вероятно е най-честната оценка за всяко мотивационно писмо.

После дойде психологическият тест. За първи път в живота ми се налагаше някой да удостовери официално, че съм достатъчно уравновесен, за да преценявам други хора. Първо платих таксата и едва тогава получих документа, което ми се стори точна метафора за отношенията между гражданина и администрацията, където доверието се заплаща предварително. Събрах всичко на хартия, в папка и го занесох там, където трябваше, без онлайн формуляр или потвърждение по имейл, само с печат и входящ номер.

След известно време ми се обадиха. Покана в конкретен ден и час за събеседване. Влязох в сградата притеснен, като ученик преди устен изпит, за който е учил прекалено много. Там ме посрещна чакане. Тогава още не знаех, че това е само първото от дълга поредица чакания. През следващите години се оказа, че да бъдеш съдебен заседател е преди всичко школа по търпение. Чакаш делото да бъде извикано, свидетелят да дойде, вещото лице да представи експертизата си или отложеното заседание да бъде насрочено отново.

В тези коридори времето тече по собствени правила и всеки, който е седял там, знае, че правосъдието има своята бавна, почти геоложка страна.

И все пак, когато погледна назад, не съжалявам за нищо от това, включително за Одън. Съдебният заседател е скромна фигура, без тога и ореол, ала присъствието му в залата напомня нещо елементарно и лесно забравяно. Правосъдието се върши от името на хората и понякога, в най-добрите му мигове, наистина и с тяхно участие. Ако повече хора узнаят, че тази възможност и врата съществува, и решат да прекрачат прага ѝ с повече любопитство и знание, отколкото илюзии, институцията може да се доближи до онова, което обещава. Очакванията ми са скромни и доверието ми е умерено, макар и упорито, че нещата могат да се подобрят.

Какво видях в тези коридори и зад вратите на залите, какво разбрах за съдебната система отблизо, след като години наред я бях съдил отдалеч, ще разкажа в следващите текстове. Обещавам да бъда точен, доколкото позволява тайната на съвещанието, и търпелив, доколкото позволява жанрът. Все пак имах добра школа.

(Следва продължение.)

Поезия и видеоигри

Post Syndicated from Миглена Николчина original https://www.toest.bg/poeziya-i-videoigri/

Иля: Защо да викаш,
докато падаш?
Версо: Сън без завръщане
Светлината угасва
Кокто: Бих взел огъня.

Поезия и видеоигри

Във видеоигрите книгите често функционират като магически предмети: даряват умения или окултни решения на проблеми и катастрофи. Такива книги трябва с кръв и пот да бъдат издирвани из мрачни зандани, подземни лабиринти и крепости, охранявани от отвъдни сили. В поредицата „Древните скрижали“ има и такива книги, но там има и цяла разгърната „световна литература“, в която са представени всички жанрове – художествени или не – и всички народи по тези виртуални земи. Книгите, които са стотици на брой, могат да бъдат намирани, купувани, продавани и – в петата част „Неборъб“ – подреждани в библиотечните шкафове на аватара ни. Те могат да се четат, като допълват знанията ни за света на играта, и понякога наистина си струва да бъдат четени.

В тази игра има и поетически колеж – може да го наречем и певчески в архаичното значение на думата „рапсод“, която обединява музика и слово. За да приемат героя ни в него, ще се наложи да преборим пълчища от задгробни създания и да открием липсващата част от една еда, а тъй като текстът ще се окаже все пак в лошо състояние, ще се наложи и да го допишем…

Накратко, за да оцелява в магически сюжети, на поезията ѝ се налага да полага магически труд. В „Стълбовете на вечността“ например от заклинанията на поета може да излети дракон и да свърши доста полезна работа. Какво се случва обаче, ако напуснем хербаризираната магичност на приказната фантастика и направим стъпка към днешната ни разомагьосана чувствителност, в която мястото на поезията се е свило по кьошетата на „обществата на мъртвите поети“?

Оказва се, че във видеоигрите ще намерим убежища на поезията – в някои случаи ще трябва да ги намерим буквално и точно такива ще са примерите ми тук.

Тайни ключове

Наближавайки финала на „Индика“, играчът безапелационно е пренесен от трето в първо лице – в героинята си Индика. Моментът е напрегнат, тъй като Индика току-що е избягала от затвора и се движи по мрачна кишава уличка. Тя минава покрай човек в очевидно нетрезво състояние, който едва се крепи на крака. Ако спрем Индика за малко до него, ще чуем, че той рецитира стихотворение.

Поради еднолинейната кинематографичност на играта мнозина са се изкушили да заснемат отначало докрай изиграването ѝ. Опитах се да намеря добра версия за приятелка, която не играе, но сред седем-осем (и на руски, и на английски) игрофилма, които прегледах, не намерих нито един, който да е отключил стихотворението. Никой не се е спрял. Всички подминават сгънатия до земята съкрушен човек. Изтръгвано с покъртителни интонации, ту повишавайки глас, ту заглъхвайки, стихотворението невинаги се чува ясно. Да издиря текста се оказа обаче задача само по себе си и ми струва доста усилия. Доколкото успях да установя, то е творба на озвучителя на ролята Сергей Габър.

Стихотворението описва разтеглено във времето падане и като рефрен се повтаря „докато падаш“. Ако трябва да го резюмираме, то ни казва, че падането за някои е полет за други. Стихотворението на руски се изпълнява от озвучителя на Иля, който е вторият важен персонаж в играта. То превежда в думи първите кадри от „Индика“ – и първата задача, която трябва да решим: да преведем силуета на падащо момиченце през златни звездички, като, улучвайки ги, произведем мелодия. Момиченцето (което се оказва фантазия на Индика) сякаш пада, но около него виждаме преобърнати с покривите надолу сгради – може би защото ги виждаме отразени, а може би защото това, което ни изглежда падане, е всъщност полет.

Метафориката на тази първа задача е преведена в текста на стихотворението, като потвърждава двусмисления отворен финал на играта. Може би и двамата герои са паднали (малко след сцената с пияния поет Индика ще се сблъска с Иля, който също е пиян), а може би падането на разговарящата с дявола Индика се е оказало полет, а разговарящият с бога Иля да се е сринал безнадеждно в калта… А може и за двамата да има надежда. А може и за никого да няма надежда и часовниците, които чуваме в последните мигове от играта, да отмерват „времето, което остава“. Стихотворението, колкото повтаря началната сцена с падащото момиченце, толкова и противостои на нейната лекокрилост със своята измъчена, „подземна“, „блатна“ тоналност. Пияният се е сгърчил от другата страна на метална ограда, но като се опитах да заобиколя, за да го срещна, вместо него се натъкнах на друг пиян, вече съвсем изтърколен в снега…

Ключово стихотворение се появява и в „Светлосянка“ и то отново би могло да бъде подминато. Би било задължително намираемо само в естетско-колекционерска линия, чиято задача е събирането на 33 диска с музиката от играта, които дискове след това персонажите могат да си пускат, когато си почиват – тоест задачата е пренебрежима с оглед на сюжета. Числото 33 е значещо за играта по множество начини и отвеждането му към Данте и неговата числова символика е, струва ми се, неизбежно. Въпросното стихотворение звучи на фона на една от песните в играта, съчетавайки гласа на майката Алин, която изпълнява песента, с гласа на сина Версо, който изпълнява стихотворението. Неутешимата скръб на майката по нейния загинал син е в основата на бароковия сюжет на „Светлосянка“, но докато на сюжетно равнище Алин всячески се опитва да задържи сина си във виртуалния „свят на картината“, в тази песен, напротив, тя го призовава да избяга от виртуалния плен и да бъде свободен. Стихотворението, изпълнявано с гласа на Версо, изразява по-скоро невъзможността за такова бягство: любовта е все по-призрачна, рефренът е „светлината угасва“. За него, за тази любов, няма свобода – има край.

Този дует на майка и син, на изпято и оголено от музика слово, действително предлага вход към възела от копнеж и невъзможност, който съставлява бруталната емоционална сила на „Светлосянка“. За разлика от „Индика“, тук стихотворението не е останало незабелязано от колективния nous на играчите: дискутирано е, превеждано е на английски от ентусиасти. Обаче… острова „Бели пясъци“, където дискът може да бъде намерен и стихотворението чуто, и където нищо друго не се случва, аз преживях само като излъчван от белите пясъци глас, рецитиращ стихотворението. Пианото, което го съпровожда, беше изчезнало; песента на Алин беше изчезнала – чувах само стихотворението. Неволно бях възпроизвела разделянето на мелодия от текст, което обрамчва дуета на полет и падане в „Индика“. Сред белите пясъци ефектът на „голото“ стихотворение беше по-малко сантиментален и по мое мнение по-зашеметяващ, отколкото в съчетание с музиката, която все пак чух по-късно. При това въздействието идваше от самия глас, от езика като звук, от ритъма, от диханието, вписано в думите. Нищо конкретно от тези думи не бях запомнила, поради което месеци по-късно се оказах в плен на още една грешка.

Преди да премина към нея, нека повторя тезата си от предходни публикации в „Тоест“:

в игрите не само образът е образдеепространство, но и звукът е деепространствен.

Напълно преднамерено, той е програмиран да бъде част от определена локация или действие, но както двата ми примера демонстрират, и от специфичното движение на играча зависи дали даден звук ще се отвори и с какъв ефект ще се отвори, независимо от относително значителната автономност на музиката на игрите, която може да живее свой собствен живот из концертни зали и на запис, както дисковете в „Светлосянка“ искат да подчертаят.

Грешката е вярна

Тук преминаваме в сферата на сънищата, на собствените или на халюцинациите на ИИ, на форумните импровизации или на интернетските градски легенди. Жан Кокто има стихосбирка със заглавието на играта – „Светлосянка“¹ (първото издание е от 1954 г.). В някакъв момент аз реших – или някъде прочетох – или някъде неточно прочетох, – че едно конкретно стихотворение в този сборник е стихотворението от острова „Бели пясъци“. Не бих се учудила, ако ИИ е подхвърлил тази халюцинация, тъй като издирването на стихотворението от „Индика“ също имаше своите куриозни моменти, когато се наложи да споря, че стихотворението не е изнамереното от ИИ, а ИИ заинатено твърдеше, че е. За жалост, не запазих предложението на машината. Във всеки случай халюцинацията с Кокто, ако е имало такава, е вече ненамираема.

Стихосбирката на Кокто обаче не само предшества заглавието на играта, не само подобно на нея скърби по залеза на поезията, така както играта скърби въобще по залеза на голямото изкуство, но и наистина във въпросното стихотворение сякаш се предлага манифест на играта. Ето го цялото в свободен превод на български:

Кратък е пътят от пламъка до снега,
от червеното до бялото, от бялото до синьото.
Ако пожар изпепели дома ми, какво бих взел?
Бих взел огъня.

Знамена, знамена, сломени от вътрешно поражение,
вие ме затрупвате с дрипите си.
Мъртви знамена, обесени, траурно спуснати,
за това ли отива трудът ни?

Трагедията в играта „Светлосянка“ е предизвикана от пожар, при който Версо загива. Майка му Алин се опитва да го спаси в картина. В играта – с нейните преходи от пламъка до снега и от червеното до бялото и синьото – често стъпваме по победени, стъпкани знамена, особено в една от областите, наречена Забравените земи. В предходните разговори наблегнах върху кахърните аспекти на „Светлосянка“, върху всичките тези траурно сведени знамена като реквием на великата френска цивилизация – най-вече на великото френско изкуство. Двата възможни финала на играта, и двата мрачни, сякаш ни оставят да избираме между реалност без изкуство и изкуство без реалност.

Също така обаче намекнах, че е възможно и позитивно да се погледне на играта като сама по себе си онагледяваща изход с френския си художествен вкус и паметлива естетика: новото тотално изкуство на видеоигрите като превъплъщение на живописта, музиката и скритите ключове на поезията. От пожара

да вземем огъня.

1 Cocteau, J. Clair obscur. Paris: Points, 2003.

В рубриката „Игромислие“ публикуваме разговори, в които се срещат, съпоставят и противопоставят различни гледни точки към многоизмерния, многожанров феномен на видеоигрите – не толкова като електронен спорт, колкото като нов синтез на изкуствата и като ново поле на общуване и социалност.

Using AWS WAF to apply mitigations for PHP2Shell RCE vulnerabilities (CVE-2026-109618 and CVE-2026-109619)

Post Syndicated from Alex Waddell original https://aws.amazon.com/blogs/security/using-aws-waf-to-apply-mitigations-for-php2shell-rce-vulnerabilities-cve-2026-109618-and-cve-2026-109619/

On October 21, 2026, the PHP project released emergency fixes for two critical remote code execution (RCE) vulnerabilities in the PHP core runtime, tracked as CVE-2026-109618 and CVE-2026-109619 and collectively named PHP2Shell. Both are rated 9.2 (Critical) under CVSS v4.0, and both allow an unauthenticated attacker to run code on a vulnerable server. The fixed releases are PHP 8.5.12, 8.4.27, 8.3.36, and 8.2.35.

Patching is the only complete fix, and you should upgrade PHP as your first priority. But patching a fleet takes time: you need to inventory where PHP runs, schedule maintenance windows and test applications against the new builds. This post shows you how to use AWS Web Application Firewall (AWS WAF) to help reduce exposure to the confirmed attack paths during that window. You’ll learn which request patterns to block, how to write the rules in AWS WAFv2, how to deploy them without breaking legitimate traffic and where its protection ends, so you don’t develop a false sense of safety. For how Amazon threat intelligence detected PHP2Shell exploitation before public disclosure, see Amazon Threat Intelligence identifies PHP2Shell exploitation prior to public disclosure in MadPot. For AWS service status and the AWS WAF rule that AWS recommends, see AWS Security Bulletin 2026-143-AWS.

IMPORTANT: Patching is the only complete fix, and you should upgrade PHP as your first priority.


The vulnerabilities in brief

Both PHP2Shell vulnerabilities are unauthenticated RCE issues rooted in how PHP handles multipart/form-data request processing (the request format browsers use for file uploads) before your application code runs, which is why the AWS WAF rules in this post focus on multipart traffic, request body size, and the session upload progress field. At a high level, CVE-2026-109618 corrupts memory when PHP runs out of memory mid-request, and CVE-2026-109619 lets one request leave behind stale data that a later request on the same worker process reuses. For the root-cause analysis, affected versions, and PHP’s own guidance, see the official PHP advisories and release announcement:

Where AWS WAF fits in your response

AWS WAF is a defense-in-depth control in this situation, not a replacement for the PHP upgrade. The PHP advisories are explicit: updating to a patched release is the only complete mitigation. One of the two vulnerabilities is largely outside the reach of any web application firewall, as explained later. Treat the rules in this post as mitigating controls that help reduce exposure while you patch, then remove them or keep them as supporting controls after you’ve patched.

AWS WAF inspects HTTP requests at the edge. It doesn’t parse the internal structure of a multipart body, and it has no visibility into PHP worker memory or server-side configuration. The following table maps each attack element to whether AWS WAF can help mitigate it.

Attack element

AWS WAF coverage

Session upload progress field in a multipart POST (PHP_SESSION_UPLOAD_PROGRESS, the form field that turns on PHP’s upload-tracking feature)

Yes. A targeted rule can block requests carrying that field.

Multipart upload path (multipart/form-data, the request type used for file uploads and the entry point for both vulnerabilities)

Yes, if the application has no legitimate multipart uploads. Block multipart/form-data.

Out-of-memory condition from an oversized body

Partial. Cap the request body size. Doesn’t catch header amplification (many small part headers that cost far more memory to represent than their size on the wire) that stays under the cap.

Repeated attempts against the same worker (the reused PHP process that handles many requests)

Yes. A rate-based rule blunts the volume an exploit needs.

fatal_error_backtraces producer (a PHP 8.5 setting that stores crash-trace state across a request)

No. This is a server configuration setting (fatal_error_backtraces=0).

Invalid or deprecated INI diagnostics as a consumer (warnings PHP raises when applying bad configuration settings)

No. This path runs server-side, not over client HTTP.

Where an application does not accept multipart uploads, an edge rule that blocks multipart/form-data removes the multipart out-of-memory path that works against any application, plus the session-upload-progress trigger, which is a defense-in-depth control during the patch window.

If your application does use multipart uploads, AWS WAF reduces risk but does not close the vulnerability, because header amplification (a few kilobytes of part headers that expand into far more memory inside PHP) stays within size limits and the firewall cannot parse the headers inside individual body parts. In that case, prioritize the PHP upgrade and apply the server-side mitigations described later.

Implementing the AWS WAF rules

The rules below are AWS WAFv2 JSON, deploy each of them on the WAF protection pack (web ACL) associated with the Amazon CloudFront distribution, Application Load Balancer, or Amazon API Gateway stage in front of your PHP workloads.

IMPORTANT: Before implementing any changes, ensure that your WAFv2 logging is setup in line with AWS WAF Logging guidance. Start every rule in Count mode, confirm it does not match legitimate traffic, then switch to Block.


Request body inspection limits

AWS WAF inspects a bounded portion of the request body. On Application Load Balancer and AWS AppSync the limit is a fixed 8 KB. For AWS services such as CloudFront and API Gateway, the default is 16 KB and you can raise it to 32, 48, or 64 KB through the web ACL AssociationConfig as seen below. Any part of the body beyond the inspection limit counts as oversize. Choose the limit that fits the rules you deploy, because a body-size rule can only enforce a cap up to the inspected size.

aws wafv2 update-web-acl ... --association-config \
'RequestBody={CLOUDFRONT={DefaultSizeInspectionLimit=KB_16}}'

AWS WAF Rule

This rule targets both CVEs by blocking a request only when all three conditions in its AndStatement are true at once:

  1. The method is exactly POST – matched on the HTTP method, no transformation.
  2. A PHP session identifier is present (the nested OrStatement, so either sub-condition satisfies this leg):

    • PHPSESSID appears as a cookie key (exact match on the key, scanning all cookies), or
    • PHPSESSID appears anywhere in the request body (contains match).
  3. The body contains PHP_SESSION_UPLOAD_PROGRESS – the form field that activates PHP’s session upload progress feature.

Pair the rule with session.upload_progress.enabled=0 on the server, which turns the feature off.

{
  "Name": "PHP2Shell",
  "Priority": 0,
  "Statement": {
    "AndStatement": {
      "Statements": [
        {
          "ByteMatchStatement": {
            "SearchString": "POST",
            "FieldToMatch": {
              "Method": {}
            },
            "TextTransformations": [
              {
                "Priority": 0,
                "Type": "NONE"
              }
            ],
            "PositionalConstraint": "EXACTLY"
          }
        },
        {
          "OrStatement": {
            "Statements": [
              {
                "ByteMatchStatement": {
                  "SearchString": "PHPSESSID",
                  "FieldToMatch": {
                    "Cookies": {
                      "MatchPattern": {
                        "All": {}
                      },
                      "MatchScope": "KEY",
                      "OversizeHandling": "CONTINUE"
                    }
                  },
                  "TextTransformations": [
                    {
                      "Priority": 0,
                      "Type": "NONE"
                    }
                  ],
                  "PositionalConstraint": "EXACTLY"
                }
              },
              {
                "ByteMatchStatement": {
                  "SearchString": "PHPSESSID",
                  "FieldToMatch": {
                    "Body": {
                      "OversizeHandling": "CONTINUE"
                    }
                  },
                  "TextTransformations": [
                    {
                      "Priority": 0,
                      "Type": "NONE"
                    }
                  ],
                  "PositionalConstraint": "CONTAINS"
                }
              }
            ]
          }
        },
        {
          "ByteMatchStatement": {
            "SearchString": "PHP_SESSION_UPLOAD_PROGRESS",
            "FieldToMatch": {
              "Body": {
                "OversizeHandling": "CONTINUE"
              }
            },
            "TextTransformations": [
              {
                "Priority": 0,
                "Type": "NONE"
              }
            ],
            "PositionalConstraint": "CONTAINS"
          }
        }
      ]
    }
  },
  "Action": {
    "Block": {}
  },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "PHP2Shell"
  }
}

Additional WAF Rules to consider

Block multipart requests when the application has no uploads

NOTE: This rule, if implemented in Block mode, will break applications that require file uploads. If your application does not require file uploads, then blocking multipart/form-data removes the multipart out-of-memory path that works against any application for both CVEs at the edge.

A single named header is inspected in full, with no 8 KB header cap, so matching the Content-Type header is reliable.

{
  "Name": "Block-Multipart-FormData",
  "Priority": 1,
  "Action": { "Count": {} },
  "Statement": {
    "ByteMatchStatement": {
      "FieldToMatch": { "SingleHeader": { "Name": "content-type" } },
      "PositionalConstraint": "CONTAINS",
      "SearchString": "multipart/form-data",
      "TextTransformations": [ { "Priority": 0, "Type": "LOWERCASE" } ]
    }
  },
  "VisibilityConfig": { "SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true, "MetricName": "PHP2ShellBlockMultipart" }
}

Cap the request body size

Capping body size reduces the out-of-memory condition behind CVE-2026-109618 and the stale state it can leave behind. Use OversizeHandling: MATCH with a size constraint so that any body larger than the threshold is blocked, including bodies that exceed the inspection limit. To enforce a cap of N bytes, the web ACL body inspection limit must be at least N. Note that you can’t cap the numeric Content-Length with a size constraint, because the constraint measures the length of the header value string, not the number it contains. If your application has legitimate large uploads, scope this rule to non-upload paths with an AndStatement on the URI path, or it will break those uploads.

{
  "Name": "Block-Oversize-Body",
  "Priority": 3,
  "Action": { "Count": {} },
  "Statement": {
    "SizeConstraintStatement": {
      "FieldToMatch": { "Body": { "OversizeHandling": "MATCH" } },
      "ComparisonOperator": "GT",
      "Size": 8192,
      "TextTransformations": [ { "Priority": 0, "Type": "NONE" } ]
    }
  },
  "VisibilityConfig": { "SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true, "MetricName": "PHP2ShellBlockOversizeBody" }
}

NOTE: if you already have the AWSManagedRulesCommonRuleSet managed rule group, the SizeRestrictions_BODY rule blocks bodies larger than 8 KB by default. If a specific managed rule breaks legitimate traffic, override that rule to Count rather than disabling the whole group.

Rate-limit repeated attempts

A rate-based rule on POST requests can reduce the volume an attacker can send, lowering the possibility that the vulnerabilities can be triggered by overloading the worker, while the stale-state path needs a producer request and a consumer request to land on the same worker. This rule complements a server setting of pm.max_requests=1, which recycles the worker on each request.

{
  "Name": "RateLimit-Posts",
  "Priority": 4,
  "Action": { "Count": {} },
  "Statement": {
    "RateBasedStatement": {
      "Limit": 100,
      "EvaluationWindowSec": 60,
      "AggregateKeyType": "IP",
      "ScopeDownStatement": {
        "ByteMatchStatement": {
          "FieldToMatch": { "Method": {} },
          "PositionalConstraint": "EXACTLY",
          "SearchString": "POST",
          "TextTransformations": [ { "Priority": 0, "Type": "NONE" } ]
        }
      }
    }
  },
  "VisibilityConfig": { "SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true, "MetricName": "PHP2ShellRateLimitPosts" }
}

Server-side mitigations that complement AWS WAF

These host and runtime changes address the parts of CVE-2026-109619 that sit below the HTTP layer a WAF inspects, so they fall outside its scope by design. Apply them alongside the AWS WAF rules as the host and runtime layer of your defense.

  • Upgrade PHP to 8.5.12, 8.4.27, 8.3.36, or 8.2.35. This is the only complete fix. PHP 8.1 and earlier are no longer supported upstream, so check with your distribution or long-term support vendor for a backported fix, or plan a move to a supported branch.
  • Address CVE-2026-109618 at the PHP level. Set memory_limit=-1 so applications cannot override it, and keep post_max_size low (8M where the application accepts no uploads, 32M where it does). Enforce memory bounds through container or cgroup limits, never through RLIMIT_AS or RLIMIT_DATA, which trigger the vulnerable out-of-memory path.
  • Set fatal_error_backtraces=0 on PHP 8.5 and restart every worker. This disables the setting that stores crash-trace state across a request, one of the confirmed ways the vulnerability is triggered.
  • Set session.upload_progress.enabled=0 and restart every worker. This turns off the upload-tracking feature that’s the other confirmed trigger, and is prudent to keep off even after patching.
  • Prefer php.ini, FPM pool, or server startup configuration over per-request INI overrides (settings applied per request through .htaccess, php_value, or FastCGI PHP_VALUE). Remove obsolete directives so they don’t raise diagnostic warnings.
  • Eliminate fatal errors and execution timeouts on attacker-reachable routes, including upload, import, error-page, shutdown, serialization, and extension paths.
  • Set pm.max_requests=1 if performance allows, so each worker process is recycled after one request, which breaks the link between the request that plants stale data and a later request that would reuse it.
  • Turn on error logging (log_errors=On, a working error_log, error_reporting=E_ALL) and review your Apache, FPM, or proxy logs for repeated warnings, deprecations, fatal errors, and timeouts on attacker-controlled routes. The absence of errors is not proof of safety.

Getting started

Complete the following steps to get started:

  1. Inventory where PHP runs and which versions and server APIs (mod_php, FPM, FrankenPHP, LSAPI) are in use. Identify any public endpoint that accepts a request body.
  2. Decide whether each application uses multipart uploads. This determines whether you can deploy the WAF rule to block multipart requests.
  3. Create or update the web ACL in front of each PHP workload and add the applicable rules in Count mode. Raise the body inspection limit on CloudFront or API Gateway if a rule needs it.
  4. Watch the sampled requests and Amazon CloudWatch metrics for each rule. Confirm that legitimate uploads and large JSON POSTs aren’t matched.
  5. Switch the rules to Block after the metrics are clean. Order the priorities so the session upload progress and multipart rules run before the size and rate rules.
  6. Test with a benign multipart/form-data POST, an oversized body, and a request carrying PHP_SESSION_UPLOAD_PROGRESS. Expect a 403 response and the matching rule metric.
  7. In parallel, apply the PHP upgrade and the configuration mitigations. Remove or retain the AWS WAF rules as supporting controls after your fleet is patched.

Conclusion

The PHP2Shell vulnerabilities—CVE-2026-109618 and CVE-2026-109619—are unauthenticated RCE vulnerabilities that reach PHP before your application code runs. AWS WAF gives you a way to help narrow the attack surface during the patch window: block the session upload progress field, block multipart requests where no uploads are expected, cap request body size, and rate-limit repeated attempts. These mitigating controls can help reduce exposure, but they don’t close the vulnerabilities. Upgrade PHP to a fixed release, apply the server configuration changes, and treat the AWS WAF rules as the edge layer that supports those fixes rather than the fix itself.

To learn more about the rule types used here, see the AWS WAF documentation on the web ACL body inspection limit, oversize request component handling, and handling oversize HTTP request bodies. For the vulnerability details, see the PHP advisories GHSA-w8hw-w9fx-j79w and GHSA-6wmf-4rv5-p3rp, and the PHP session upload progress manual.

Alex Waddell

Alex Waddell

Alex Waddell is a Principal Solutions Architect at AWS specializing in security within the Worldwide Specialist Organization, based in Scotland. Alex has been working in the security domain since 1999 and joined AWS in 2021 to work with customers across EMEA on cloud security architecture, identity, threat detection and application security. When he is not working, Alex enjoys spending time sampling rum from around the world (Alex is one of those rarely found Scottish people that doesn’t like whisky), walking his dogs in the local forest trails and traveling.

Lawton Pittenger

Lawton Pittenger

Lawton is a Worldwide Security Specialist Solutions Architect at AWS, based in New York City. He specializes in helping customers design and implement effective network security controls. At AWS, he works with customers at scale and collaborates closely with service teams to drive continuous improvement in security services based on customer needs and feedback. Outside of work, his interests include skateboarding, snowboarding, and spending time in nature.

Ian Olson

Ian Olson

Ian is a Senior Security Specialist Solutions Architect at AWS. He helps
customers automate security services to safeguard against threats like
DDoS and web exploitations. Through intelligent automation, he delivers
security solutions tailored to organizations of any scale. When he’s not
working, Ian enjoys spending quality time with his two young children.

[$] LWN.net Weekly Edition for October 22, 2026

Post Syndicated from jzb original https://lwn.net/Articles/1100612/

Inside this week’s LWN.net Weekly Edition:

  • Front: Android vendor hooks; Reproducible builds and kernel integrity; Rust data structures; NFS server changes; Setting no_new_privs for PID 1; Rust XArray; Rust cross-crate declarations; 7.3 statistics; Nix flakes.
  • Briefs: eMudhra CA compromise; PHP RCEs; Node.js and musl vulnerabilities; GNOME OS; OpenBSD 8.0; Ubuntu 26.10; TAB results; Quotes; …
  • Announcements: Newsletters, conferences, security updates, patches, and more.

The collective thoughts of the interwebz