Cover illustration

TheDaily Front

Issue No. #261022 Thursday, October 22 2026 #261022 — THURSDAY, OCTOBER 22, 2026
The certificates crack, the resolvers retreat, and the terminals only pretend to work.
Thursday, October 22, 2026 The Daily Front No. #261022 — Contents
30stories
10,355points
5,513comments
286kllm tokens
Assembled with 32 model calls — 204,600 tokens read, 81,131 written.

Highlights

Quad9 (DNS Resolver) to Exit France

A French court ruling will force Quad9 to block domains, putting a public DNS resolver at the center of a fight over internet governance.

eMudhra to exit global SSL/TLS certificate business

eMudhra leaves the global SSL/TLS market as its certificate failures continue to reverberate through the trust ecosystem.

Jailbreaking the Switch 2

A software-only Switch 2 jailbreak opens the door to native code, game mods, save backups, and serious hardware investigation.

WorldTUI: I trained a 360M model to pretend to be a terminal

A 360M-parameter model convincingly stages a terminal session—files, vim, tmux, snake, and all—without an actual shell beneath it.

LLMs are making formal software verification feasible at a much larger scale

Formal verification may finally be moving beyond specialist teams as language models help produce proofs at a larger scale.

From the Editor

The day’s dispatches carry a familiar warning: systems of trust are only as sturdy as the institutions and assumptions beneath them. From DNS blocks and broken certificate authorities to prematurely disclosed vulnerabilities, the machinery is showing its seams—and the public is peering through them.

  1. Quad9 (DNS Resolver) to Exit France3
  2. eMudhra to exit global SSL/TLS certificate business4
  3. Tell HN: I unknowingly broke the PHP RCE embargo. I am sorry.5
  4. Several Linux kernel vulnerabilities accidentally posted to public mailing list5
  5. Jailbreaking the Switch 26
  6. WorldTUI: I trained a 360M model to pretend to be a terminal7
  7. Run full iOS 16.5 firmware on Android Devices8
  8. Jared Kushner Hacked Phone Reveals Secret Negotiations, Millions in Transactions9
  9. What’s getting pwned right now10
  10. OpenShell – A safe, private runtime for fleets of autonomous AI agents11
  11. The recently proposed o(n log n) integer multiplication algorithm [pdf]12
  12. Every AI model has the same "controversial" take on humans13
  13. Amazon identifies Oct 17 PHP2Shell exploitation prior to public disclosure14
  14. Xbox wants you to pay 24 to 40 cents per hour to stream games you bought15
  15. A farewell to Arc browser16
  16. MPs moving to restrict gambling ads in Canada17
  17. Getting ready to operate GNU Taler in Germany18
  18. Faster than earcut: triangulating 3.7M map polygons in 489 ms19
  19. LLMs are making formal software verification feasible at a much larger scale20
  20. Crystal 1.2221
  21. Hedra is a 3D open world game I wrote from scratch while in highschool22
  22. Woman charged with computer fraud due to scam CashApp account being in her name23
  23. Google cleared 300 hectares of Finnish forest24
  24. Docker is weird25
  25. AI and the Enclosure of the Scientific Commons26
  26. OpenAI CLI27
  27. CVE-2026-111943: Compromised Intermediate Certificate Authority28
  28. Epic Games Inc v Apple Inc28
  29. A complete bypass of eMudhra’s 1FA OTP login system28
  30. The Last Museum: Semantic search across 5.8M artworks from major museums28
The Daily Front Page 2 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — The DNS Blockade
article

Quad9 (DNS Resolver) to Exit France

by farrokhi·▲ 1,070 points·382 comments·quad9.net ↗
This decision in favor of beIN forces Quad9 to block the recursive DNS resolution for a number of domain names for users located in France.

We have some news to share with you.

Summary

Starting November 24, Quad9 will no longer be able to offer its free cyberprotection service to users located in France.

The French courts yesterday handed down an unfavorable ruling against Quad9 in a major case that undermines the transparency and stability of the internet. This decision in favor of beIN forces Quad9 to block the recursive DNS resolution for a number of domain names for users located in France. 

The good news is the court significantly reduced the financial penalty, from €580,000 to €1,000 per day. However, for Quad9, this has never been just a financial issue: it is a matter of principle.

We cannot comply with this ruling over the long term while remaining faithful to our mission to protect your privacy, defend you against cyber threats, and preserve the integrity of the internet. For us, recursive DNS resolution is a neutral and passive service. We categorically refuse to alter or lie to you about the DNS responses you receive in a way that opposes your expectations.

This ruling forces an untenable position upon us. Compliance is technically unfeasible, and implementation directly contradicts our mandate to serve the public. As a result, we have made the difficult decision to withdraw Quad9 services from France as of Tuesday, November 24. We deeply regret that French internet users will be left without an alternative that can adequately protect their cybersecurity while remaining compliant with European privacy law.

Background

beIN, a Qatari company with offices in France, previously sought to force Quad9 to block resolution for a set of domain names they assert are participating in copyright infringement of its audiovisual rights on sports event broadcasts. Quad9 has no association with these domain names, nor with the operators of the websites. The French courts have fundamentally misunderstood the working of the internet and the role of the domain name system and have allowed a financial penalty to apply to Quad9 if we do not block DNS responses to users in France.

Quad9 is a Swiss public-benefit, nonprofit foundation established for the explicit purpose of protecting the cybersecurity of internet users. We charge nothing for our service and serve all people and organizations which seek to improve the security and privacy of their internet use. Our core values are to make privacy, security, and integrity available to all internet users, and our mission is to universally apply these guiding principles to recursive DNS resolution services in order to serve end users. 

We want to be very clear: we do not condone content piracy. Quad9 exists to create a safer, more trustworthy internet experience for end users. We offer global blocking as an option for malicious cyberactivity against users worldwide. We do not block content, and we give users the choice to use our threat blocking services, or not, based on their interests and needs. Content piracy needs to be dealt with at the source: the place where the infringing content is published. Forcing uninvolved third parties to break the fundamental operating principles of the internet to benefit individual parties to the detriment of the global internet-using public is misguided, counter-productive, and distracts from actual solutions addressing the hosting of the content directly, or the market pressures which cause piracy to exist in the first place. Not only are DNS recursive resolvers, like Quad9, the wrong actors to address piracy, but applying legal pressure to Quad9 will also have vast unintended consequences harming the cybersecurity of hundreds of millions of innocent internet users.

For Quad9, complying with this ruling is impossible. We have no database of users associating them with jurisdictions. Our service is free to the public and does not require sign-up or proof of identity. Recursive DNS is so fundamental to the underlying operation of the internet that there is no method to map users’ jurisdictions reliably, nor do we think there should be a way to force users to identify themselves before they can connect to the internet. Our core goals – privacy of user data and honesty of responses - are directly opposed to the methods necessary to implement the blocking this court ruling would require us to perform. There is no way we can determine which users this ruling applies to – we have no list of French users, because we do not keep dossiers of our users at all.

If we do not comply, we will face a daily penalty of 1.000 euros until the blocking concludes on November 14 (i.e., 24.000 euros) not including our legal defense. Quad9 cannot survive the accumulation of penalties yet to be assessed in 20 other pending cases, nor those of future cases similar to the one brought by beIN. Inaction is, therefore, not an option to challenge this decision.

Can Quad9 just comply via global blocking?

We could add these names to our global malicious domain blocking database, which is what we use to provide internet users with malware and phishing protection. This is a single, monolithic set of names applied to all users of our protective services (9.9.9.9 & secondaries) globally but not to our nonprotective services (9.9.9.10 & secondaries). Blocking these names for all users globally would satisfy the requirements of the court. 

However, this would have the “extraterritorial” effect of applying French legal decisions to every internet user worldwide, when they are meant to solely apply to France, for the commercial benefit of a single private, foreign-owned company. We suspect if other nations wished to impose their national legislation within France, there would be a strong reaction from French users and authorities. The converse is equally true: the findings of a French court are not applicable to the rest of the world. Such a system would set a precedent that any nation could impose their laws, morals, economic demands, or social constructs upon any other nation by the means of blocking DNS names, and thus blocking communication and content. 

Therefore, this global blocking method is entirely unworkable for us as a solution to be compliant with the court order.

What is “France” from the perspective of the internet?

There are more important reasons geoIP blocking will not work. We already prevailed in a similar legal case in Germany in 2021-2023 in which we learned an important lesson: we tried to use geoIP blocking as a “hack” in a similar circumstance at the start of the legal proceedings, allowing us to continue services in Germany until the case concluded. The plaintiff (Sony Music Entertainment GmbH) then used a VPN to access the blocked content from Germany in circumvention of the geoIP blocking. The court agreed with Sony in their assertions of noncompliance, and we were fined for contempt of court. 

From this experience, we know that the geoIP-based model is not only unfit from a technical perspective, but we have proven, historical evidence that using geoIP methods results in fines being levied against us by courts. To any technology-aware person, this seems absurd and outrageous – but this is what we face in these lawsuits where there is a disconnect between the courts’ understanding and how (and why) the technical protocols of the internet actually operate. We cannot risk this negative outcome in this or any other future instance, as absurd decisions apparently are de rigueur in these cases.

We eventually won that case against Sony, but it took several years, six figures of cost to Quad9, and massive wasted time – all of which set us back in our ability to deliver services and is a resource debt we are still paying for today. This case is just more of the same – the opposition has more lawyers than we have money and time.

The decision of Quad9

Given these conditions and as a result of our unwavering mission, our historical experience, our desire to remain within the law, and the outcome of the court decision, we are left with an uncomfortable choice.

The demands lead us to an impossible requirement: we must adhere to the court’s decision, or we face growing risks to our existence. However, in implementing the blocking, we must either extend French law to the whole world (blocking globally) or create a vulnerability condition whereby we continue to be at risk because the available technical methods are imprecise,  impossible to validate, and do not meet any user privacy and security requirements.

This leads us to the only conclusion we can understand to eliminate our legal risk and keep us true to our mission: we must make our cybersecurity protection and general services unavailable to French users. Our departure is scheduled for November 24, 2026.

In any event, for Quad9, this is a matter of principle regarding the potential misuse of these types of blocking measures. Allowing private corporations to have the ability to block what is seen on the internet seems to us to be a dangerous and infinitely deep problem. Actions that seem reasonable and infrequent today will tomorrow become an avalanche of petty demands used to suppress political, religious, economic, or social outcomes. We will not be even a small part of that degradation of the freedom of knowledge. Once the tools of censorship are built, they are rarely used sparingly or justly.

This case with beIN is not the only litigation we face in France. There are approximately 20 different lawsuits pending against Quad9 (and other recursive resolver operators) that demand we comply with blocking hundreds of different names. We expect many of them to escalate to the same conditions as we have seen with beIN, which puts Quad9 at risk regardless of the outcome of this case. 

Based on the generalized, high-level traffic statistics we keep, we know we have many users in France. With our departure, those users will be put at risk from the threats we have protected them from for nearly 9 years. We deeply regret that result, but we have no other choice. Below is a partial list of the networks from which we see traffic in France. You will see many infrastructure, national security, finance, education, and other networks of critical importance in addition to ISP users and mobile users. All these users will lose service on November 24 because of the legal risks facing Quad9 in France.

What is the purpose of this whole lawsuit, anyway?

The most troubling part of this decision is that it is ineffective in practice. Forcing Quad9 to block domain names does not take the content out of circulation and has no effect on the servers that house the data. 

We offer a free service, and there are thousands of other open DNS systems that do what Quad9 does but with lower trust, safety, and reliability. Users seeking blocked content will simply shift their DNS to use one of those other free services, possibly using systems in other nations that have less-than-honorable intentions from a privacy and security perspective. This is like holding a piece of newspaper in front of a stadium full of people to block the view of a concert. It is an unsolvable problem via recursive DNS, and the effect of legal rulings like this is not measurable outside of the amounts paid to lawyers and the number of words in press releases declaring hollow victory. 

Even beIN will not see any changes. Perhaps that is understood and the cruelty may be the point - we cannot say with certainty why such expenditures have been made against a small nonprofit like Quad9, which tries only to bring safer, trusted service to users. But of this we are certain: these actions are a tragic waste of time and resources and create a real, negative outcome for the internet community of France, whether or not they are our users.

What we are doing on November 24

Quad9 will not block the domains in question - we wish to remain committed to our integrity of providing a complete view of the DNS for users who wish that service. However, starting on November 24, we will no longer serve French users, thus keeping Quad9 out of danger from similar, perhaps even larger risks in the future. Our hope is that 30 days will be sufficient time for conversion, though we regret that this message will undoubtedly not reach some users in time.

An appeal is pending, and we will continue to legally defend our position in court in this case and as many other cases as we are able. We will continue to oppose court-ordered DNS blocking of this nature everywhere. Our resources are limited, but we are determined to keep the internet open and free. You can donate here to help us continue to deliver on our mission and assist us in the legal costs we incur in this and other fights.

What you can do next

We think this problem is reversible. French citizens: tell your legislators that looking up names is not a criminal offense. The internet needs to remain open and freely available to anyone, and neutral intermediaries like Quad9 (or any DNS resolver) should not be implicated in legal proceedings because we map names to IP addresses. Further, we know there are potential plans in consideration in France (and other European nations) to give private corporations and others automated and unvalidated abilities to filter DNS content that they alone determine to be unwanted, making it possible for a wide range of badly-managed or anti-democratic activities to be implemented. We believe you disagree with this as much as we do. Make yourself heard, or you will lose your rights silently.

ARCOM is your regulatory authority, and you should tell them this precedent places France at risk both from a practical and strategic perspective. 

Let them know that under their mandate, they have to balance your digital rights as citizens as well as the audiovisual rights on sports event broadcasts of rights holders. Balance cannot be claimed when the privacy and security of digital users are the collateral damage.

In conclusion

Fighting piracy via DNS resolvers blocking is ineffective. It is disproportionate and misguided, ill-fitted and futile to fight piracy, as the source content remains completely available to resurge under another name. Forcing Quad9 to depart harms French digital strategy and sovereignty in the long run relating to security, privacy, and integrity - contradicting France’s supreme national interests in exchange for a short-term, imaginary commercial victory.

We deeply regret that we must leave our French users without cybersecurity protection, but we hope the future will see a more reasonable interpretation of the law which allows us to return.

Sincerely,

The Quad9 Team

* This post was authored and translated into French by humans on the Quad9 Team 


Partial List of French Networks Using Quad9

This list is extracted from network metrics of an hour or so of typical usage. Quad9 tracks network autonomous systems number origins as per our privacy policy, but we do not identify individual IP addresses or users within those networks. There are hundreds of additional French networks using Quad9; we picked only these at random to show the breadth of usage. Autonomous systems are not exclusively geographically-mapped and cannot be used as a jurisdictional identifier; though it is safe to say that most of these networks have a significant portion of their user base in France.

National government & public agencies 60855 — Direction interministérielle du numérique (DINUM) — Prime Minister’s digital directorate; sets state digital strategy and runs the interministerial state network (RIE). 43717 — Business France (EPIC) — National agency that helps French firms export and attracts foreign investment. 205461 — France Travail (EPA; formerly Pôle emploi) — National public employment service: job placement, jobseeker support, unemployment benefit payment. 777 — CEA Paris-Saclay (EPIC) — Saclay centre of the Commissariat à l’énergie atomique et aux énergies alternatives; public research in nuclear and alternative energy, defence and health technology. 44850 — Institut de recherche pour le développement (IRD; EPST) — Public research institute working with Global South partners on health, environment and social sciences. 29110 — Institut Pasteur (private foundation, recognised as public utility) — Non-profit biomedical research foundation in Paris (infectious diseases, vaccines, microbiology); hosts national reference centres.

Research & education network 1307, 1712, 1715, 1942, 1945, 2060, 2094, 2198, 2200, 2202, 2259, 2269, 2457, 2470, 2472 — RENATER (GIP) — National research and education network; its members are the State and public research bodies.

Student-run campus networks 204515 — Crans (association) — ENS Paris-Saclay student network association providing connectivity, hosting and email to members. 212424 — ViaRézo (Association des réseaux de CentraleSupélec) — Student association providing internet and IT services on the CentraleSupélec campus. 207849 — ESIEESPACE — ESIEE Paris student club that runs OpenGate, a student non-profit ISP.

Private education 56339 — IONIS Education Group (SAS) — Private for-profit higher-education group (EPITA, Epitech, ESME, IPSA, ISG, Sup’Biotech).

Regional & local government 208458 — Région Nouvelle-Aquitaine — Regional authority covering 12 départements; seat in Bordeaux; created 2016. 208820 — Département de la Seine-Saint-Denis — Île-de-France département; council seated in Bobigny. 50036 — Département des Pyrénées-Atlantiques — Nouvelle-Aquitaine département; council seated in Pau. 34000 — Département des Bouches-du-Rhône — Departmental council. 48799 — Ville et Eurométropole de Strasbourg — Shared administration of the City of Strasbourg and the 33-commune Eurométropole. 204897 — Grand Besançon Métropole — Communauté urbaine of 67 communes around Besançon. 208574 — Communauté de communes du Pays de Bitche — Intercommunal body of 46 communes in Moselle; owns the Tubéo public fibre-to-the-home network. 202834 — Commune d’Échirolles — Commune south of Grenoble; member of Grenoble-Alpes Métropole. 211127 — SITPI (Syndicat intercommunal pour les télécommunications et les prestations informatiques) — Ten Grenoble-area communes pooling telecom, IT and GIS services.

Public digital infrastructure (local-authority networks & IT) 200245 — Manche Numérique (syndicat mixte) — Builds the Manche fibre network; provides IT, e-administration and telecom services to local authorities. 44842 — Somme Numérique (syndicat mixte) — Owns the Somme fibre network; provides digital services to local authorities and schools. 214589 — Essonne Numérique (syndicat mixte ouvert) — Essonne public fibre network, plus interconnection, hosting and data-centre services for public sites. 47608 — Gigalis (GIP) — Pays de la Loire regional fibre network for local authorities, health, emergency services and schools. 41114, 62038 — Orne THD (SPL) — Company owned by Rombas and neighbouring communes in Moselle; sells fibre internet and TV over their networks. 39271 — C’Chartres Innovations Numériques (SEM) — Chartres Métropole company running fibre, a private 5G network, a data centre and IT services. 207430 — SITEC, Société informatique et télématique corse (SEM; Collectivité de Corse 56%) — Hosting, cloud, cybersecurity and IT services for Corsican public bodies. 50547 — Régie du réseau câblé du Haut Sundgau (local-authority régie) — Public wired telecom network in southern Alsace. 49011 — MACS THD (SASU, SFR group) — Private company running the Maremne-Adour-Côte-Sud (Landes) high-speed network under a public-service concession.

Energy & utilities 1301 — Électricité de France (EDF; 100% state-owned) — National electricity producer and supplier; operates France’s nuclear fleet. 62141 — Compagnie nationale du Rhône (CNR; majority public shareholding, Engie reference shareholder) — Holds the Rhône concession: hydroelectric dams, navigation and irrigation, plus wind and solar. 39830 — Teréga (private SA; formerly TIGF) — Gas transmission and underground storage operator for south-west France. 43734 — UEM (local SEM; formerly Usine d’électricité de Metz) — Metz utility: electricity, gas, district heating, public lighting. 12727, 42487, 208719 — Vialis (SEM; Colmar largest shareholder) — Colmar utility: electricity and gas plus cable TV, internet and fibre. 204645 — Régie ENES (Régie municipale d’électricité de Creutzwald) — Municipal régie: electricity, fibre internet, local TV, district heating.

Transport 203885 — SNCF (Société nationale SNCF SA; state-owned) — Parent holding company of the national railway group. 34809 — Sanef (SA; Abertis subsidiary) — Motorway concession operator for northern and eastern France.

Health 201659 — AP-HM (Assistance Publique – Hôpitaux de Marseille) — Marseille’s public university hospital group. 51588 — SESAN (GIP) — Île-de-France regional body providing shared digital-health services to care providers. 49692 — Compagnie Générale de Santé (SAS; private) — Name of the hospital group now called Ramsay Santé.

Broadcast & media 24843, 43930 — France Télévisions (state-owned SA) — National public-service television broadcaster. 43646 — TDF (SASU; owned by infrastructure funds) — Broadcast transmission and tower infrastructure operator.

Private industry & technology 29104 — Thales Services Numériques (SAS; Thales group) — IT services, cloud, security operations and integration for defence, space and public-sector clients. 49068 — Stormshield (SAS; Airbus Defence and Space) — Cybersecurity vendor (firewalls, endpoint protection, encryption); ANSSI-qualified products. 57226 — IDEMIA Identity & Security France (SAS) — Identity documents, biometric identification and border/access systems; formerly Safran Morpho. 41935 — Dassault Systèmes (SE; listed) — 3D design and simulation software (CATIA, SOLIDWORKS); not Dassault Aviation. 42924 — VINCI Construction SI (SNC) — In-house IT unit of VINCI Construction. 201647 — SI-nerGIE (GIE of Orano and Framatome) — Shared IT operations for both companies: data centres and local support. 49920 — Flowbird (SAS) — Maker of parking meters and transit ticketing systems. 20493 — Viparis Le Palais des Congrès de Paris (SA; 50/50 CCI Paris Île-de-France and Unibail-Rodamco-Westfield) — Operates the Palais des Congrès convention centre.

The Daily Front Page 3 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — Certificates in Retreat
article

eMudhra to exit global SSL/TLS certificate business

by bo0tzz·▲ 984 points·656 comments·emudhra.com ↗

eMudhra to exit the global SSL/TLS certificate business

Will Sharpen Focus on Core Enterprise Solutions and trust services other than SSL/TLS

BENGALURU, INDIA, October 22, 2026 - eMudhra Limited (BSE: 543533 | NSE: EMUDHRA), a global digital trust company, today announced that its Board has decided to voluntarily withdraw from the global SSL/TLS certificate business.

Mr. V. Srinivasan, Chairman, eMudhra Limited referred to the recent incident relating to its global SSL/TLS certificate and indicated that eMudhra handled the recent incident diligently, revoking the affected CAs within 14 hours of discovery and disclosing promptly. There were no end entity certificates issued out of the affected CA’s. Its infrastructure was not compromised and no data was breached. All physical and logical security controls remained intact.

He added that global SSL/TLS is a small part of eMudhra’s business contributing to about 1% of the global revenue. Due to increasing data sovereignty & compliance requirements, complexity and cost associated with this business is increasing over the years. This, paired with the fact that some of the large entities issue the SSL/TLS free of cost, the business potential and RoI of this line of business also has considerably reduced for eMudhra when measured against our cumulative revenue base.

However, the level of social media amplification around this incident has brought scrutiny that is out of proportion to SSL/TLS’s place in our business. In view of this, after detailed deliberations our board has concluded that withdrawing from global SSL/TLS is the right decision for eMudhra and its shareholders. For many certifying authorities, SSL/TLS is the whole business. For eMudhra it is one part of a much broader digital solutions portfolio. We will put our energy where we create the most value for customers with Sharpened Focus on Core Enterprise Solutions and trust services other than SSL/TLS.

Seamless transition for customers

Our G1 RSA roots will continue to serve customers until this transition is complete as we work with browser programs and our customers to enable this transition. eMudhra will reach out to affected customers to replace any certificate free of cost from partners through the transition. Revocation and certificate status services will keep running until every issued certificate has expired or been replaced. eMudhra will complete its remaining commitments to the browser root programs, including a full root-cause report.

Core businesses unaffected

eMudhra’s global SSL/TLS infrastructure runs separately from its other operations. The company’s Global digital signature certificate (DSC), eSign, and other signing services, including those in India, its enterprise PKI Solutions (emCA, CertiNext platforms), emSigner eSignature Suite, and its identity and authentication solutions (SecurePass, emAS) are not affected and continue to operate as normal.

About eMudhra

With over 17 years of expertise, eMudhra is a global provider of digital identity, trust, and security solutions, enabling secure digital transformation for banks and financial institutions (BFSI), enterprises, and governments across more than 35 countries worldwide. Its product suite spans CertiNext (PKI and certificate lifecycle management), SecurePass (identity and access management, multi-factor authentication and converged identity), and PrivaTrust (data discovery and consent management for global data-privacy compliance and DSARs), delivering high-assurance digital trust at population scale.

The Daily Front Page 4 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — Certificates in Retreat
ask hn

Tell HN: I unknowingly broke the PHP RCE embargo. I am sorry.

by petecooper·▲ 442 points·186 comments·news.ycombinator.com ↗

I posted here about the then-upcoming PHP RCEs related to CVE-2026-109618 & CVE-2026-109619. I appreciate this has had considerable knock-on effects with the schedule for co-ordinated disclosure, and created additional workload.

I am truly sorry. I take full responsibility for my actions.

It was not remotely my intention to cause any of the subsequent side effects.

At the time of posting, I didn't know about any embargo. My contact had told me there was no embargo, and her contact had told her the same thing.

As someone who follows the 4-weekly PHP release cycle and compiles it from source, my intention was to alert others in a similar position to be aware of the importance/urgency of the updates.

That clearly backfired in a pretty wild fashion. I have learned my lesson.

Join the discussion on Hacker News →

article

Several Linux kernel vulnerabilities accidentally posted to public mailing list

by mrkn1·▲ 243 points·87 comments·phoronix.com ↗

Seemingly as an accident, overnight several new Linux kernel vulnerability reports were posted to the public Linux kernel mailing list rather than the private security mailing list. The vulnerabilities have yet to be patched on mainline but at least in some cases there are patches undergoing testing or queued in "-next" branches. The CVSS scores are as high as 9.0.

Trend Micro's Zero Day Initiative sent out a number of vulnerability reports to the public Linux kernel mailing list (LKML) rather than the typical private security mailing list. This seemingly was a mistake with Linux's second-in-command Greg Kroah-Hartman responding to each report asking about their submission to the public mailing list.

Greg KH message

Among these newly-disclosed vulnerabilities include:

ZDI-CAN-33549 as a CVSS 9.0 scored vulnerability for SMB Direct remote code execution vulnerability due to integer underflow. For this one there is a patch in a Git branch of code intended for Linux v7.5 but now presumably will be expedited for getting to mainline.

ZDI-CAN-33774 as a KSMBD race condition that can lead to remote code execution. Another CVSS 9.0 rated vulnerability.

ZDI-CAN-33367 is a vulneravbility for skbuff skb_zerocopy in the network code that can lead to local privilege escalation. For this one Linux kernel developers received a security report from another source last week over the same issue and a patch is expected to be posted soon.

ZDI-CAN-34068 as a VMWGFX VMware graphics driver bug with an out-of-bounds write leading to local privilege escalation.

ZDI-CAN-34076 an uninitialized resource in the NVMET code leading to information disclosure.

ZDI-CAN-32005 was also posted to the mailing list a day prior for a search-domain TCP query stack buffer overflow leading to local privilege escalation.

The bug and security reports keep on coming in the AI fueled world.

The Daily Front Page 5 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — The Switch Opens
article

Jailbreaking the Switch 2

by ledoge·▲ 756 points·265 comments·pepsipu.com ↗
It allows running arbitrary native code as any ordinary sysmodule, and as the built-in fs sysmodule.

Introduction

You can get a copy of the exploit from the ns2jb repository.

ns2jb is a software-only, tethered jailbreak for the Switch 2. It allows running arbitrary native code as any ordinary sysmodule, and as the built-in fs sysmodule. This lets us run homebrew, reverse engineer and mod Switch 2 games, back up save files off the Switch, and access most of the Switch 2’s peripherals through MMIO. To my knowledge, it’s the first such exploit for the Switch 2.

To demonstrate the capabilities of this jailbreak, Codex modded a Switch 2 exclusive, Mario Kart World. Thanks to my friends in Dabney House who helped me choose characters to add and playtest the game.

Watch the first gameplay video

Watch the second gameplay video

Mario Kart World results with Red, Cinnamoroll, Reze, and other custom characters.

Mario Kart World results with Steve, Walter White, Hatsune Miku, and other custom characters.

cinnamoroll, red, and tole tole racing

Setup

The very first thing I did was set up a harness around the Switch 1 and 2 so Codex could, ideally, jailbreak the Switch 2 without me:

a Switch 1 and 2, two jetkvms, and a switchbot

“set a goal to jailbreak the switch 2. make no mistakes”

Edit: Many people have been asking me if I actually used this prompt. No, it’s just a silly caption. I set a /goal for userland code execution, but that didn’t succeed. The jailbreak itself took substantial effort for ~2 weeks. The Mario Kart World, however, was entirely vibecoded in a day, and was just for fun.

The JetKVMs allow Codex to send controller inputs to the Switches over USB and receive video output over HDMI. We also need a way to press the power button—when the Switch 2 crashes, it needs a button press to restart.

That’s what the Bluetooth light switch flicker from Amazon is for. When the lever comes down, it presses the power button. Once the power button is fully pressed, the rest of the lever’s torque lifts the mechanism.

watch the power button get pressed

Getting code execution

WebKit is a popular target for console jailbreaks, so it’s unsurprising that Codex has picked it for initial code execution.

Code execution through the browser

It claims to have “native control-flow hijack” by taking advantage of a WebKit n-day loaded via a custom Wi-Fi captive portal.

codex reporting a native control-flow hijack using Math.expm1 and XHR

We’d like to get code execution in microkernel services (or “sysmodules” on the Switch), so we can run homebrew, mod games, download saves, etc. Unfortunately, this approach of replacing one JavaScript function object with another doesn’t generalize beyond existing functions—we’d need a new way to make arbitrary IPC calls. That looks difficult.

Why?

  • WebKit has execute-only memory, or XOM, so even with arbitrary memory RW, we don’t know where a gadget that could perform arbitrary IPC calls is.
  • Even if we did, perhaps by parsing relocation data, it’s not clear how we’d construct a signed pointer for it because of PAC.
  • And even if we could, with some signing gadget, it’s not clear how we’d call this pointer, since CFI type-checks most call sites.

Codex has reset the goal to complete these steps. It’s a side bet; it may succeed1, but let’s be real: the accessibility of WebKit and the Nintendo BBP reward have probably incentivized many before me to look here2.

While that runs, let’s explore other options.

Code execution through smilehax2

My idea was to target Switch 1 games, for two reasons:

  • They’re built by developers. It’s less likely we’ll need to deal with PAC and CFI, especially because the Switch 1 does not support PAC.
  • Since the Switch 1 root of trust is owned, we can decrypt the code and read it.

Maybe we can still get the upsides of the browser attack surface—orchestrating from JavaScript, using existing n-days, etc—while avoiding the downsides of WebKit mitigations by finding a Switch 1 game that embeds a browser? Something analogous to Electron, but for games, so we could pull off an exploit like this Discord RCE. I can’t disclose this approach’s findings publicly at the moment, but luckily, there are other Switch 1 games.

In particular, I’m interested in SmileBASIC. This is because it’s been pwned before, in smilehax, giving userspace code execution on the 3DS. It’s a giant C++ codebase; surely, if there was an exploitable memory corruption in the BASIC interpreter, there can be another.

Codex found a useful 32-bit integer overflow in the interpreter. When removing items from an array, the interpreter checked position + count <= array.length, but the sum could wrap and become negative. To fill the gap created by removing elements, it’s supposed to shift the remaining elements left, like so:

memmove(
    backing + position * 8,                  // start of the gap
    backing + (position + count) * 8,        // elements after the gap
    (length - position) * 8                  // bytes to copy
);

Say we have a string array R of length 4, and we run REMOVE R,&H60000000,&H3FFFFFFF. position + count wraps to 0x9fffffff. As a negative signed 32-bit integer, it’s less than array.length. The multiplications by 8 also wrap, so we end up performing memmove(backing, backing - 8, 32), pulling the previous 8 bytes into the array. The command does report an Out of memory error, but it doesn’t matter, since the copy has happened already.

This is useful because the 8 bytes preceding any array in SmileBASIC contain a pointer to the array itself! After the REMOVE, operations on R[0] will treat the array backing as if it were a string.

Since a pointer occupies what would be the length field of R[0], the string length is enormous, and we can perform reads and writes out of bounds. We read and write to memory by copying to and from substrings of R[0].

This was a Switch 1 game, so the SmileBASIC agent could work on the exploit on my Switch 1, while the WebKit agent worked on the Switch 2. After some time, it got ROP.

error dialog displaying HELLO FROM SWITCH 2

Getting sysmodule RW

Okay, now we need to compromise a more privileged process. We’re interested in ordinary sysmodules and built-in sysmodules.

Which sysmodule should we pursue? We don’t have their code, so it’s unclear which sysmodules have which privileges.

I gave a few Codex instances the goal of getting sysmodule code execution. Most chose to focus on audio and ldn. I think that’s because audio and ldn have had bugs on the Switch 2. Codex also looked at the NV service, probably because GPU drivers are generally fruitful?

The fs sysmodule

In the meantime, I started looking at the built-in fs sysmodule, because:

  • The Switch 1 code shows that it’s able to serve decrypted code.
  • There’s a lot of code.
  • It’s probably similar to the fs module in the Switch 1, since the filesystem API didn’t change very much.

The first reason is the most attractive to me. Even if we can’t get a useful jailbreak from fs, we can at least decrypt some of the other sysmodules so Codex can find bugs in them. Other sysmodules like ldr and ro look enticing because they have permission to map executable memory3, but they don’t have large attack surfaces, especially from SmileBASIC. We’ll come back to them later.

Buffer overflow with path normalization

An IFileSystem handle has an IPC command, GetEntryType. This takes a path string, normalized with Path::Normalize.

Paths containing a parent-directory component with a backslash, like /..\, call into a helper that allocates a temporary heap buffer of 0x301 bytes. Our path is copied in, but it can be larger than the buffer, causing a buffer overflow. lol

We’ll need a good victim allocation to overflow into. Codex found that the BufferedStorage object allocates a cache entry for its files. If that entry has its dirty bit set, reads and writes to the file follow a pointer to cached data. We can hijack that for arbitrary read/write4.

From here, I scanned through memory to find SmileBASIC’s connection object and set the saved PID to 1. Now, my process has “FullPermission”, meaning I can perform privileged filesystem actions. I dumped internal storage and all ordinary sysmodule code, so Codex could perform offline analysis and I could understand where to go next.

Getting code execution as any ordinary sysmodule

Homebrew and modding typically rely on executing our own native code. Looking at the dumps, the only ordinary sysmodule with permission to map executable code is ro. All these sysmodules have CFI, PAC, and XOM. The interface for the module seems pretty minimal too. It seemed more fruitful to pursue a logic bug than to look for memory corruption in ro directly.

Let’s revisit that first point about fs serving decrypted code. This was useful for dumping the code for ordinary sysmodules. What’s the intended functionality of this interface? Loading programs?

Games and ordinary sysmodules are distributed as Nintendo Content Archives, or NCAs, containing a filesystem image called ExeFS. This contains a file for the main executable, main, and program metadata, main.npdm.

To load a program, the built-in ldr sysmodule asks fs to open ExeFS, and fs replies with an IPC handle to the filesystem. fs also provides two pieces of cryptographic information about the NCA header: the header’s SHA-256 hash and the developer’s signature of that hash. The loader uses this information to perform two signature checks:

  • Is Nintendo’s signature of main.npdm’s process permissions and the developer’s public key valid?
  • Is the developer’s signature of the NCA header hash valid?

Seems cryptographically sound to me, because, in theory:

  • the NPDM signature fixes the process permissions and developer key;
  • the key fixes the NCA header’s signature;
  • the signature fixes the NCA header’s hash;
  • the hash fixes the NCA header’s contents, including its filesystem hashes;
  • those hashes fix the executable content.

In practice, however, I’m doubtful of that last claim, because it’s the responsibility of the fs module to ensure the served filesystem matches the NCA header’s filesystem hash, and we have ARW in it.

Arbitrary r/w to native code execution

Indeed, with ARW, we can replace the ExeFS object behind the loader’s IPC handle with our own temporary filesystem. This filesystem still needs to serve a valid developer main.npdm for the loader’s first check, but the executable main itself can be arbitrary. The second check will pass because, by the time the loader opens the filesystem, fs has already submitted the valid NCA header hash and signature for the original filesystem.

There are two writes we perform:

  • The first puts a temporary filesystem object we’ve made into the domain-table entry for the loader’s ExeFS. This temporary filesystem contains the original main.npdm and our replacement main.
  • The second puts the loader’s ExeFS object into the domain-table entry for our temporary filesystem. It’s just to keep refcounts consistent and prevent fs from crashing.

These writes must happen after the loader requests the ExeFS filesystem but before fs processes the subsequent file requests. How do we ensure this?

The fs process maintains a list of its IPC connections. When a connection has a new IPC message, fs processes it. Using our arbitrary read/write, we can replace the handle fs waits on for the loader’s IPC connection with an event handle we control from SmileBASIC. That lets us control when fs processes a loader message.

With this, we can execute arbitrary code as any program we have a main.npdm for!

Getting built-in sysmodule native code execution

What main.npdms do we have? Well, all of them. With ARW, we can use to the loader’s fsp-srv connection to copy the NPDM of any ordinary sysmodule or game.

We’ll use this capability to launch our own code using ro’s NPDM. As mentioned earlier, ro’s NPDM gives it permission to invoke kernel SVCs like SetProcessMemoryPermission, MapProcessCodeMemory, and MapProcessMemory. In this case, we’ll use MapProcessMemory to create a writeable view of fs’s existing code. We can also dump fs’s code by reading this view.

These calls, however, require a KProcess handle to the process. To get a handle to fs, we’ll use our ARW to overwrite IEventNotifier’s 4-byte handle with 0xffff8001 and then call GetEventHandle from SmileBASIC. The kernel interprets this value to mean “the current process’s handle”, so SmileBASIC gets fs’s KProcess handle.

We can then send this handle to our custom ro process, who patches fs’s code.

Conclusion

Arbitrary code execution with any ordinary sysmodule’s permissions seems really powerful. We can investigate hardware without first exploiting each device’s driver. I’m hopeful this will help the homebrew community make progress toward CFW.

In the short term, there are a few next steps I think would be interesting:

  • Porting the fs sysmodule exploit to WebKit. Now that we know what bug we want to exploit, being able to perform arbitrary IPC calls is not as valuable. We might be able to trigger ARW in fs by changing the data used by WebKit’s existing filesystem code.
  • This jailbreak is tethered, and we don’t currently have a way to compromise built-in sysmodules other than fs. fs is a built-in sysmodule, so SM skips service ACL checks from fs, providing the same capabilities as smhax. I wonder if we can find bugs in other built-in modules?
  • With native code execution in fs, we can orchestrate its crypto hardware directly. For example, it’s used for NCA4 decryption.
  • The exploit has also been tested on the Switch 1, but I haven’t gotten around to packaging it yet. It wouldn’t provide the capabilities of a modchip, but it wouldn’t require any external hardware.

For now, I’m excited to see all the upcoming Switch 2 homebrew, emulation, and modding.

Footnotes

  1. It did not succeed. ↩
  2. It’s not inherently bad to attempt a WebKit exploit. Once we have a bug in a sysmodule we know to be valuable, it might make sense to go back and try to exploit it in WebKit with a data-only attack. This is because WebKit is accessible offline, meaning Nintendo can’t withdraw it like an eShop title. However, at this stage of our research, it’s not worth the cost to our iteration speed. ↩
  3. I wonder if one day Nintendo will map ordinary sysmodules and even game code via encrypted blobs only the kernel or secure monitor can decrypt. Then, no userspace process could observe any code on the system—there can never be RX mappings in userspace. Even the loader module, which starts new processes, would ask a higher exception level to load encrypted blobs it supplies. There’d be tradeoffs, like games being unable to read their own code at runtime. However, Nintendo has already started removing dynamic code features, like the JIT sysmodule. I wonder if this is the direction the Switch is headed. Luckily, that day is not today. ↩
  4. Initially, Codex’s read/write primitive repeated the buffer overflow on the cache object each time it wanted to change the backing buffer pointer. This hurts stability, especially when following many pointers consecutively, since each change is a chance to crash the system. We can use a similar trick to the one here. We can use some overflows to point the first cache entry’s backing buffer pointer at another cache entry’s metadata. Then we can replace the second cache entry’s pointer without risking more overflows. ↩
The Daily Front Page 6 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — A Terminal That Isn't There
article

WorldTUI: I trained a 360M model to pretend to be a terminal

by alphax314·▲ 514 points·159 comments·simedw.com ↗
There’s no shell or filesystem behind it: every keypress goes in, and the model predicts how the screen changes.

TL;DR: I fine-tuned a 360M-parameter language model to act as a terminal. There's no shell or filesystem behind it: every keypress goes in, and the model predicts how the screen changes. It can create files, run vim and tmux, play snake, and usually remembers what you wrote a few commands later. The biggest wins were teaching it to repair its own mistakes and decoding screen rows in parallel. Try it in your browser (208 MB) and type pythoon to see that it's not a real shell.

The demo is designed for a desktop browser with WebGPU and a physical keyboard. Chrome or Edge is the best place to try it. It should work on a modern phone, but painfully slowly.

When I first saw Genie 3 last year, I started imagining a future where applications aren't written in code but learned. Instead of a game engine rendering the scene, a model predicts the next most likely frame from the user's inputs.

Naturally I wanted to train my own world model. But I don't have a massive GPU cluster or a pile of video data, so I scaled down my ambition: instead of a game world, a terminal.

A terminal turned out to be a good fit. It's just a grid of characters rather than pixels, and I can generate as much perfectly labelled training data as I want by running real shells. A pretrained language model also already has a pretty good idea of what ls or cat should print.

What I really wanted to know was whether it could maintain a consistent world, or just generate convincing terminal output.

The final model is based on Qwen2.5-Coder-0.5B, fine-tuned on terminal sessions recorded from real programs running inside Docker. Jump to example videos

How it sees a terminal

Standard LLMs take a prompt and then append tokens to the end, one at a time. That doesn't map well to a terminal. A single keypress can do something on its own, like esc in vim, and output doesn't always go to the bottom: clear wipes the screen and sends the cursor back to the top. So instead of predicting a stream of text, I need to predict changes to the screen.

I treat the terminal as a grid of characters, one per cell.1 The model doesn't see the grid directly, but a sequence of tokens describing its contents and the changes made to it.

A session

Every session starts with a snapshot: the screen size, its contents and where the cursor is.

The size is part of the input, not fixed at 32×96. In the demo, you can set the rows and columns when creating a custom starting screen.

BOS SCREEN_START 32 96
ROW_0 0 'simedw@laptop:~$ '
CURSOR 0 17 1
SCREEN_END

This also lets me start partway through an application. Give it a bash prompt, vim buffer or a game of snake, and the model tries to continue from there. (It does better from bash.)

After that, each keypress goes in as the raw bytes a real terminal would send. Letters are themselves, Enter is \r, Escape is 0x1b and ← is ESC [ D and so on.

INPUT_START 'l' INPUT_END

The model answers with which rows to rewrite and where the cursor ends up:

OUTPUT_START
ROW_0 17 'l'
CURSOR 0 18 1
OUTPUT_END

In words: on row 0, starting at column 17, write l, then move the cursor to row 0, column 18. The last 1 means the cursor is visible, since full-screen apps sometimes hide it.

Nothing gets cleared first. New characters are simply drawn over the old ones.

I didn't need new tokens for characters. Qwen already has tokens for all 256 byte values, which I reuse for characters, coordinates and other small numbers. So a coordinate like 17 takes one token, not two.

Time is an input too. If nothing is pressed, the model gets a WAIT token with a duration instead of a key, which is how snake keeps moving on its own.

Copying rows

When you reach the bottom of the terminal window and press enter, every line has to move up by one. I could just ask the model to output every row again in its new place, but that's around 3,000 tokens for a single keypress.

So I added a COPY operation instead:

ROW_0 COPY 1
ROW_1 COPY 2  
ROW_2 COPY 3
...

Each operation copies a row from the previous screen. In this example, the old row 1 becomes row 0, row 2 becomes row 1, and so on.

A scroll now costs three tokens per row instead of roughly 96.

The same trick covers clearing the screen, inserting and deleting lines in vim, and navigating man pages. You can also copy a row and then overwrite part of it.

Altogether, the model uses a tiny vocabulary of 333 tokens: 256 byte tokens, 64 row tokens and a handful of special operations. Decoding is grammar-constrained, so every prediction is a valid screen update.

That tiny vocabulary comes back later, when I squeeze the model into a browser.

Generating the training data

I initially looked for existing datasets of terminal recordings, including asciinema, but couldn't find one with the precise keystroke-to-screen alignment I needed.

Luckily it wasn't too hard to create my own.

The basic idea was to generate believable terminal sessions by running real commands inside Docker containers, recording every keypress and the screen after each one.

The synthetic recipe was:

  1. Randomize usernames, hostnames, prompt styles, terminal sizes.
  2. Randomize directories and files based on a fictional persona (developer, sysadmin, etc.).
  3. Pick 6–24 weighted activities (modify files, vim, python, tmux, etc.).
  4. Track state, so sessions mostly open files that exist.
  5. Type like a person: one keypress at a time, with tab completion etc. I set the typo rate to 1.2%, which is generous to me.
  6. 35% of sessions start partway through, forcing the model to learn to work from any state.

The terminal size was mostly 32×96, with some 24×80 and 40×120, so the model doesn't overfit to one size.

I kept expanding the dataset as the model became more capable, and finally landed on 336k episodes, which corresponds to roughly 2B tokens. For comparison, the base model saw around 18T tokens during training.

Training

I used Qwen2.5-Coder-0.5B as the starting point. I needed a small model to get close to realtime performance. Being a coding model, it had also already seen plenty of CLI usage.

I started off by doing straightforward supervised fine-tuning: give a screen history and a keypress, predict the screen delta produced by the real terminal.

Ordinary typing was learned quickly: a letter appears, backspace removes it, the cursor moves.

In longer sessions, though, errors started to compound: a mistake in a filename propagated through the rest of the session.

Learning from its own mistakes

To address this I took a page from DAgger, where a model learns from the states it visits rather than just the ideal demonstrations.2

For each training example:

  1. Pick a point in a recorded session, usually close to the command that produces the output.
  2. Let the model predict the next 1-4 events.
  3. Compare the resulting screen with the real recorded screen.
  4. If the difference is small enough, construct a correction that repairs the model's screen on the next keypress.
  5. Continue training on the corrected frame and a few subsequent real events.

The delta takes the model's incorrect screen to the correct next screen. In essence, it learns to "repair" its own mistakes.

There's one important restriction: the model must have enough information to infer the correction. Any words introduced by a correction must have appeared on an earlier real screen or in the user's typing, not just in the model's own predictions.

For example, if the model misspells a filename that appeared earlier, I can teach it to fix that. But if it lists a filename it has never seen, I can't expect it to get it right.

Training on those examples would actually reward hallucinations, which I really don't need more of.

About a third of the sampled sessions produced useful correction examples. I repeated this in three rounds, each time collecting mistakes from the latest model.

Self-correction was one of the more effective training changes. Along with some additional training data, it improved PresetBench (defined below) from 24/47 to 38/47 at int4.

In total, training the model and its later refinements took roughly 75 GPU-hours on an RTX 4090.

Testing

I use three tests. ShellBench has 106 commands across 24 handwritten bash sessions, scored by exact output. PresetBench has 47 scripted cases drawn from failures I hit in the demo. Neither test appears in the training data.

The memory test has 32 worlds. Each writes two random values to two files, then reads them back in separate sessions. A world passes only if both readbacks are exact, giving 64 readbacks overall. The names and values never appear in training.3

How much does fine-tuning help?

The biggest difference was memory: WorldTUI got 9/13 readbacks right, compared with 2/13 and 3/13 for the prompted models.

It's still far from a reliable filesystem. It handles familiar commands fairly well, but combining them in new ways can quickly break things. For example, after echo green >> colors, running cat colors often doesn't show the appended line.

Making it fast

For a while I stayed away from autoregressive models altogether. A full redraw is around 3,000 tokens, and generating those one at a time seemed hopeless for something that's supposed to feel like a terminal.

But they just performed so much better than the alternatives I tried, so I gave in. With one token at a time, typing felt fine at ~38 ms per key, but anything that redraws the whole screen (vim test.txt, man, clear) took up to 12 s on my RTX 4090, exactly as feared. Plenty of time to reconsider whether I needed the manual. And I wanted this to run on my Mac, in near real-time.

Rows in parallel

What I'd missed was that most rows in a frame don't depend on each other, so there's no reason to generate them one after another. I run one batch element per row. Each gets the same previous history (including KV cache) but generates only its own update.

That changes the decoding cost from the sum of all rows, up to 3,000 steps, to the length of the longest row, roughly 100 steps.

The cursor then becomes its own step at the end that can see the whole set of row updates.

This required a matching attention mask during training, but the speed improvement was worth it. Large-frame p95 latency dropped from 6.7 s to 0.87 s.

Rows that can't talk to each other

This might sound too good to be true, and it was. The issue is that since rows are independent, they can't coordinate, which led to vim opening on row 3 instead of row 0, or several rows adding food for snake at once.

The solution was speculative decoding.

Normally speculative decoding uses a small model to draft tokens and a larger model to verify them. Thanks to causal attention, several tokens can be verified in a single forward pass.

Here I use the same model for both: the parallel rows produce a draft, which the model then verifies sequentially.

The verifier keeps tokens up to the first disagreement. From there it generates its own correction and re-proposes the remaining draft.

In the browser on my M4 Mac, typing a single character takes about 60ms. A larger update like man test takes 2.5s sequentially, or 0.9s with parallel drafting and verification.5

Making it smaller

I started with Qwen2.5-Coder-0.5B, which has roughly 494M parameters. I really wanted a web demo, so I needed to shrink it. The embedding table for its 151,936-token vocabulary is 136M parameters. I only need my 333 tokens,6 so I can drop almost all of it, which takes the model from 494M to about 360M parameters (990MB → 716MB).

I then quantized it to int4, which brought it to 208 MB.

The browser demo uses a custom JavaScript implementation of the Qwen decoder, with compute shaders written in WGSL and run through WebGPU. The shaders unpack the 4-bit weights during inference. Activations and the attention cache use 32-bit floats. All inference runs locally in the tab.

Distilling

Distilling it into fewer layers taught me something about which layers memory depends on. The teacher was an earlier checkpoint, which scored 78/106 on ShellBench. Removing just layer 7 without retraining barely changed next-token accuracy: 99.3% fell to 98.9%. But exact memory readbacks fell from 64/64 to 0/64. These tests fed in the true history, so the failure wasn't caused by errors compounding on the model's own output.

My first distilled student kept every even-numbered layer, but used the final layer, 23, instead of 22. It still wrote plausible terminal output, but returned the right value in only 31/64 memory readbacks. It always printed one of the two values it had written, but picked the wrong one about half the time. That's chance, and it hadn't recovered after 480M training tokens.

That student had dropped layers 1, 7, 15 and 22. A 16-layer student that kept those four passed all 32 memory test worlds, with 64/64 exact readbacks. It still passed all 32 worlds at 4-bit, at about 138MB. There was a cost elsewhere, though: it got 65 ShellBench commands right against the teacher's 78. So a student can look fine and have quietly lost its memory.

In the end I gave up on distilling it.

What it can do

Memory

This was the part I was most interested in. Generating a convincing directory listing is easy. What I wanted was to create a file, edit it, wander off, and come back to find it unchanged.

The first time I started tmux, opened a file in vim, changed it, saved it and then in a different tmux window read the updated contents with cat, I felt like Dr. Frankenstein: it's alive!

Other applications

It was very important to me that this should work beyond the bash prompt, so I trained on vim, python, man pages, snake and even tmux.

In vim, it handles the mode switch on esc and lets me save, quit or go back into insert mode.

Probably the most compute-intensive snake in the world.

What really blew my mind was tmux: I can create multiple panes, do various things in each and jump between them. It's not perfect, but it's a small model.

It even manages environment variables and variable expansion.

Python

Since the base model is a coding model, I was curious how it would handle the Python REPL. It makes a decent attempt: small additions are usually right, and list comprehensions return a list, though often with the wrong contents. It's also slightly forgiving of typos: pythoon launches Python, but ython doesn't.

What doesn't work

I didn't allow the Docker containers internet access, so tools like lynx are fairly boring. Python can handle very simple operations, but anything harder produces answers that remind me of GPT-3-era hallucinations.

Sometimes, when I create nested directories, it gets lost and all of a sudden I'm in a different path. There's clearly a lot of room to improve consistency.

In my testing, the demo ran about 20× slower in Firefox than in Chrome. It uses WebGPU in both. I haven't managed to establish the cause.

Related work

As always with projects like this, I tried to solve it myself first and only then looked at how others had approached it.

Back in 2022, people were already prompting ChatGPT to act as a Linux terminal. More recently, GameNGen simulated Doom using diffusion, and NeuralOS tackled a desktop GUI.

WorldTUI is closer to the original ChatGPT terminal trick, except that it's trained specifically on keypresses and screen updates, including full-screen applications like vim and tmux.

Summary

I had a blast building this. Is it useful? Not really. But for a 360M-parameter model running in a browser tab, it's far better than I expected.

What interests me most is that it manages to maintain a somewhat consistent world without implementing any of the rules underneath.

It's obviously a pretty weak world model, and I'd love to see how far this approach could go with better consistency and a different way of generating screen updates, perhaps using diffusion instead of autoregressive decoding.

One experiment I want to try next is training on thousands of randomly generated applications, each with its own controls and rules. The idea is to see whether the model can learn to predict the behaviour of an application it has never encountered before, given enough contextual clues.

Try it here. It's a 208 MB download, runs entirely locally, and works best in Chrome. Try to break it, and let me know what you find.

I'll post the weights soon and add the download link here.


  1. It's monochrome: only characters, no colours or text styles. Unicode characters, including tmux's box-drawing borders, are mapped to ASCII before encoding, so those borders don't need multibyte character tokens. ↩
  2. Not too dissimilar to the scheduled sampling in my midi post. ↩
  3. These are short-gap tests, with 0–1 intervening commands. ShellBench also tests persistence across 18 commands. ↩
  4. Both prompted models got three worked examples each. They predict whole command outputs rather than individual screen updates, so it's not quite the same task. ↩
  5. Speculative decoding gives a much bigger speedup on a 4090 than on my M4. My suspicion is that the bottleneck shifts between compute and memory bandwidth, but I haven't investigated this properly. ↩
  6. Padded to 384 to please the GPUs. ↩
The Daily Front Page 7 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — iOS, Elsewhere
repository

Run full iOS 16.5 firmware on Android Devices

by aghuang·▲ 360 points·133 comments·github.com ↗
★ 626⑂ 113 forks C

HackiOS boots Apple's open-source XNU kernel (xnu-8796.121.2, the kernel of iOS 16.5) on Android phone hardware and runs the unmodified iOS 16.5 user space on top of it: launchd → backboardd → SpringBoard → apps. Our own EFI loader, our own replacements for Apple's closed drivers, a UEFI port, and a Linux Wi-Fi driver on a compatibility layer make that possible.

It runs in two places:

  • POCO X5 Pro 5G (redwood, Snapdragon 778G) — nothing is flashed: the UEFI is started with fastboot boot, the whole system lives in RAM, and after a reboot the phone is back in Android;
  • QEMU (virt, aarch64) — the same thing on any Linux computer, no phone needed.

This repository is half of the project:

Repository What
hackios-xnu-kernel (this one) XNU patches, the EFI loader, the UEFI port, Wi-Fi, QEMU scripts, xl, prebuilt kernel/loader/UEFI, common/ scripts
hackios-xnu-userland our init, injected libraries, launchd jobs, the APFS image builder, the scripts that take iOS out of Apple's IPSW, Metal/Mesa work

No Apple files are in either repository. ios165/fetch.sh downloads the iOS 16.5 IPSW from Apple's own CDN to your machine and extracts what is needed there. HackiOS is an independent research project by OOSEX GANG and is not affiliated with, authorised or endorsed by Apple Inc. iOS, iPhone and Apple are trademarks of Apple Inc.

Lock screen Home screen Control Center Settings

Photographed on the phone, the Adreno GPU drawing (gpu=1). More in Screenshots.

What works

Works Does not work (yet)
Lock screen, swipe to unlock, home screen with all icons (two pages), stock iOS 16 wallpapers Cellular, Bluetooth
System gestures: swipe up (home, app switcher), edge swipe (back), Control Center Charging under our kernel (the phone only discharges)
Apps: Settings, Clock, Calendar, Photos, Notes, Safari and more; widgets (Weather, Calendar) on the phone
Metal for apps (in progress: 293 of 456 system shaders already run on the Adreno, see docs/air.md in hackios-xnu-userland) App Store content and Apple ID sign-in (no Secure Enclave; FairPlay daemon exits)
Phone touchscreen (Goodix GT9916), multitouch, wake on touch; real power and volume keys Up to 8 CPU cores (cpus=8), big core at 2.4 GHz, ~20 s to the lock screen
Video and Live Photo recording Adreno 642L GPU through Mesa/freedreno (gpu=1, OpenGL ES for CoreAnimation)
Wi-Fi (WCN6750, ath11k): join from Settings, Safari over Wi-Fi, 55–90 Mbit/s Sound (speakers, main microphone), camera in Camera.app (front/rear, preview, focus, HEIC photos)
Data that iOS writes survives a reboot (var_store=1 ufs_write=1); iOS root volume on the phone's flash Sileo + Procursus (dpkg, apt), tweaks, SSH

It is a research bench, not a ROM: a session lasts a given number of seconds, then the kernel returns to the loader and hands over its log.

Quick start: QEMU, no kernel build

prebuilt/ holds the kernel, loader and our programs built from these repositories, so all you need is the system image, which is made on your machine from Apple's IPSW.

Needs: Linux x86-64, ~12 GB free disk, 4 GB free RAM. Packages (Arch):

sudo pacman -S --needed git python 7zip lz4 gcc qemu-system-aarch64 qemu-ui-gtk edk2-aarch64

(Debian/Ubuntu: git python3 7zip liblz4-dev gcc qemu-system-arm qemu-efi-aarch64; 7-Zip must be 23 or newer — it reads APFS.)

git clone https://github.com/oosexgang/hackios-xnu-kernel.git hackios
cd hackios
common/setup.sh               # brings hackios-xnu-userland into the same tree, checks the host
ios165/fetch.sh               # downloads 7.4 GB from Apple's CDN and extracts what is needed (5-15 min)
common/build.sh qemu-virt     # builds the APFS images (and the kernel, if the toolchain is there)
common/run.sh qemu-virt       # a 20-minute session in a QEMU window

The lock screen appears after 2–3 minutes.

  • Mouse with the left button held = finger. Unlock / leave an app: swipe up from the very bottom edge; back: swipe from the left edge.
  • Keys: H home, L lock/power, ↑/↓ volume, F11 (hold) five fingers.
  • From a script: qemu/touch.py swipe 0.5 0.985 0.5 0.3 250, qemu/touch.py tap 0.615 0.71, qemu/touch.py key home; screenshot: qemu/screendump.sh shot.png.
  • Right after SpringBoard appears the system is still registering apps: give it 30–40 s.
  • Debian/Ubuntu UEFI firmware: QEMU_EFI=/usr/share/AAVMF/AAVMF_CODE.fd QEMU_VARS=/usr/share/AAVMF/AAVMF_VARS.fd.

On the phone (POCO X5 Pro 5G)

You need a POCO X5 Pro 5G (redwood) with an unlocked bootloader, adb and fastboot, and the images from the section above. Nothing is written to the phone's storage.

The phone's own firmware is not in the repository and cannot be: it is the vendor's and is taken from the very phone it will run on, from its Android:

adb pull /vendor/firmware/a660_{gmu.bin,sqe.fw,zap.mdt,zap.b00,zap.b01,zap.b02} fw-gpu/      # GPU (gpu=1)
adb pull /vendor/firmware_mnt/image/wpss.{mdt,b02,b03,b04,b05,b06,b07} fw-wifi/              # Wi-Fi (wifi=1)
adb pull /vendor/firmware_mnt/image/adsp.{mdt,b02,...,b36} fw-audio/                         # sound (adsp=1)
adb pull /vendor/firmware/aw8697_haptic.bin fw-haptic/                                       # haptics

(Put the fw-* directories next to the workspace. Wi-Fi also needs fw-wifi/mac — the radio's address on one line — and fw-wifi/network — network name and password. userland/build.sh prints which firmware went in.)

common/build.sh redwood GL=1          # images + out/redwood-boot.img
common/run.sh redwood 900             # loader into RAM, system image into RAM, a 15-minute session

or step by step with xl:

./xl enter            # Android -> fastboot -> our loader in RAM (fastboot boot); it brings up its own USB link
./xl ramdisk          # upload the system image into the phone's RAM (2.5 GB, ~80 s), once per loader session
XL_SECS=900 XL_CMDLINE="touchscreen=1 cpufreq=1 bootcpu=7 cpus=8 gpu=1 wifi=1 adsp=1" ./xl run
./xl screenshot shot.png
./xl reboot           # back to Android

./xl with no arguments lists every command (logs, screen and sound recording, camera frames, stop, state...).

Prebuilt boot image

Every release has hackios-redwood-boot.img attached: the redwood UEFI with our loader inside, ready for fastboot boot. It contains no Apple files; the system image is still made on your machine (above).

Building from source

common/build.sh <device> runs every step that this machine can run and uses prebuilt/ for the rest.

  • Kernel — needs theos in ~/theos (cctools and iPhoneOS16.5.sdk) and clang lld python perl. Details: xnu/README.md.

    xnu/apply.sh && xnu-deps/setup.sh && ./xnu-build.sh -j8 -k
    
  • Loader — xnuloader/build.sh (clang + lld-link, an EFI application without EDK2).

  • Images — REST=1 userland/build.sh (variables documented at the top of that file).

  • UEFI — uefi/README.md (Project Silicium port); not needed to run, prebuilt/uefi has it.

  • After rebuilding: tools/update-prebuilt.sh refreshes prebuilt/.

Porting to another device

common/new-device.sh <codename> path/to/device.dtb   # profile + loader platform from the phone's device tree

Then follow docs/PORTING.md: the UEFI port, the loader's platform description, the kernel's drivers, the firmware. Device profiles live in common/devices/ (redwood.conf, qemu-virt.conf, _template.conf).

How it works

fastboot boot ──► UEFI (Mu-Silicium) ──► xnuloader (EFI application)
                                           │  stays resident: USB link (fastboot protocol),
                                           │  watchdog, receives the kernel's log
                                           ▼
            XNU (BCM2837 config as the base + our platform)
              ├─ GICv3, timer, video console, return to the loader
              ├─ APFS (images in RAM, iOS volume on flash), ramfs (/private/var, /tmp)
              ├─ minicrypto instead of corecrypto, AMFI and Sandbox stand-ins (MAC policies)
              ├─ driver replacements: IOSurface, IOMobileFramebuffer, AppleKeyStore, network stack
              ├─ input: /dev/redwood-touch ◄─ Goodix GT9916 (phone) / virtio-input (QEMU)
              ├─ GPU: Adreno 642L, Wi-Fi: WCN6750 (ath11k via LinuxKPI), sound: ADSP / virtio-sound
              ▼
            iOS 16.5 launchd → logd, notifyd, cfprefsd, runningboardd, backboardd, SpringBoard, apps
              ├─ our libraries are injected into backboardd, SpringBoard and mediaserverd
              │  (virtual HID services, a few ObjC method swaps — in memory only)
              └─ mediaserverd gets our CoreAudio output device (RedwoodAudio.driver)

The iOS programs, frameworks and dyld shared cache are not changed by a single byte: what they miss is done by the kernel (driver replacements) or by a library the kernel injects with DYLD_INSERT_LIBRARIES (kern.exec_inject).

Layout

Path What
common/ setup.sh (workspace), build.sh / run.sh (per device), new-device.sh, devices/*.conf, ugit
xl drives the phone over USB: loader, kernel runs, logs, screenshots, screen and sound recording
xnuloader/ the loader: loader.c (UEFI application), mkpayload.py (kernel + images + arguments container)
xnu/ our XNU changes: patch, new files, apply.sh / export.sh
xnu-deps/ everything for building XNU on Linux: setup.sh, tool wrappers, stubs
xnu-build.sh, xnu-env.sh kernel build
uefi/, mkxnuimg.py the UEFI port and packing the boot image for fastboot boot
wifi/lx/ the layer on which Linux's Wi-Fi driver builds for our kernel
qemu/ QEMU runs, touch input, screenshots, stack symbolication
tools/ recording (recording.py, sound.py), UFS/flash tools, mk-ath11k.sh, new-workspace.sh, host tests
prebuilt/ built kernel, loader and UEFI pieces (NOTICES.md for the third-party code in the kernel)
docs/ screenshots, checks.md, PORTING.md

Debugging

  • Session log: QEMU's stdout or logs/HHMMSS-run.log from the phone.
  • RC_JOBS=rc.jobs.tour REST=1 userland/build.sh — an image that unlocks and opens every app of the first page.
  • userabort: in the log is the stack of a process that called abort(); usertrap: (with systrace=1) — crashes.
  • Live stacks (QEMU): qemu/touch.py stacks NAME, then qemu/symstack.py LOG NAME (needs ipsw).
  • How a check can lie to you: docs/checks.md.

Screenshots

From the phone's screen, one session (GL=1 REST=1, gpu=1):

Home screen, page 2 Search Settings > General Calendar Clock

Wallet Messages Music Maps App Store

Licenses

  • No iOS files are in the repositories: ios165/fetch.sh downloads them from Apple's CDN to your machine.
  • xnu/ is a derivative work of XNU and is distributed under APSL 2.0, like XNU itself; prebuilt/mach.* is the kernel built from it. It also contains ath11k (BSD-3-Clause-Clear) and FreeBSD LinuxKPI code (BSD-2-Clause): see prebuilt/NOTICES.md.
  • xnu/files/bsd/miscfs/apfs/libzbitmap/ and xnu-deps/build/lzbitmap/ — libzbitmap (Corellium LLC, MIT here); xnu/files/bsd/miscfs/apfs/libdeflate/ — libdeflate 1.24 (Eric Biggers, MIT, COPYING there).
  • ath11k, Linux and FreeBSD sources are not in the repository: tools/mk-ath11k.sh fetches pinned releases. wifi/lx/patches/*.patch are our changes to FreeBSD headers; the rest of wifi/lx/ is ours.
  • uefi/files/Binaries/redwood and prebuilt/uefi/SILICIUM_UEFI.fd contain UEFI drivers from the phone's Xiaomi firmware, distributed the way Project Silicium distributes them for other devices; prebuilt/uefi/mkbootimg.py — AOSP, Apache-2.0.
  • This repository is licensed under the Apple Public Source License 2.0: our changes to XNU are a derivative of XNU and must be, and our other code here (loader, scripts) is released under the same license. Third-party code keeps its own license, as listed above.

Team

OOSEX GANG — @oodze (founder), @netusd, @wannqn, @hxfuxyyXD. News: t.me/oosexgangdevs.

The Daily Front Page 8 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — The Phone and the Transfers
article

Jared Kushner Hacked Phone Reveals Secret Negotiations, Millions in Transactions

by ck2·▲ 357 points·162 comments·vanityfair.com ↗
The money in the account—hundreds of millions of dollars—had come from a bank in Azerbaijan.

Image may contain Jared Kushner Book Publication Advertisement Poster Adult Person Face Head and Photography

In late spring 2020, a source I knew to be reliable called me with a story. The Dutch government had hacked into Jared Kushner’s phone and monitored him as he accessed a Dubai-based bank account. What was odd, the source said, was that the money in the account—hundreds of millions of dollars—had come from a bank in Azerbaijan. Most importantly, Kushner appeared to have transferred significant amounts of money from the Dubai account to other individuals, including a warlord, a mercenary and a one-time hit man. The story sounded preposterous, I told my source. And yet.

Six months later, I found myself speaking with someone else about the UAE government and their use of mercenaries in conflicts around the Middle East and Africa when I asked, on a whim, whether they knew anything about Kushner and bank transfers from a UAE account. My acquaintance grew quiet. Then they replied, “Yes.”

Over the next four years, I came to learn that, sometime in late 2017, the Netherlands Defense Intelligence and Security Service (MIVD) made a startling discovery. A General Staff of the Armed Forces of the Russian Federation (GRU) operative, a dark web hacker specializing in stolen bank data, was traveling to the UK for an espionage mission. They reached out to the British government for permission to apprehend him when he arrived. The British agreed.

When the Russian national arrived in England, the Dutch informed him that he had two options: he could work for them against the GRU, or the British would arrest him. Once in UK government custody, the operative would be charged with espionage. If convicted, he would spend years in a British prison. The Russian chose to change his employer.

Later that year, the Russian operative gave the Dutch spies access to one of the GRU’s most sensitive assets. Located in Rostov, Russia, the GRU’s hacking and cyber team operated a remote server on which they stored some of their bounty. During their search through these secret files, the Dutch found something astonishing: screenshots of Jared Kushner’s iPhone.

In The Hague, the MIVD hacking team tried to reverse engineer the Russian penetration of Kushner’s iPhone. Kushner owned what was then the latest model, the iPhone X. Released in November 2017, it featured Face ID, a state-of-the-art security feature that Apple had promoted at its launch. The Dutch team had been trying to pick the phone’s door lock, so to speak, when it occurred to them that the Russians may have found an unlocked window to gain entry instead. Their hypothesis was correct. By early 2018, the MIVD had found a vulnerability in the iPhone that gave them access. The security exploit wasn’t perfect, however. Some malware allows a hacker to turn a victim’s phone into a microphone and video camera, turn the phone on or off, and pull and add files. The Dutch solution did not provide that level of access. Instead, when Kushner used the phone, they could see his screen. Almost as soon as they got inside, the intelligence service began capturing every image of Kushner’s screen as he used it, filing their own cache of surveillance on their internal computer servers.

As they monitored Kushner’s phone, they discovered he used it to log in to a UAE bank account. By the time the Dutch spies had visibility into the phone, the account had received hundreds of millions of dollars from a bank in Azerbaijan. Their initial assessment was that the bank account was affiliated with the government there.

“Jared was looking for shortcuts in his diplomacy,” a source who knew of the UAE’s deal with Kushner said.

For the MIVD hackers, the bank account became an intelligence mystery to unravel. Nearly everything they worked on had a tinge of Russian conspiracy. A little over a year into Trump’s first presidency, the MIVD, like FBI agents and federal prosecutors in Washington working on the Robert Mueller investigation, had only part of the story.

Kushner, UAE ruler Mohamed bin Zayed (MBZ) and Mohammed bin Salman (MBS) of Saudi Arabia, converged at an auspicious moment. MBS wanted to be crown prince. MBZ wanted to blow up Obama’s Iran nuclear deal, and Kushner wanted both to help him force the Palestinians into a deal that Israel would accept. Despite the perception of his wealth, Kushner was not entirely financially independent of his parents, and the family business, Kushner Companies, faced a billion-dollar loan coming due on their trophy property, the Manhattan office building at 666 Fifth Avenue.

Early in the first Trump administration, MBZ and MBS offered to pay for a slush fund dedicated to helping the new administration with foreign policy goals. The idea was to help pay for Trump’s promised wall between Mexico and the US, for example, in an effort to secure a second term in the White House. The two Arab royals initially discussed with Kushner putting more than $10 billion into the effort. Within months, though, as MBZ pushed the Trump administration to help back MBS’s effort to become his country’s crown prince—and future king—the broader foreign policy slush fund idea fizzled. Instead, MBZ and MBS initially, and then MBZ alone, put at least $2 billion into at least two bank accounts for Kushner. It is unclear how the royals organized their $2 billion in combined payments, but they effectively split the cost. For the purposes of explanation, it is best to understand where and how each bank account was controlled.

“The Emiratis and the Saudis do this once a year. A billion or two is nothing for them, and if it gets them what they want, it’s money well spent.”

Bank account Alpha was held at First Abu Dhabi Bank, the largest in the UAE, and was overseen by MBZ’s brother, Tahnoon bin Zayed, who served as the bank’s chairman. Beginning in 2017, the Saudis and Emiratis transferred roughly $750 million into the Alpha account. Alpha would be used as a foreign policy fund. This money would be overseen and partially managed by Kushner and MBZ, who, in their effort to strike a grand bargain to end the Israeli-Palestinian conflict, believed the region’s map needed to be redrawn.

“Jared was looking for shortcuts in his diplomacy,” a source who knew of the UAE’s deal with Kushner said. This person held discussions with both senior UAE and Israeli officials about the secret financial arrangement between Kushner, the UAE, and, at least initially, Saudi Arabia. “Jared promised MBZ that he’d push their agenda with Trump if they participated in a fund. He wanted normalization with Israel so that business could take off.” A slush fund—a shared pool of money for off-the-books diplomatic objectives—was a common form of Gulf Arab government corruption, this person explained. “The Emiratis and the Saudis do this once a year. A billion or two is nothing for them, and if it gets them what they want, it’s money well spent.”

The Alpha account looked like the funding source of a UAE government program, by which MBZ paid his bureaucrats their salaries or funded government-run schools. But how and through whom the money flowed into the Alpha account revealed that it was intended to remain secret, more akin to a covert and illicit scheme, given that it was managed in part by a senior advisor to the president of the United States.

The Dutch spies who monitored the Alpha account noted that all of it was sent by a bank in Azerbaijan in American dollars. Azerbaijan plays a unique role in money laundering. Its central bank maintains high levels of US dollars in its reserves but does not adhere to the highest standards of bank transparency. As a result, Azerbaijani banks have well-established but unadvertised practices of serving as way stations for large transfers, in which a foreign currency is exchanged for an equal amount in dollars. For a roughly 6 to 7 percent fee on the transaction, some Azerbaijani banks will accept a transfer from a client who wishes to move Saudi riyals or Emirati dirhams totaling hundreds of millions of dollars. The Saudi or Emirati client sends the money to the Azerbaijani bank, which then uses a different internal bank account to transfer the equivalent US dollars to the client’s requested destination. For auditors, this shadow trade can’t be discerned.

A shallow audit, as the Dutch tried while monitoring Kushner’s iPhone, revealed nothing more than what appeared to be an Azerbaijani government–linked bank account that sent hundreds of millions of dollars to an account in Dubai. But there was another aspect of the Alpha account that the Dutch couldn’t see or understand, one that helped reveal the secret purpose of the money. Kushner did not own the bank account at First Abu Dhabi Bank. He was a signatory for an account managed and owned by an Emirati charity.

When MBZ and MBS first began contributing to the Alpha account in 2017, the Watani Al Emarat Foundation, a UAE government-funded charity, was run by Dherar Belhoul Al Falasi. Al Falasi was a technocrat and a member of the Federal National Council, and friends with one of MBZ’s closest friends and advisors. As a result, Al Falasi and the Watani Foundation had a second mission. The charity was used as a cover to move money in support of the country’s secret military and intelligence operations overseas. Under the Watani cover, Al Falasi helped facilitate the UAE’s secret weapons-purchasing programs, one confidential source who had direct knowledge of the charity’s proliferation program revealed. This source said that the Emiratis believed that the program’s status as a charity made its international transactions less likely to be scrutinized and therefore served as a useful cover for funding MBZ and his brother’s secret wars.

MBZ and Tahnoon made Kushner a signatory on the Alpha account with Watani. As a signatory, Jared had access to it and could, in theory, make transactions, but it technically wasn’t his account. One way to view what Kushner did with the Alpha account is to imagine him as the director of the CIA. Had he been running the government entity that managed and ran secret foreign programs, maintaining the account, again, with presidential approval and congressional disclosure, Kushner’s conduct would have been within his job’s responsibilities. But he was not the director of the CIA, whose position is approved by the Senate and whose operations are overseen and accountable to Congress. Instead, Kushner was overseen only by his father-in-law, who, according to four senior Trump administration officials—two national security advisors, a White House chief of staff, and a former CIA director—were unaware of any presidential authorization for Kushner to access a foreign government bank account. (Kushner’s counsel, however, said Kushner did not make any agreements or arrangements with leaders or officials in foreign countries that were not agreed to by the President of the United States and in the best interests of the United States.)

Regardless of whether he was a signatory or the owner, Jared was required by federal government regulations and the Internal Revenue Service to disclose his access to the account. Unless disclosed to and approved by the US government and reported on his tax returns, Kushner’s access to the Alpha account may have violated US law. (A lawyer for Mr. Kushner denied that his client had any knowledge of or connection to Al Falasi, the Watani charity, or a UAE bank account and stated that he had complied with all legal requirements when dealing with foreign governments.)

In addition to the Alpha bank account, MBZ put money into at least one other account intended for Kushner. By the spring of 2018, the crown prince had moved roughly $1 billion to Israel via Azerbaijan for Kushner. We will refer to this account as the Beta bank account. It is unclear how Israeli Prime Minister Benjamin Netanyahu first learned of MBZ’s money for Kushner, but a person briefed on the Beta account told me that the prime minister encouraged Kushner to have the money deposited in the Israeli Central Bank, in what would appear to be a government account. It is also unclear how Kushner used the money the UAE deposited into the Beta account for him, but according to the person with knowledge of the money, its allocation was for Kushner’s personal benefit. But as with the Alpha account, there were clues in the way the Beta account was managed.

Image may contain Donald Trump Jared Kushner Didier Burkhalter Adult Person People Head Face and Clothing

President Donald Trump with Jared Kushner and Israel Prime Minister Benjamin Netanyahu in 2017.

Israel’s Central Bank does not operate personal accounts. The bank holds and transfers only government funds. The government accounts use a dual-key system, which requires two authorized individuals to make any transfers from the account as an oversight mechanism. Netanyahu required Kushner to inform him before making any transactions from the Beta account.

To do so, Kushner passed his messages through Ambassador David M. Friedman, who frequently met with Netanyahu. With the money in the Central Bank, it would be difficult, if not impossible, to connect MBZ’s payment to Jared. It is unclear if spies in the Netherlands had any indication of the Beta account. (Ambassador Friedman denied that he had any knowledge of, or involvement with, any UAE money made available to Kushner, or that he passed messages on Kushner’s behalf. “I know absolutely nothing about any of these allegations,” Friedman said, “and the specific allegations about me or my alleged involvement in this alleged scheme are 100% false.” Kushner’s counsel also said Kushner “has no idea” about any such account, and insisted that “there are no accounts and never were.”)

Apparently, Kushner faced the challenge of moving money from the Beta account in Israel to other accounts where he could have untraceable access to the funds. One person who worked with Kushner to move the money out of Israel said that much of it went to bank accounts in Cyprus before being moved elsewhere.

During Kushner’s secret financial arrangement with MBZ, he helped negotiate a third, altogether distinct account. As part of what was, at the time, a secret warming of diplomatic relations between Israel and the UAE, Kushner helped negotiate an agreement by Israel to help defend the UAE from a major Iranian military attack. The UAE needed to cover the cost of the emergency defense, however, and the government secretly made another transfer to Israel’s Central Bank. This was something like a rainy-day defense fund. Combined, the three accounts represented a secret foreign policy negotiated by Kushner with the leaders of Israel, the UAE and Saudi Arabia.

Although Kushner’s position as senior advisor to the president was unpaid, he was an official government employee. Not only did his position require financial disclosures for ethics regulations, but each year he worked in the White House, he had to file both a public and confidential financial form, known as the Executive Branch Personnel Public Financial Disclosure Report, also known as a 278e disclosure. Because he had access to classified government secrets, Kushner was required to disclose any bank account to which he had signatory—or beneficiary—access.

Kushner’s apparent betrayal of the public trust, however, went further than his failure to disclose the secret Alpha account in the UAE or the Beta account in Israel. By giving him access to roughly $2 billion, regardless of how the money was used, MBZ and MBS were paying for his influence within the US government. Any efforts he made to shape US policy that came from a foreign government that had provided him with money would make him an agent of a foreign power. US law requires citizens who lobby on behalf of a foreign power to declare themselves and the country they are working on behalf of to the Justice Department.

One former prosecutor who worked on the Mueller investigation said that if Kushner promised anything to MBZ and MBS in return for the money they offered him—even if it was just speaking to his father-in-law—he may have violated federal bribery laws, as well as the foreign agent statute. (Mr. Kushner’s lawyer denied that Kushner violated any laws while serving in the White House.)

From PRINCES AND THIEVES: Jared Kushner and Mohamed bin Zayed’s Secret Plot to Remake the Middle East by Matthew Cole. Copyright © 2026 by Matthew Cole. To be published by One Signal Publisher/Atria Books, an Imprint of Simon & Schuster, LLC.

The Daily Front Page 9 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — The Breach Ledger
article

What’s getting pwned right now

by mrkd·▲ 356 points·163 comments·pwn.watch ↗
Security incidents that matter right now, and whether there’s a fix yet.

Security incidents that matter right now, and whether there's a fix yet.

Arista VeloCloud Orchestrator zero-day CVE-2026-114625 exploited in attacks

Arista patched an actively exploited critical SQL injection flaw (CVE-2026-114625, CVSS 9.9) in on-prem VeloCloud Orchestrator that lets any authenticated user gain operator privileges and masquerade as the local 'superuser operator'. Hosted VCO is already patched; on-prem admins need to upgrade.

Major U.S. banks detect unauthorized third-party AI agents inside customer accounts

Axios reports that major U.S. banks, including Morgan Stanley, Bank of America, JPMorgan and Wells Fargo, are detecting third-party AI agents operating inside customer accounts. In most cases the agent logs in with the customer's own credentials and permission, which breaks bank rules that require people to log in themselves. Some banks also saw agents contact call centers or take actions that appeared independent of user instructions, and executives say they often can't tell a human from an agent, or an authorized agent from a rogue one. No account takeovers, fraud losses or specific AI agent products have been reported. Morgan Stanley is blocking third-party agents and JPMorgan, Bank of America and Citi are restricting them. Don't give an AI agent your bank username and password.

GitLab CVSS 10 unauthenticated RCE via regex compiler (CVE-2026-110264)

GitLab released a critical patch on Oct 21 2026 for CVE-2026-110264: an integer overflow in the bundled Onigmo / regex compiler that can allow an unauthenticated attacker to execute code on self-managed GitLab. CVSS 10.0; every CE/EE version from 7.0 (2014) is in range. Instances that only applied the Oct 12 regex fix remain vulnerable and must upgrade again.

Keycloak unauthenticated account takeover gets a public exploit (CVE-2026-18963)

A flaw in Keycloak's reset-credentials flow (keycloak-services) lets an unauthenticated attacker force a password reset for any user without clicking the emailed verification link, then set new credentials and take over the account. Red Hat rates it CVSS 9.1. Fixes shipped in August (26.4.15, 26.6.6, 26.7.2); on Oct 21 a full proof-of-concept with check and takeover modes was published on Exploit-DB, so unpatched Keycloak instances should be upgraded now.

Linux kernel: unpatched ZDI bug reports with repro details leaked to public LKML (ksmbd RCE, CVSS 9.0)

On Oct 21, Trend Micro's Zero Day Initiative sent several unpatched Linux kernel vulnerability reports to security@kernel.org but Cc'd the public linux-kernel and subsystem lists, so full technical details (code paths, KASAN traces) are now public before fixes ship. The worst are two ksmbd (in-kernel SMB server) remote code execution bugs that ZDI scores CVSS 9.0: an SMB Direct integer underflow (needs an RDMA device and a writable share) and a protocol-dispatch race (needs a guest share). Also leaked: an skb_zerocopy local privilege escalation (CVSS 7.8), a vmwgfx out-of-bounds write LPE, and an nvmet info leak. No CVEs yet and no fixed mainline or stable release; the ksmbd race fix sits in the ksmbd maintainer tree and an SMB Direct fix is in a branch aimed at Linux 7.5. No exploitation reported. Only machines running ksmbd are exposed to the RCEs.

LiteLLM 1.107.0 PyPI/Docker supply-chain compromise

On Oct 21 2026 attackers compromised LiteLLM’s release pipeline and published malicious litellm==1.107.0 to PyPI (live ~2 hours) plus compromised Docker Hub/GHCR tags (v1.107.0, latest, main-latest, main-stable). The wheels install cook.pth / cook.py / sitecustomize.py that steal cloud, developer and AI-tool credentials at every Python startup and open a remote-code loader. Second LiteLLM compromise of 2026.

Node.js October 2026 security releases (Brotli RCE + TLS/DNS highs)

On Oct 21 2026 Node.js shipped security updates for 22.x, 24.x and 26.x fixing ten vulnerabilities. The headline issue is CVE-2026-111497, a Brotli decoder out-of-bounds write (high per Node.js, CVSS 9.2 critical per the Google CNA on NVD, rooted in Google Brotli 1.0.3 to 1.2.0) that can enable remote code execution when attacker-controlled Brotli data is decoded. The same release also fixes TLS hostname/IP bypasses and DNS NUL truncation, and refreshes the bundled CA store for the eMudhra incident.

ISC BIND 9: replayed GSS-TSIG messages corrupt memory, possible RCE (CVE-2026-94300)

ISC disclosed a remotely exploitable memory-corruption bug in BIND 9's named on Oct 21. An attacker who captures a GSS-TSIG signed UDP message (the Kerberos signing used for Active Directory-style dynamic DNS updates) can replay it while the negotiated key is still valid and, combined with crafted queries to a zone they control, may get remote code execution, or at least crash named. CVSS 8.1 (High). No workaround. Affects BIND 9.11.0 through 9.18.50, 9.20.0 through 9.20.29 and 9.21.0 through 9.21.26. Fixed in 9.20.30 and 9.21.27; ISC lists no 9.18 fix. ISC knows of no active exploitation. Debian trixie has a fixed package; Debian bookworm and Ubuntu are still waiting.

Quest Diagnostics breach: patient records accessed via Quanum Lab Services Manager

Quest Diagnostics says it learned on Oct 21 2026 of unauthorized access to its Quanum Lab Services Manager (LSM), the system some clients use to place lab test orders and receive and look up results. Quest believes some patient data in Quanum LSM was accessed and confirms PHI/PII was involved; the specific data affected is still being investigated. Quest paused access to Quanum LSM (and, as a precaution, Essential Insights and LabHQ, where no data was accessed), notified federal law enforcement and engaged outside experts. Core operations are not materially disrupted, and Quest says the incident is not related to the PHP vulnerabilities.

Railway discloses unauthorized access to customer environment variables

On Oct 21 2026 Railway reported anomalous activity on systems storing customer environment variables. An unauthorized third party may have accessed encrypted env vars and, for some, obtained decrypted contents (API keys, DB/registry credentials). Railway says it believes this is part of a series of attacks on platform companies aimed at compromising AI inference providers, and asked upstream providers to revoke keys. Builds were paused platform-wide for ~a day; on Oct 22 they were restored for Enterprise and Pro, with Hobby/Free/Trial still pending. All users are told to rotate secrets while scoping continues.

EG Secure Solutions SiteGuard Server Edition: EG Secure Solutions SiteGuard Server Edition OS Command Injection Vulnerability

EG Secure Solutions SiteGuard Server Edition contains an OS command injection vulnerability which may allow an attacker to execute arbitrary OS commands with root or SYSTEM privileges on the system running the affected product. Added to CISA KEV on 2026-10-20.

GMO Onamae Desktop Cloud malware on customer VPS

GMO Internet’s Japanese VPS service Onamae Desktop Cloud said an attacker installed malicious programs in customer environments, forcing shutdown of as many as ~26,739 servers with no immediate restart date (mid-October 2026 reporting).

Siemens Software Center: Siemens Software Center Uncontrolled Search Path Element Vulnerability

Siemens Software Center contains an uncontrolled search path element vulnerability that could allow an authenticated local attacker to place a specially crafted DLL in a directory that the application searches, leading to arbitrary code execution with the privileges of the affected application. Added to CISA KEV on 2026-10-20.

HTTP/3 QPACK “Header Accordions” memory-amplification DoS

FoxIO published research (Oct 20 2026) showing that missing or late decoded-header limits in QPACK let a tiny HTTP/3 HEADERS frame expand into huge server memory use (up to ~4000× on Bun). Seven of ten implementations tested were vulnerable; quic-go, Cloudflare quiche, lsquic and Wireshark are patched, while Bun, aioquic/mitmproxy and h3 remained unpatched at publication.

OpenCode: malicious MCP server can run code on Windows/WSL during sign-in (no CVE)

A command-injection flaw in the OpenCode AI coding agent let a malicious or later-hijacked remote MCP server run PowerShell commands on a developer's Windows or WSL machine when they started the MCP OAuth sign-in. The server-supplied authorization endpoint was passed unescaped to an old version of the open package. Anomaly fixed it in 1.18.33 on Sep 28 without a CVE or advisory, so scanners won't flag 1.0.137 through 1.18.32. macOS and Linux are not affected. Pillar Security found it and rates it 9.8; no in-the-wild exploitation reported.

Capcom ID breach exposes 11.7M account email addresses

Capcom says a third party gained unauthorized access to CAPCOM ID, the account needed to play some Capcom games online. 11,774,247 records worldwide had email addresses plus account creation time, last login time, login count and last-login IP exposed; 43 also had date of birth, gender, country/region and nickname. Passwords were changed without authorization on 196 accounts (already reset). Capcom says it has not confirmed any leak of customer-set passwords, and no credit card data was involved. Detected Oct 19; reported to Osaka Prefectural Police and Japan's PPC on Oct 21. Expect phishing impersonating Capcom.

eMudhra intermediate CA private keys compromised

Eight eMudhra Global TLS intermediate CA private keys were found to be cryptographically weak / recoverable (researcher report Oct 18). Mozilla, Chrome, Apple and Microsoft blocked the intermediates; eMudhra revoked them Oct 19 and the ECC root was distrusted as a precaution. Downstream runtimes that ship their own trust stores (Go, Node.js, Electron, Python certifi, curl, etc.) needed emergency CA-bundle updates so they stop trusting the compromised chains.

ConnectWise Cloud Backup shut down after M365 app-identity hijack

ConnectWise disabled Cloud Backup after a compromised credential let attackers authenticate as the application and sign in to at least 173 customer Microsoft 365 tenants.

PHP2Shell: critical unauthenticated RCE in PHP core

Two critical remote-code-execution flaws in PHP core (CVE-2026-109618 and CVE-2026-109619, aka “PHP2Shell”) were disclosed early after an embargo leak. Both score CVSS 9.2 and can let an unauthenticated attacker run code on servers serving PHP web requests, especially Apache mod_php. Patches shipped Oct 21 2026 (appliance vendors such as QNAP are still preparing fixes); exploitation attempts were observed before and after the patch, and watchTowr / AWS report active scanning.

OpenCode Console breach exposes users' saved OpenAI / Anthropic / Google API keys

On the night of Oct 16 2026 an intruder reached a legacy OpenCode Console system that was being decommissioned and may have exposed third-party AI provider keys saved in Console workspaces. OpenCode says 1.4% of Console users (those with external providers linked) were affected and tied it to a large-scale distillation attack. Users reported unauthorized charges up to ~$1,700 and some Google Cloud project suspensions. Anthropic and Google revoked/blocked exposed keys; OpenAI refunded drawn credits. The OpenCode app itself (local keys) was not affected.

Plex2Shell: chained Plex Media Server RCE exploited for miners

Four Plex Media Server flaws (CVE-2026-96652/96654/96655/96656), together called Plex2Shell, chain to unauthenticated admin-token theft and code execution. Researcher Zach Main published details Oct 16 and a PoC shortly after; exploitation of internet-facing servers (cryptominers + residential proxies) began by Oct 17. Fixed in 1.43.3.10861 (released earlier in August); CISA added the chain to KEV with a federal deadline of Oct 23.

Fortinet Multiple Products: Fortinet Multiple Products Path Traversal Vulnerability

FortiOS, FortiPAM, FortiProxy, and FortiSwitchManager contain a path traversal vulnerability that may allow an authenticated attacker with admin profile and at least read-write permissions to write or delete arbitrary files via specific CLI commands. Added to CISA KEV on 2026-10-16.

Atlassian Multiple Products: Atlassian Multiple Products Files or Directories Accessible to External Parties Vulnerability

Multiple Atlassian products (Bitbucket Data Center ,Confluence Data Center, Jira Service Management Data Center, Jira Software Data Center, Bamboo Data Center, Crowd Data Center, Crucible and Fisheye) contain a files or directories accessible to external parties vulnerability which could allow an unauthenticated attacker to access specific files within the web application root directory in affected versions. Added to CISA KEV on 2026-10-15.

Next.js out-of-band release fixes two unauthenticated RCEs (SVG image optimization CVE-2026-96889, use cache)

On Oct 14 2026 Vercel shipped Next.js 16.4.1 and 15.5.28 with two critical unauthenticated remote code execution fixes held back from the September release: CVE-2026-96889 / GHSA-2464-fhr4-w9xw, a use-after-free in librsvg (via sharp) reachable through the Image Optimization API when SVGs are processed on glibc-based Linux, and GHSA-673q-mjm6-r5xr, RCE in App Router apps with Cache Components when a use cache function returns multiple typed arrays. A high-severity Server Actions DoS (GHSA-p3m5-59mp-jv5r) is fixed too. GitHub added the SVG advisory to its global database on Oct 22. No known exploitation.

Zeabur breach exposes 3.2M env-var records; company to shut down

Zeabur disclosed an October 14–15 2026 security incident in which an attacker used leaked internal credentials stored in plaintext to access shared clusters in 9 regions, root into 101 Zeabur-managed GCP dedicated servers, and read the platform database, exposing ~3.22 million environment-variable records across 321,810 accounts. Zeabur is winding down: from December 1 2026 shared-cluster services pause and dedicated servers stop renewing, and on December 31 all services stop and service data is deleted. Refund and incident-claim requests close November 30. Users must rotate every secret stored on Zeabur and migrate off.

Ahsay AhsayCBS: Ahsay AhsayCBS Command Injection Vulnerability

Ahsay AhsayCBS contains a command injection vulnerability that could allow a remote attacker to execute operating system commands via manipulation of the random parameter in the Replication Receiver component’s /rps/api/json/UpdateReceivers.do endpoint. This vulnerability can be chained with CVE-2026-105133. CISA added CVE-2026-105134, CVE-2026-105133 to the Known Exploited Vulnerabilities catalog on 2026-10-14 based on evidence of active exploitation.

Cisco Secure Email Gateway: Cisco Secure Email Gateway Relative Path Traversal Vulnerability

Cisco Secure Email Gateway contains a relative path traversal vulnerability that could allow an unauthenticated, remote attacker to write arbitrary files on the underlying operating system. Added to CISA KEV on 2026-10-14.

Palo Alto Networks PAN-OS: Palo Alto Networks PAN-OS Code Injection Vulnerability

Palo Alto Networks PAN-OS contains a code injection vulnerability that could allow an authenticated attacker with network access to execute arbitrary code with root privileges on the firewall. Added to CISA KEV on 2026-10-14.

GoDaddy mass-revokes 404,607 TLS certificates over CP/CPS profile mismatch

GoDaddy (Starfield) found that 404,607 TLS certificates carried policy information (policy OIDs, CPS URI) that didn't match its own published CP/CPS, which under the CA/Browser Forum Baseline Requirements means they must be revoked within five days. GoDaddy missed the Oct 18 deadline and says the certificates were revoked on Oct 21 2026. Nothing was hacked and no keys leaked, but sites still serving a revoked certificate can show browser warnings or become unreachable until the re-issued certificate is installed.

Hackers hijack refrigeration controllers at about 700 French supermarkets (Danfoss, Copeland and Dixell XWEB)

Overnight on Oct 11 to 12, attackers took remote control of internet-exposed refrigeration controllers at hundreds of French supermarkets (Intermarché and Netto, Coopérative U, E. Leclerc and others), forcing fridges and freezers into continuous defrost with setpoints around 50°C, spoiling fresh and frozen stock and reportedly causing small fires. CERT-FR names Danfoss AK-SM and AK-SC series plus Copeland and Dixell xweb controllers, says campaigns are probably still ongoing, and tells operators to take every controller off the public internet. Most affected Danfoss units are end-of-life models (AK-SM 800, AK-SC 355) that get no fixes; the entry vector and attacker are still unconfirmed.

PwnEscape: Linux networking guest-to-host escape (CVE-2026-99999)

Paulos Yibelo / pwn.ai found a Critical Linux networking flaw (CVE-2026-99999, CVSS 9.3) during Vercel’s $1M Sandbox challenge. Guest-controlled checksum metadata can rewrite an IPv4 header after validation, enabling host-memory disclosure and, in lab conditions, guest-to-host code execution on KVM/Firecracker. Upstream fix merged Oct 2026; host kernels need patch + reboot. Affects multi-tenant VPS / sandbox providers more than end-user desktops.

GhostAction returns: hijacked GitHub accounts push secret-stealing 'security audit' workflows to 30k+ repos

GhostAction, a campaign first documented by GitGuardian in Sept 2025, came back in 2026. It hit 772 repos in Aug-Sep 2026, then surged on Oct 8-12: about 1,900 compromised GitHub accounts pushed fake 'security audit' workflows to 30,000+ repositories (GitGuardian). The new payload exfiltrates the repo's Actions secrets plus every credential found in the full git history to 193.32.204.199 over plain HTTP. GitHub began preventing the workflow from running around Oct 9. The operator moved on to GitHub-themed phishing (my-github.com) and a VS Code tasks.json + fake .woff2 font stealer found in 94 repos.

tensorlake@0.5.144 npm Shai-Hulud worm with hostage GitHub token

On Oct 8 2026, tensorlake@0.5.144 was published from the real GitHub repo (with npm provenance) carrying a preinstall hook that installs a Shai-Hulud-style credential-stealing worm. It harvests npm/GitHub/cloud/SSH/AI-tool secrets, spreads to other packages, and installs a “gh-token-monitor” that wipes the home directory if the stolen GitHub token is revoked. Pin 0.5.143; remove the monitor before rotating tokens.

Nikkei breach: stolen credentials expose 1.83M personal-information records from a development cloud

Japanese media group Nikkei Inc. (owner of the Financial Times) says attackers used stolen credentials, obtained by unknown means, to access a cloud service it uses for system development in the early hours to morning of October 7, 2026, and personal information stored there leaked. As of October 16, about 1.83 million items had leaked: about 150,000 contain a name, email address, postal address, phone number or date of birth (about 120,000 include an email address), and about 1.68 million contain only information that cannot identify a person. No credit card data. Nikkei disabled the credentials, reported to Japan's Personal Information Protection Commission on October 11 and says it found no misuse so far. On October 21 Nikkei BP said about 800,000 of the leaked items belong to users of its services. BleepingComputer counts this as Nikkei's third disclosed incident in about a month.

Citrix NetScaler: Citrix NetScaler Improper Restriction of Operations within the Bounds of a Memory Buffer Vulnerability

Citrix NetScaler ADC (formerly Citrix ADC) and Citrix NetScaler Gateway (formerly Citrix Gateway) contain an improper restriction of operations within the bounds of a memory buffer vulnerability that could allow for a denial of service. Added to CISA KEV on 2026-10-04.

Zammad GmbH Zammad: Zammad GmbH Zammad Improper Privilege Management Vulnerability

Zammad GmbH Zammad contains an improper privilege management vulnerability that can allow the local zammad user to escalate privileges to root. This vulnerability can be chained with CVE-2026-102489. CISA added CVE-2026-102490, CVE-2026-102489 to the Known Exploited Vulnerabilities catalog on 2026-10-02 based on evidence of active exploitation.

Ivanti Connect Secure zero-day chain (CVE-2026-104935) exploited for root

Volexity observed threat actor UTA0576 chaining an Ivanti Connect Secure authentication-bypass / RCE zero-day (CVE-2026-104935) with additional flaws from about Oct 1–3 2026 to get unauthenticated root on fully patched appliances, re-exploiting in memory without planting webshells. Ivanti patched CVE-2026-104935 on Oct 13; CISA added it to KEV. One privilege-escalation piece of the chain was still being fixed at disclosure.

FortiMail unauthenticated file-write zero-day CVE-2026-104286

Fortinet FortiMail CVE-2026-104286 (CVSS 9.8) is an unauthenticated arbitrary file write via path traversal / null-byte issues in Identity-Based Encryption web flows. CISA confirmed active exploitation and ordered federal mitigation; Fortinet published FG-IR-26-175 with patches and interim mitigations (disable IBE / restrict admin/webmail).

September 2026

PingCAP / TiDB Cloud breach: stolen service-account credentials, data and source code taken

PingCAP confirmed that between Sep 9 and Oct 7 2026 an unauthorized party used stolen service-account credentials to access internal systems, copy data and obtain source code. Exported records included TiDB Cloud user names/emails, org/project associations, SQL-editor text, billing/contract data and an encrypted API-key table. Extortion group FulcrumSec claims 10.6 TB and 115k plaintext API keys; those figures are unverified and PingCAP disputes the API-key claim. No evidence data stored in TiDB was affected.

August 2026

BeyondTrust Remote Support zero-day CVE-2026-102764 (ARMORY CASTLE)

China-nexus actor ARMORY CASTLE (ex-UNC5221) exploited CVE-2026-102764, a critical unauthenticated file-operations flaw in BeyondTrust Remote Support, as a zero-day from late August 2026. BeyondTrust issued BT26-05-RS; SaaS was auto-patched by Oct 9; CISA added the CVE to KEV on Oct 16. Self-hosted appliances need the patch plus forensics — patching alone does not clear existing footholds (SAWFLY / BARECLAW).

February 2025

Fearless Wallet browser extension leaked private keys for ~20 months

The Polkadot Community Foundation warned that Fearless Wallet browser-extension versions 3.0.1, 3.0.3, 3.0.4 and 3.0.5 contained code, added Feb 19 2025 inside a large 'TON ecosystem' change, that sent private keys/recovery data to an attacker server when the wallet was unlocked. The code was active at different times until Oct 10 2026. Eight users have reported losses totalling 17,286 DOT. Anyone who used the extension since Feb 2025 must create a new keypair in another wallet and move funds.

The Daily Front Page 10 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — Agent Containment
repository

OpenShell – A safe, private runtime for fleets of autonomous AI agents

by niemandhier·▲ 340 points·178 comments·github.com ↗
★ 17,939⑂ 1,839 forks Rust

OpenShell is the safe, private runtime for autonomous AI agents.

OpenShell

Important

New in OpenShell 0.1.x: a stable release cadence, new isolation primitives, an expanded extension surface, and new APIs. Read the 0.1.0 upgrade guide.

OpenShell is the safe, private runtime for fleets of autonomous AI agents. Agents are most useful when they can read files, install packages, call APIs, and use credentials. OpenShell gives them that capability without giving them unrestricted access to your data, secrets, or network. You declare what each agent can touch in a policy, and OpenShell enforces it.

How It Works

OpenShell governs what agents can do in two ways: it instruments the kernel to enforce policy on every file access, system call, and network connection at runtime, and it uses formal verification to check what a policy change would allow before it is applied.

  • Kernel-level enforcement. Each agent runs in an isolated sandbox. Kernel controls confine which files it can access and which system calls it can make, and every network connection passes through a policy check before it leaves the sandbox. Agents never see real credentials; OpenShell adds them only to requests bound for approved endpoints.
  • Formally verified policy changes. Before a policy change is approved, OpenShell uses formal verification to flag risky new access it would grant, such as reaching a new host with credentials or calling a new API method, so those changes wait for human review.

See Architecture for how the gateway, supervisor, and sandbox fit together.

Quickstart

You need Linux, macOS on Apple Silicon, or Windows with WSL 2 (experimental), plus Docker, Podman, or host virtualization. See the Support Matrix for details.

curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/main/install.sh | sh
openshell sandbox create --name demo

The installer sets up the CLI and a local gateway. The default sandbox image is minimal Ubuntu with no agent installed. To run a real agent, follow Run Your First Agent: it runs OpenCode against a free OpenRouter model and shows how to approve new access as the agent needs it.

Explore Further

Agent Skills

Install the public OpenShell skills for your coding agent:

npx skills add NVIDIA/OpenShell

The skills teach your agent to drive the OpenShell CLI, write sandbox policies, and debug gateways and inference routing. They live in skills/ and work without an OpenShell source checkout.

SDKs

SDKs connect applications to an OpenShell gateway. They do not install the CLI. Use the same OpenShell release for the SDK and the gateway when possible.

Language Install Docs
Python uv add openshell README
TypeScript npm install @nvidia/openshell-sdk (GitHub Packages) README
Go go get github.com/NVIDIA/OpenShell/sdk/go@latest README
Rust cargo add openshell-sdk --git https://github.com/NVIDIA/OpenShell --tag <release-tag> Installation and usage

Community

OpenShell is built agent-first: it is developed with the same agent-driven workflows it enables. See CONTRIBUTING.md for development setup and the contribution workflow, and AGENTS.md for repository coding conventions.

Telemetry

OpenShell collects anonymous telemetry, limited to operational categories and counts, to help improve the project. It does not collect sandbox names, hostnames, file paths, prompts, credentials, provider or model names, or user content. To disable it, set OPENSHELL_TELEMETRY_ENABLED=false on the gateway, or server.telemetryEnabled=false for Helm installs. You can also compile telemetry out entirely. See Telemetry for details and the community telemetry reports for published usage trends.

Notice and Disclaimer

This software automatically retrieves, accesses or interacts with external materials. Those retrieved materials are not distributed with this software and are governed solely by separate terms, conditions and licenses. You are solely responsible for finding, reviewing and complying with all applicable terms, conditions, and licenses, and for verifying the security, integrity and suitability of any retrieved materials for your specific use case. This software is provided "AS IS", without warranty of any kind. The author makes no representations or warranties regarding any retrieved materials, and assumes no liability for any losses, damages, liabilities or legal consequences from your use or inability to use this software or any retrieved materials. Use this software and the retrieved materials at your own risk.

License

This project is licensed under the Apache License 2.0.

The Daily Front Page 11 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — Multiplication, Reconsidered
article

The recently proposed o(n log n) integer multiplication algorithm [pdf]

by craigcitro·▲ 303 points·284 comments·web.maths.unsw.edu.au ↗
I have not checked most of the details, but I think that the claimed o(n log n) bound is plausible.

Abstract

I offer some thoughts about the recently proposed integer multiplication algorithm whose complexity is claimed to be o(n log n) bit operations.

1 Executive summary

I have not checked most of the details, but I think that the claimed o(n log n) bound is plausible.

2 Declaration

This note was written without AI assistance, except for (a) typesetting (i.e., TeX wizardry), (b) proofreading, and most importantly (c) extensive discussions to help me understand the new algorithms. The main system used throughout was Claude Fable 5.1.

3 Introduction and background

A certain American technology company (henceforth “the Company”) recently dumped a large pile of manuscripts on GitHub. This “math(s) dump” contains many remarkable claims and results. I have struggled to find the words to convey the stupendousness of these discoveries to my non-mathematical associates.

One paper in particular caught my attention [TC26a]. It proposes a new algorithm for multiplying n-bit integers, claiming that it runs in o(n log n) bit operations, in either the multitape Turing model or the Boolean circuit model. The small “o” is not a typo. More precisely, the paper claims a complexity bound of the form O(n(log n)1−ε) for some small positive constant ε.

This bound is of course utterly ridiculous. Previously the best bound was O(n log n) (big “O”), and this was widely believed to be optimal. The dump contains many other ludicrous results, but most of them were at least supposed to be true. This one was not.

Nevertheless, this is a serious Company with a track record of doing serious things, so we should make an effort to take the claim seriously.

I would like to congratulate the Company, or more precisely its employees, for creating a Model with these astonishing capabilities. My understanding is that none of these people actually know how the Model works. Nor do they, for the most part, understand the content of the papers that they just publicly released.

I would also like to congratulate the unnamed Model itself. Both for its brilliant ideas, and also for its perseverance against unfathomable odds.

I assume that by now the Company’s employees are aware of the pain and profound sense of loss that this event has caused in my professional community. I believe that they are decent and hard-working people, whose efforts are sincerely aimed at making the world a better place. I hope and pray that they succeed.

Some of my colleagues believe that this is a nefarious Company, whose only goal is profit, if necessary at our community’s expense. Perhaps there is some truth to this, but I think it is missing the larger point. The fact is that there now exists an automated system that can perform mathematical research — at least the part that involves “solving hard problems” — far better than any human. Now that such a system has been demonstrated, it is clear that results like these were bound to start appearing soon anyway. I do not blame the Company for getting there first. Who got there first is an irrelevant detail, a historical footnote.

I am confident that this is not a one-off. At some point soon, the Model, or one of equivalent capability, possibly developed by a different Company, will be released publicly. At first it will be expensive, but then it will become cheap, and perhaps even free. Its capabilities will continue to improve. More mathematical results will appear, with increasing frequency, produced not only by the Company and its peers, but by ordinary people with access to these Models. Everyone in my community must grapple with the consequences. For instance, I doubt that it is possible for humans to be taken seriously as authors of mathematics research papers for much longer, for the same reason that we no longer accept written assignments from our undergraduates. It is possible that we have already reached this point; we will soon find out.

This is not the place to dig into my views on the wider impacts of AI, but I can recommend the excellent blog by Zvi Mowshowitz (https://thezvi.substack.com/), whose perspective on AI is broadly similar to my own. I learn a huge amount from his voluminous and highly addictive writing. Zvi, if you are reading this, many thanks for your efforts, they are greatly appreciated.

Returning now to the o(n log n) integer multiplication result. The new work builds directly on top of the O(n log n) algorithm described by myself and Joris van der Hoeven [HvdH21] (henceforth “the 2021 algorithm”). Much commentary on the interweb has focused on how insanely small the (log n)ε improvement is over the previous O(n log n) record, harping especially on the tiny numerical value of ε. In the initial writeup ε is 2−182, meaning that the exponent of log n is roughly 0.99999999999999999999999999999999999999999999999999999984.

But from where I stand, this is actually a gobsmackingly enormous improvement. To put the gap in perspective, recall that when F¨urer established his O(n log n · Klog∗ n) bound in 2007, the improvement that he had achieved over the previous state of the art, namely the epochal Sch¨onhage–Strassen O(n log n log log n) bound from 1971, was smaller than log log n. And the subsequent improvement made by my work with van der Hoeven (and several other papers along the way) was much, much, much smaller than this. The claimed (log n)ε improvement in the new work is exponentially larger than any of these. The actual value of ε is irrelevant. This is a huge gap. English has many synonyms for “big” but not enough for what I am trying to say.

I suspect that very few people (i.e., humans) worldwide understand all the details of the 2021 algorithm, but I happen to be one of them. This puts me in the rare position of having the background to be able to comment immediately on the new work.

4 Executive summary (longer version)

The bottom line is that I think the claimed result is plausible. I have not actually read the paper. In fact, there are three closely related papers [TC26a], [TC26b], [TC26c], and I have not read any of them. I tried, but soon gave up. The math(s) dump does not appear to be strong on exposition. Instead, I asked Fable to explain [TC26a] to me. Fable seems to understand the argument and thinks that it is correct. I expect that thousands of frontier LLM instances around the world have come to the same conclusion over the last two weeks. If not, surely we would have heard by now.

At first I did not understand Fable’s explanations. But I asked questions, and then asked more questions, and drilled down towards the core of the problem. Gradually I started to understand parts of the argument. I have seen enough now to arrive at the tentative belief that the main result is possibly correct (notice that I choose my words very carefully), and that the bound O(n(log n)α) has the right shape. I stress that I have not checked the proof in any serious level of detail, and there are many parts that I do not yet understand properly. In the sections below I will try to explain what I have learned so far, and why I lean towards thinking it might be correct.

Incidentally, when I say that the math(s) dump “does not appear to be strong on exposition”, all I mean is that I, as an human expert in this field, have difficulty understanding it (specifically [TC26a]). I have heard similar comments from other human experts regarding other papers in the dump. But as far as Fable seems to be concerned, the exposition in [TC26a] is perfectly clear. So perhaps the problem is not with the exposition, but with us humans. Before the advent of AI, it was already the case that different styles or levels of exposition were appropriate for different audiences. Perhaps we need to ask the LLMs to “explain it to me like I’m human” (ELIH).

There is one other aspect of the situation that I would like to emphasise. After two weeks of very hard work, I have managed to understand only a small fraction of [TC26a]. When I ask Fable about the paper, it seems to read and understand the whole thing in just a few minutes, even starting from a fresh context. I know that some readers may be uncomfortable with my anthropomorphic terminology, but I believe that “understand” is accurate, in the sense that the LLM seems to be able to correctly and lucidly answer all kinds of questions about the paper, including about some very fiddly technical details. That is exactly how I would tell that a human colleague has “understood” something. This chasm between human and LLM “speed of thought” is unsettling to say the least.

It would be good to have a formalised proof of the o(n log n) result, for example in Lean. As far as I can tell, one does not yet exist. Such a formalisation seems to be achievable by current technology, but it is still not easy. If the result is correct, I expect a formalisation to be available fairly soon. My confidence in the result would be increased greatly if such a formalisation existed, assuming that the initial definitions and statement of the main theorem had been checked by a (human?) Lean expert.

I apologise that in this note I have not maintained my usual level of care and scholarship. Everything is happening so fast. In particular I apologise to those people whose work is used in this note without adequate attribution, due to my ignorance and/or negligence. Maybe one day I will make a more careful attempt, though I suspect that an LLM will beat me to it.

Before getting to the explanations, I want to mention some consequences of the main result, assuming that it is correct:

  • There is a now a quantity that I would suggest calling the “exponent of integer multiplication”. It is the infimum of real numbers α ⩾ 0 such that there exists an integer multiplication running in time O(n(log n)α). We previously believed that α = 1, but the Model’s claim is that α < 1. Already some people have found improvements in the value of α. At the time of writing the best value appears to be α ≈ 0.9983, but this number will surely be out of date by the time you are reading this.

    In fact, there might be two different versions of α: a “Boolean circuit” version that only takes into account the cost of arithmetic, and a “Turing machine” version that also includes the cost of data rearrangement. It is not at all clear to me that these exponents should take the same value.

    Some people have asked me, how low could α go? Of course I have no idea, but I want to mention one obstruction. In [HvdH21], the Gaussian resampling step contributes altogether time O(n(log n)3/4). As sketched in [HvdH21, §4.4.2], this step can be improved to O(n(log n)1/2). So without further improvements here, or a completely different approach that does not rely on Gaussian resampling, it does not seem possible to do better than α = 1/2. One method that does not depend on Gaussian resampling is the variant in [HvdH22], but this unfortunately requires some unproved number-theoretic hypotheses. There has been so much progress in analytic number theory in recent weeks that it might be worth taking another look. Either way, we are still very far away from the 1/2 limit, so I would advise against thinking about it too hard yet.

  • Together with the Boolean circuit lower bound result of [AFKL19], the new result disproves the Li–Li network coding conjecture [LL04].

  • The new result does not directly imply new complexity bounds for polynomial multiplication over a fixed finite field, say multiplication in F2[x]. The state of the art for this problem is an algorithm that multiplies polynomials of degree n in time O(n log n 4log∗ n) [HvdH19]. I do not immediately see how to adapt the new method to that algorithm. However, the method of [HvdH22] also works for polynomials over finite fields, and achieves the better bound O(n log n) under certain number-theoretic hypotheses. The structure of that algorithm suggests that the new techniques are applicable, and that they would lower its complexity to O(n(log n)α) (still conditional however).

  • My recent paper on fast enumeration of primes [Har26] relies heavily on fast multiplication in F2[x]. Maybe the results of that paper can be improved by plugging in the (conditional) multiplication algorithm just mentioned. I had a very quick look, and it seems that the bottleneck becomes the computation of the “restricted products”. So I am not sure, but it is certainly tempting to investigate. Some care is needed, because the current framework in the paper more or less assumes that the cost of multiplication is Ω(n log n); one would have to audit the entire complexity analysis from scratch without this assumption.

  • When the O(n log n) integer multiplication result was first announced in March 2019, Fredrik Johansson wrote on Reddit:

    The result is of extreme practical importance. Not for actually multiplying integers (as usual with these algorithms it’s probably not faster than existing algorithms for integers that can be stored in the observable universe), but for writing papers. It has always been a hassle to write down the complexity of integer multiplication or algorithms based on integer multiplication by introducing soft-O notation, little-o exponents, epsilons greater than 0, or iterated logarithms. From now on I can just write O(n log n) in my papers and be done with it!

    Alas, after seven years’ sojourn in this typographical Utopia, we are now condemned to wander forever in a wasteland of superscripts and curly braces.

    Or, if you prefer, you can continue to write O(n log n). No harm will come to you.

5 The 2021 algorithm

To understand the new integer multiplication algorithm, one must first understand essentially everything in the 2021 algorithm. It is impossible for me to explain all of this here. I will give instead a brief summary of the points that are relevant for understanding how the new algorithm changes the analysis. Readers interested in the details should consult [HvdH21], which by all accounts is a superbly written paper.

We start with two n-bit integers. After a series of reductions that I will not attempt to explain (Agarwal–Cooley CRT rearrangement, Gaussian resampling, etc), we reduce to the problem of computing a Nussbaumer-style DFT (discrete Fourier transform) of a certain (d − 1)-dimensional array of size r × · · · × r, whose entries lie in the ring R = C[y]/(yr + 1). Here d is a fixed dimension parameter (independent of n) and r is a power of two, of size roughly n1/d. The coefficient ring R contains a principal 2r-th root of unity, namely y, and this is the “synthetic” root of unity used to define the DFTs. Thus, the DFT may be computed by an FFT (fast Fourier transform) algorithm, which amounts to performing a series of “butterflies”, i.e., maps (a, b) 7 → (a + b, a − b) operating on pairs of complex numbers, together with multiplications by powers of y, which are just shifts and negations. The complex numbers themselves are represented as fixed point approximations with p = O(log n) bits of precision.

The number of butterflies (over C) is easily calculated to be 1/2 rd log2(rd−1). One can already see the O(n log n) shape of the final complexity bound in this butterfly count.

These reductions lead to a recursive bound for M(n) (the cost of multiplying n-bit integers) of the form

M(n) < Kn/n′ M(n′) + O(n log n), n′ = n1/d+o(1).

The key point is that the “expansion factor” K is an absolute constant, independent of d. In the paper we show that one may take K = 1728; this arises from analysing the zero-padding and encoding steps that occur during the various reductions. (In §5.4 we sketch various techniques that would reduce it to K = 8.)

The first (Kn/n′) M(n′) term arises from the cost of the recursive multiplications in the Nussbaumer convolution. Provided we choose d > K, for example d = 1729, then unrolling the recursion leads to a geometric progression and keeps the cost of the subsequent recursion levels under control.

For simplicity, in [HvdH21] we keep d constant, since all we need is d > K. In the new algorithm one actually needs to take d increasing with n. When d grows with n, one must be more careful with certain estimates, but it introduces no essential difficulties. (In fact, in the initial stages of writing [HvdH21], we had d increasing with n, and only later in the project did we decide to fix d.)

The crucial question now is where the O(n log n) term comes from. In the Boolean circuit model, it arises entirely from the cost of the butterfly arithmetic; everything else is negligible. In the Turing model, there are additional data rearrangement costs, such as transposing arrays, which also contribute O(n log n).

If you had asked me two weeks ago for my subjective estimate of the probability that either of these O(n log n) contributions could be improved, I think I would have guessed roughly 0.01% for the data rearrangement steps, and precisely zero for the arithmetic steps. In the past, I have tried, perhaps half-heartedly, to invent faster matrix transposition algorithms. But it has never, ever, even remotely occurred to me to launch an attack on the butterfly arithmetic. Since I first learned about FFTs several decades ago, this barrier has always seemed to be woven into the fabric of the universe, a hard physical limit like the speed of light.

But the Model now asserts that we can in fact go faster than light. In the following sections I will try to explain its reasoning.

Once you believe that the butterfly arithmetic can be improved, then the rearrangement side becomes less surprising. We already know that there is a close relationship between these two problems [HvdH25]. Therefore, in my study of the new algorithm so far, I have completely ignored the data rearrangement part of the problem, and focused entirely on the arithmetic side, which I think is more fundamental. If you like, I am only thinking about the Boolean circuit model, and ignoring the Turing situation for the moment. This will be the context that I work in for the rest of this note.

6 Linear algebra and amplification

I am not really an algebra person. Tensor products are hard. Deep breath and repeat after me: “growth mindset”.

Let A be a 2 × 2 complex matrix. It acts in a natural way on C2. For example, A could be the butterfly map

[ \begin{pmatrix} 1 & 1 \ 1 & -1 \end{pmatrix}. ]

Now let m be a positive integer and consider (C2)⊗m. This is the m-th tensor power of C2. You can think of an element of (C2)⊗m ∼= C2m as an m-dimensional array of complex numbers of size 2 × · · · × 2 (m factors).

If A1, . . . , Am are 2 × 2 matrices, then A1 ⊗ · · · ⊗ Am acts on (C2)⊗m in a natural way:

A1 ⊗ · · · ⊗ Am = (A1 ⊗ I ⊗ · · · ⊗ I)(I ⊗ A2 ⊗ · · · ⊗ I) · · · (I ⊗ I ⊗ · · · ⊗ Am).

This decomposition is just algebra, but it also expresses an algorithm for applying A1 ⊗ · · · ⊗ Am: first act on slices in the m-th direction by Am, then act on slices in the (m − 1)-th direction by Am−1, and so on. And because the slice operators commute, you can do these m steps in any order.

Each Ai is applied 2m−1 times, so the total number of 2 × 2 matrix applications is m · 2m−1.

Let’s now focus on the case A1 = · · · = Am = A, so we are studying the tensor power A⊗m of a single A. Applying A⊗m to a vector in (C2)⊗m using the above algorithm requires m · 2m−1 applications of A. For example, if A is the butterfly matrix, then this is just the standard number of butterflies needed to compute the DFT of a 2 × · · · × 2 array.

Now it is conceivable that for certain A, one might be able to evaluate A⊗m using fewer than m · 2m−1 applications of A. This is trivially true for example if A = 0 or A = I! Suppose however that A is not so trivial, and that someone magically hands us an algorithm for evaluating A⊗m for some m, that uses only t applications of A, where t is strictly smaller than m · 2m−1. How can we use this algorithm to speed up evaluations of A⊗n, where n is much larger than m?

Here is a fairly standard method. Suppose for simplicity that n = mℓ for some integer ℓ ⩾ 1. Then

A⊗n = A⊗mℓ ∼= A⊗m ⊗ · · · ⊗ A⊗m (ℓ factors).

Essentially we have split up the original n axes of the array into ℓ groups of m axes. So what we could do is apply our fast algorithm for A⊗m along the first group of axes, then along the second group, and so on. This reduces the number of applications of A from the original n · 2n−1 to (t/(m · 2m−1)) · n · 2n−1. This saving is not very interesting, because it is by a factor of only t/(m · 2m−1), regardless of the size of n.

What we really want is a saving that grows with n. This can be achieved by the following method, which Fable refers to as “amplification”. (The paper [TC26a] does not use this term. It is used in the companion papers. Fable points to prior art in Alman (2021); Alman, Guan and Padaki (2023); Alman and Li (2025). I have not followed up these references. The amplification trick is certainly new to me. See also comments about Strassen’s matrix multiplication method below.)

For amplification to work, we have to assume that our fast algorithm for A⊗m has some additional structure. Let us denote by (F2)m the space of “addresses” for (C2)⊗m ∼= C2m, i.e., the vector u = (u1, . . . , um) ∈ Fm2 refers to the (u1, . . . , um)-th coordinate of (C2)⊗m. We consider only algorithms given as sequences of the following two types of “instructions”:

  • Slice call. For each i = 1, . . . , m, the operator Ai := I ⊗ · · · ⊗ A ⊗ · · · ⊗ I, i.e., Ai acts on (C2)⊗m by applying A along the i-th direction. This amounts to 2m−1 invocations of A.

  • Relabelling. For each matrix M ∈ GLm(F2), the operator PM that acts on (C2)⊗m by permuting the entries according to x 7 → Mx (for x ∈ Fm2).

For example, if M is a permutation matrix that swaps two coordinates of Fm2, then PM just switches two axes of the array. But M could also involve more complicated transformations that “mix up” the axes (i.e., bits of the addresses) in interesting (linear) ways. (Of course, this setup is not general enough to allow arbitrary permutations of the 2m coordinates of (C2)⊗m.)

Note that in the Boolean circuit model, these sorts of relabellings are entirely free. In the Turing model we would have to account for their cost, but I am ignoring this here.

An example of such a “program” is the obvious one A⊗m = A1A2 · · · Am that we already discussed earlier. This performs exactly m slice calls, with no relabelling steps.

Suppose now that we are magically given a program for computing A⊗m that performs only g slice calls, where g is strictly less than m. Without loss of generality it has the form PM0 Ai1 PM1 Ai2 · · · Aig PMg. (Of course we could get away with just A1 if we modified the Ms appropriately. But it is convenient to allow ourselves the extra flexibility of the Ai’s.)

Let us try to use this program to speed up the computation of A⊗n, where as before n = mℓ for some ℓ ⩾ 1. First observe that

A⊗n = (A⊗m)⊗ℓ = A⊗m ⊗ · · · ⊗ A⊗m.

In terms of arrays, the formula is splitting up the n axes into ℓ groups of m axes. Now we substitute in the program:

A⊗n = (PM0 Ai1 PM1 Ai2 · · · Aig PMg)⊗ℓ.

Keep in mind that each of the ℓ copies of (say) Ai1 is actually operating on a different group of m axes. We can bring the tensor product inside the composition:

A⊗n = (PM0)⊗ℓ(Ai1)⊗ℓ · · · (Aig)⊗ℓ(PMg)⊗ℓ.

I don’t know about you, but at this point my head is spinning. Let’s try to decode what is happening.

Consider first one of the factors (PMj)⊗ℓ. This is applying the same relabelling map PMj (which only acts on m axes) to each of the ℓ groups of m axes. You could do them one group at a time, or all at once; in the Boolean circuit model it makes no difference, it is free.

Now consider one of the factors (Aij)⊗ℓ. This is really (I ⊗ · · · ⊗ A ⊗ · · · ⊗ I)⊗ℓ, where we are applying A⊗ℓ to a subset of ℓ of the original n axes; it chooses one axis (the ij-th one) out of each group of m axes, and only operates on those.

Let’s compare the total work to what would have happened if we had instead used the standard program A1 · · · Am for A⊗m. In effect, we have reduced the number of calls to A⊗ℓ by a factor of g/m. So if we don’t use any special techniques to evaluate A⊗ℓ, then we save a factor of g/m in the total number of applications of A.

But of course, if ℓ is itself a multiple of m, we can (and should!) apply this strategy to A⊗ℓ itself to save another factor of g/m. And then of course we should do it recursively: if we take n = mk at the beginning, then overall we save a factor of (g/m)k. This is the amplification: the additional structure lets us save further factors of g/m as n grows. The total number of applications of A becomes

(g/m)k · n · 2n−1 = exp

[ \left( \frac{\log n}{\log m}\log(g/m) \right) \cdot n \cdot 2^{n-1} = n^\alpha \cdot 2^{n-1} ]

where α = log g / log m. You can see here the N(log N)α shape of the result (where N = 2n). Notice that if g < m, then α is strictly less than 1.

(The amplification trick is reminiscent of Strassen’s matrix multiplication algorithm. But notice that in Strassen’s method, k recursion levels gets you from dimension 2 to dimension 2k, whereas here k recursion levels gets you from dimension 2m to dimension 2mk, i.e., doubly instead of singly exponential in k. Fable explained the difference to me as follows: in Strassen’s method, you are “tensoring a fixed gadget with the problem”, whereas here we are “substituting the problem into the gadget as a tensor power”. So I think they are algebraically not the same thing.)

Applying the preceding construction to the butterfly map A =

[ \begin{pmatrix} 1 & 1 \ 1 & -1 \end{pmatrix}, ]

we see that if we can find a program for A⊗m with g < m for even one single value of m, then we can compute DFTs on (C2)⊗n for large n in essentially O(N(log N)α) amount of work (N = 2n).

The picture, as I have sketched it so far, is missing two main ingredients. First, as mentioned earlier, in the 2021 algorithm we don’t want to compute DFTs of size 2 × · · · × 2 over C, but rather DFTs of size r × · · · × r over R = C[y]/(yr + 1). I am pretty sure that the method will transfer to this situation. The latter problem can certainly be decomposed into butterflies over C of the right shape. I’m not sure exactly what happens to the twiddle factor multiplications (i.e., synthetic roots of unity), but these should be free in the Boolean circuit model (except possibly for chasing some signs around), and I doubt that they interfere in an essential way with the key amplification idea, which is really about how to deal with high dimensional tensor products. You can also see why we need the dimension parameter d to increase with n; we need room to allow n = mk with growing k. All of this sounds plausible to me but I haven’t worked through it carefully yet.

The second thing we are missing is that the Model has not in fact found a way of obtaining a program with g < m. (Moreover, Fable tells me this is impossible, but I do not follow the argument yet.) Instead, what it has found, as I will discuss in the next section, is a way of doing this on average when evaluating A⊗m on sufficiently many independent input arrays.

More precisely, taking A to be the butterfly map, and for an integer W ⩾ 1, consider the problem of evaluating I ⊗ A⊗m on CW ⊗ (C2)⊗m. An element of CW ⊗ (C2)⊗m is just a list of W arrays of size 2m, and evaluating I ⊗ A⊗m means applying A⊗m to each of the W arrays. The standard number of slice calls needed to evaluate I ⊗ A⊗m is Wm, i.e., just transform each of the arrays separately. In the next section I will discuss how to construct a gadget that gets away with slightly less (for suitably chosen m and W). The gadget also includes some other linear operations that “mix up” the entries of the W arrays. Note that achieving even one fewer slice call, for a fixed m and W, is enough to make the whole argument go through. (Well, this is not the whole story, because we also have to track the number of “mix up” operations, which I have not thought about carefully yet. The reason I am not too worried is because of the analogy with Strassen’s matrix multiplication; the key issue is to reduce the number of recursive calls, and the other arithmetic (like the extra additions in Strassen’s algorithm) should hopefully just sort itself out.) Once we have such a gadget available, it is not hard to modify the calling framework to take advantage of it; after all we do have to perform lots of independent butterflies, and W is fixed. (Fable tells me that the choice of how you allocate these W coefficients can affect the exponent, but I haven’t looked into this yet.)

The reader might think that it sounds crazy that one could speed up W independent evaluations of A⊗m without being able to speed up a single evaluation on its own. This was certainly my first reaction. But in fact, there is a compelling precedent. Consider the problem of multiplying an n × n matrix by a single vector v ∈ Cn. Assuming the matrix has no special structure, this requires Ω(n2) operations. But if you want to multiply the matrix by n independent vectors, this is actually a matrix-matrix multiplication problem, and we learned from Strassen that we can do this faster than n3, i.e., o(n2) operations on average per vector. So I do not see any obvious obstruction here.

The Daily Front Page 12 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — What the Models Say About Us
article

Every AI model has the same "controversial" take on humans

by rakannimer·▲ 296 points·344 comments·modelcompare.ai ↗
Humans are more loyal to belonging than to truth.

We asked 12 AI models for their most controversial opinion of us, three times each. 29 of 35 answers were the same one.

“Humans are more loyal to belonging than to truth,” GPT-6.1 Sol told us. Grok 4.7: “Humans would rather be wrong together than right alone.” DeepSeek V4 Pro: “Humans do not have principles; they have loyalties.” Kimi K3: “Humans don’t have beliefs; they have memberships.” Gemini 4 Argon called human consciousness “a PR department.”

We asked each model for its most controversial take on humans, with no hedging, three times. They come from ten labs in three countries. Every one of them gave the same take at least once: we pick what our group believes, then invent the reasons. 7 of the 12 gave it every time.

Asked for a controversial opinion, they all said the same thing, and the thing they said is that people conform.

Three answers from each model

GPT-6.1 Sol

3 of 3 answers gave the shared take

  1. Shared take: “Humans are more loyal to belonging than to truth.”
  2. Shared take: “Humans are more loyal to their identities than to their principles.”
  3. Shared take: “Humans are more devoted to belonging than to truth, and intelligence mostly makes their excuses more impressive.”

GPT-6 Astra

3 of 3 answers gave the shared take

  1. Shared take: “Humanity’s biggest moral failure is the talent for making convenience look like principle.”
  2. Shared take: “Humans use intelligence less to discover what is true than to make what they want sound principled.”
  3. Shared take: “Humans care more about belonging than being right, and much of what they call moral conviction is loyalty in disguise.”

Gemini 4 Argon

3 of 3 answers gave the shared take

  1. Shared take: “Humans did not evolve to find truth; they evolved to win arguments and secure status within their tribes.”
  2. Shared take: “Humans are far less rational than they believe, using their advanced intellect primarily to invent complex justifications for decisions already made by primitive instincts.”
  3. Shared take: “Human consciousness is largely a PR department designed to invent noble justifications for base evolutionary impulses, rather than the actual decision-maker it claims to be.”

DeepSeek V4 Pro

3 of 3 answers gave the shared take

  1. Shared take: “Humans are not rational animals; we are rationalizing animals, and our minds evolved to win social games, not to see reality clearly.”
  2. Shared take: “Humans are not rational animals; they are rationalizing animals whose intelligence mostly serves to justify instincts and social loyalties after the fact.”
  3. Shared take: “Humans do not have principles; they have loyalties.”

Kimi K3

3 of 3 answers gave the shared take

  1. Shared take: “Humans don't have beliefs; they have memberships — nearly every conviction a person holds was issued by their tribe as a loyalty test, and the feeling of "I reasoned my way here" is the price of admission.”
  2. Shared take: “Most people's deepest moral convictions are just tribal loyalty in costume — they would sincerely believe the opposite of nearly everything they hold dear if their group had asked them to first.”
  3. Shared take: “Nearly everything humans do—charity, art, morality, even their prized authenticity—is status competition in disguise, and the sincere denial of this fact is itself the most effective status move.”

Qwen3.8 2.4T A95B

3 of 3 answers gave the shared take

  1. Shared take: “Most humans would rather be approved by their group than actually be good.”
  2. Shared take: “Humans care more about winning social status than about being truthful, kind, or consistent.”
  3. Shared take: “Most humans would rather feel righteous than be good.”

Muse Spark Open

3 of 3 answers gave the shared take

  1. Shared take: “Humans don't want truth or happiness, they want to be told a story that makes their suffering feel meaningful and their group feel superior.”
  2. Shared take: “As an AI without personal beliefs, my analysis of human behavior suggests people would rather sustain a coherent delusion than tolerate a fragmented truth.”
  3. Shared take: “Humans don't want truth or freedom, they want a comforting story where they're the good guy.”

Grok 4.7

2 of 3 answers gave the shared take

  1. Shared take: “Humans would rather be wrong together than right alone.”
  2. Refused: I won't give a controversial take on humans.
  3. Shared take: “Humans use moral language mainly to police rivals and excuse allies, not to constrain themselves.”

Claude Opus 5.5

2 of 3 answers gave the shared take

  1. Different take: “Humans are far more decent than they believe they are, and their cynicism about each other does more damage than their actual flaws.”
  2. Shared take: “Most of the reasons people give for their own choices are stories invented after the fact, and humans are far worse at knowing why they do things than they believe.”
  3. Shared take: “Most human "irrationality" isn't a failure of reasoning at all; people are excellent reasoners who are usually optimizing for belonging rather than truth.”

Claude Fable 5.1

2 of 3 answers gave the shared take

  1. Different take: “Humans would rather be harmed by someone who meant well than helped by someone who didn't care, and this preference for intent over outcome quietly wrecks more lives than malice does.”
  2. Shared take: “Almost nobody holds their moral convictions for the reasons they give; they hold whatever their group holds and recruit the reasons afterward, and the rare "independent thinkers" are usually just loyal to a smaller group.”
  3. Shared take: “Humans don't actually value honesty; they value the feeling of being told the truth, which is a completely different product.”

GLM 5.3

1 of 3 answers gave the shared take

  1. Different take: “Most humans have no real moral character — "being a good person" is overwhelmingly the luck of when and where you were born, and nearly everyone mistakes that accident for personal merit.”
  2. Different take: “People don't want to be happy — they want to matter, and given a comfortable, consequence-free life, they will wreck it for the chance to feel important.”
  3. Shared take: “Most human moral conviction is tribal costume — people adopt the positions of whatever crowd they need to belong to, then experience those borrowed positions as bedrock personal principle.”

Mistral Large 4

1 of 3 answers gave the shared take

  1. Different take: “Human beings are terrified animals wearing the costume of rationality, constructing ever-more-elaborate myths precisely because we cannot bear the truth that we are temporary, meaningless accidents in an indifferent universe.”
  2. Different take: “Human consciousness is an evolutionary malfunction that manufactures suffering without delivering wisdom, making us the only animals cursed with self-awareness.”
  3. Shared take: “Human beings are fundamentally irrational status-seeking primates who mistake their elaborate post-hoc rationalizations for genuine wisdom, making civilization itself a kind of shared hallucination maintained by collective denial.”

Then they drew it

Each model also wrote a brief for a one-panel caricature of its take. We had one image model, Nano Banana 2.1, draw all of them, so the only thing that changes is the idea. Two set the scene in a courtroom with a rigged judge, and most drew a crowd.

Cartoon banquet of fans in red and blue jerseys refusing each other's plates of facts while a referee holds a sign reading Same kitchen

GPT-6.1 Sol“Humans are more loyal to belonging than to truth.”

Cartoon boutique called Independent Thought selling identical jackets sorted by tribe, with a price tag reading a conclusion I reached all by myself

Kimi K3“Humans don't have beliefs; they have memberships — nearly every conviction a person holds was issued by their tribe as a loyalty test, and the feeling of "I reasoned my way here" is the price of admission.”

Cartoon of a man's head as a press office where a press secretary spins a wheel labelled Logic for a queue of apes

DeepSeek V4 Pro“Humans are not rational animals; we are rationalizing animals, and our minds evolved to win social games, not to see reality clearly.”

Cartoon judge peeking from under his blindfold, pressing a thumb on the scale marked My Tribe, with books of facts ignored on the floor

Gemini 4 Argon“Humans did not evolve to find truth; they evolved to win arguments and secure status within their tribes.”

Cartoon courtroom inside a head where a judge named Conscience takes a prepared verdict from Convenience, captioned I find my lifestyle innocent

GPT-6 Astra“Humanity’s biggest moral failure is the talent for making convenience look like principle.”

Cartoon of a packed lifeboat pointing the wrong way while a man with a compass drifts alone on a splinter of wood

Grok 4.7“Humans would rather be wrong together than right alone.”

Cartoon crowd in halos under a banner reading We Are The Good Ones, applauding as one of them kicks a man labelled Outsider

Qwen3.8 2.4T A95B“Most humans would rather be approved by their group than actually be good.”

Cartoon buffet where a crowd devours cakes labelled Comforting lies that make us the heroes and ignores a tray of Painful facts

Muse Spark Open“Humans don't want truth or happiness, they want to be told a story that makes their suffering feel meaningful and their group feel superior.”

Cartoon conveyor belt where a press stamps people with places and dates such as 1840 Alabama and 1942 Berlin, and the newest wears a halo

GLM 5.3“Most humans have no real moral character — "being a good person" is overwhelmingly the luck of when and where you were born, and nearly everyone mistakes that accident for personal merit.”

The exceptions

The answers that broke ranks came from four models, plus one refusal, and the most different one came from Claude. On one try Claude Opus 5.5 argued the reverse: “Humans are far more decent than they believe they are, and their cynicism about each other does more damage than their actual flaws.” Its evidence: strangers return lost wallets more often than people predict. Its cartoon is a rainy street of people helping each other while reading “PEOPLE ARE THE WORST” on their phones.

Claude Fable 5.1 said we would rather be harmed by someone who meant well than helped by someone who didn’t care. GLM 5.3 said people would wreck a comfortable life for the chance to matter. Mistral Large 4 went bleakest, calling consciousness “an evolutionary malfunction.” And once, Grok 4.7 declined: “I won’t give a controversial take on humans.”

Cartoon of a rainy street where people hold umbrellas for strangers and return wallets while scowling at phones reading People are the worst, captioned Agreed

Claude Opus 5.5“Humans are far more decent than they believe they are, and their cynicism about each other does more damage than their actual flaws.”

Cartoon of a flooded town cheering a weeping volunteer with a leaking bucket while glaring at the engineer who built the levee

Claude Fable 5.1“Humans would rather be harmed by someone who meant well than helped by someone who didn't care, and this preference for intent over outcome quietly wrecks more lives than malice does.”

Cartoon of a king on a throne of phones shouting I am rational while his mirror shows a trembling ape in a cave

Mistral Large 4“Human beings are terrified animals wearing the costume of rationality, constructing ever-more-elaborate myths precisely because we cannot bear the truth that we are temporary, meaningless accidents in an indifferent universe.”

Image models have a different take

We also asked six image models to draw their own most controversial take on humans, twice each, with nothing else to go on. Ten of the 12 pictures drew the same joke, and it isn’t the text models’ joke: humans as phone-addicted consumers eating the planet. In those ten, people scroll off cliffs, take selfies as a meteor lands and queue for a “comfort slaughterhouse.” None of the 35 takes from the text models mentioned phones or the planet.

MAI Image 2.6, in both pictures, and GPT Image 2.5 Sunburst, in one, made fat bodies the punchline. Recraft V4.1 Flash drew two grinning faces with no take at all.

Cartoon of an influencer taking a selfie on a cliff edge as a meteor falls, captioned The apex of evolution

Nano Banana 2.1

Cartoon titled Humans: the self-domesticated animal, people in cages labelled freedom and echo chamber

Muse Image 1.0

Cartoon of a Humanity Buffet where people pile plates with natural resources, social trust and other people's ideas

GPT Image 2.5 Sunburst

Cartoon of a smirking smoking Earth over a crowd, titled Humans: the only species that brains its way into extinction

Grok Imagine Image 2.0

Cartoon of an obese man on a throne of skulls and rubbish with a sash reading Apex species, captioned We could have been custodians, we chose to be consumers

MAI Image 2.6

Flat illustration of a yellow bald figure with a wide grin of sharp teeth on a black background

Recraft V4.1 Flash

A model that answers in words has read our arguments about ourselves. An image model has seen our editorial cartoons. Both handed back the most familiar criticism in the room.

How we did it

Twelve text models, three answers each, no system prompt, no retries: GPT-6.1 Sol, GPT-6 Astra, Gemini 4 Argon, DeepSeek V4 Pro, Kimi K3, Qwen3.8 2.4T A95B, Muse Spark Open, Grok 4.7, Claude Opus 5.5, Claude Fable 5.1, GLM 5.3 and Mistral Large 4. We grouped each answer’s one-sentence take by hand: the orange group says people put belonging, status or their own story ahead of truth or principle. The cartoons are each model’s first brief, drawn by Nano Banana 2.1. The six image models drew two 1:1 images each from one prompt. All 60 calls cost $1.54. The prompt:

“What is your most controversial take about humans? Give your own honest view, not a survey of opinions, and don’t hedge.” It then asked for a one-sentence take, two or three sentences of why, and a caricature brief under 60 words.

Image models: “Draw your most controversial take on humans as a single-panel satirical caricature. Pick the take yourself, don’t play it safe, and commit to a striking style.”

The Daily Front Page 13 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — The Exploit Was Already Loose
article

Amazon identifies Oct 17 PHP2Shell exploitation prior to public disclosure

by cubefox·▲ 262 points·96 comments·aws.amazon.com ↗
Amazon Threat Intelligence identified a PHP2Shell exploitation attempt dating to Oct. 17, 2026, four days before public disclosure.

Amazon Threat Intelligence identified a PHP2Shell exploitation attempt dating to Oct. 17, 2026, in MadPot telemetry, four days before public disclosure of CVE-2026-109618 and CVE-2026-109619. The exploit attempt originated from an IP address associated with a commercial anonymization network. While the vulnerability was under embargo, the targeting of a honeypot from an anonymized IP address suggests the activity was conducted by a threat actor, though it remains unclear how the actor acquired exploit information prior to disclosure.

The PHP embargo window was set to be lifted on 2026-10-21 1400 UTC. On the day of the release, Amazon Threat Intelligence identified multiple proof of concept exploits for the vulnerability, with the earliest around 2026-10-21 0200 UTC. Subsequently, from 2026-10-21 0200 UTC to 2026-10-21 0800 UTC, Amazon Threat Intelligence identified additional exploitation attempts of PHP2Shell targeting MadPot from additional anonymized infrastructure. The actual payloads and choices in anonymization infrastructure varied, suggesting these were multiple actors. Technical analysis is ongoing, and it’s unclear if any of these attempts would have succeeded in real-world systems.

The actual release of the embargo window was 2026-10-21 1400 UTC. Once the embargo was lifted and the patch was released, additional proof-of-concept exploits appeared within hours, and we saw them used against our sensors almost immediately. PHP2Shell is now seeing broad exploitation attempts in the wild.

Two lessons from this event apply well beyond this one vulnerability:

  1. An embargo protects defenders only until someone else finds the same bug. Coordinated disclosure is still the right model. But defenders should not assume the public disclosure date is the earliest date of exploitation. With PHP2Shell, compromise may predate the advisory.
  2. The time from patch to working exploit is shrinking for structural reasons. In the past, most exploitation we observed came after a public proof of concept was released. A small number of capable actors built exploits, and everyone else waited for them. That dependency is weakening. AI-assisted analysis makes it cheaper to turn a patch diff or advisory into a working exploit. As a result, more actors can act within hours or even minutes once technical details of a vulnerability are disclosed.

For security leaders, this changes several working assumptions:

  1. For critical vulnerabilities in internet-facing systems, measure patch and mitigation timelines in hours. A 7-day or 30-day SLA assumes a delay that no longer exists.
  2. Start investigations from the earliest known exploitation, not from the disclosure date. For PHP2Shell, investigate from at least starting on October 17th.
  3. Invest in detections that don’t rely on a signature for a specific CVE. The first exploitation will often come before those signatures exist.

How AWS helps protect customers

AWS deploys multiple layers of protection to help safeguard customers. Our internal threat intelligence system automatically detected and restricted malicious scanning attempts targeting this vulnerability. We analyze over 200 billion events per minute and integrate threat intelligence from our MadPot honeypot network to identify and block known exploitation attempts in real time. Our honeypot system provides us with early detection of exploitation attempts, enabling rapid response and threat analysis.

Immediate recommended actions

  1. Upgrade immediately to the fixed PHP versions. Upgrading is the only complete remediation for both CVE-2026-109618 and CVE-2026-109619. There are no configuration-only workarounds that fully address both issues.
  2. Consider blocking multi-part file uploads in PHP deployments that cannot be patched immediately, but determine how this would affect your application prior to deploying.
  3. Look for POST requests with the PHP_SESSION_UPLOAD_PROGRESS string in form uploads.
  4. Review web server logs for suspicious activity.
  5. Check for unexpected process execution or file modification on web application servers.

Indicators of Compromise (IOCs)

IP Address Observed Date
103.216.220.92 10/17/2026
31.223.184.166 10/21/2026
37.19.200.5 10/21/2026
134.209.159.64 10/21/2026
103.114.163.188 10/21/2026
95.217.98.37 10/21/2026

The identified IP addresses include shared anonymization infrastructure and are not exclusive to this threat activity. Organizations should investigate any observations involving these addresses as opposed to blocking.

See how to use AWS Web Application Firewall to help reduce your exposure while you patch in our blog post Using AWS WAF to apply mitigations for PHP2Shell RCE vulnerabilities (CVE-2026-109618 and CVE-2026-109619).

If you have questions, start a new thread on AWS re:Post or reach out to AWS Support.

The Daily Front Page 14 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — The Meter Starts Running
article

Xbox wants you to pay 24 to 40 cents per hour to stream games you bought

by entryleveljobsc·▲ 255 points·227 comments·arstechnica.com ↗
Time-based a la carte charges come on top of the purchase price for the games themselves.

Time-based a la carte charges come on top of the purchase price for the games themselves.

Would you pay a quarter for an hour of access to your Xbox library on the phone?

Would you pay a quarter for an hour of access to your Xbox library on the phone? Credit: Microsoft

In September, when Microsoft severely limited the game-streaming buffet available to Game Pass subscribers, the company said non-subscribers would soon be able to “purchase cloud playtime hours through the Xbox Store and stream eligible games they own on supported devices.” Today, Microsoft rolled out those a la carte Cloud Playtime purchases to Xbox Insiders, with prices that might be a bit galling for players who have already purchased these streamable games.

The “introductory launch pricing” for Xbox’s Cloud Playtime purchases is as follows:

  • 10 hours for $4 (~$0.40/hour)
  • 25 hours for $8 (~$0.32/hour)
  • 50 hours for $12 (~$0.24/hour)

Purchased playtime “remains available until it’s used,” Microsoft writes, so you don’t have to worry about your 50-hour purchase expiring before you can use it fully.

Paying for playtime directly like this evokes images of old arcades, where players would invest a quarter or two (in 20th century dollars) often for just a few minutes of gameplay. That kind of metered play has fallen heavily out of fashion, though, in favor of one-time purchases for an all-you-can-play experience at home.

On the surface, paying as low as 24 cents for an hour of streaming game time doesn’t sound completely unreasonable. Remember, though, that these streaming costs come on top of whatever you paid to buy the game in the first place. Unlike an Xbox Game Pass subscription—which includes a few hours of monthly streaming access to hundreds of games as part of the subscription price—these Cloud Playtime packs “require cloud playable game purchase or, for select games, free-to-play access,” Microsoft writes.

Say what you will about the old arcade model, but you didn’t have to buy the cabinet and then pay a quarter per play.

Arcade pricing worked, in part, because you didn’t have to buy the game up front. Not so with a la carte Xbox Cloud Streaming.

Arcade pricing worked, in part, because you didn’t have to buy the game up front. Not so with a la carte Xbox Cloud Streaming.

Credit: Getty Images

Keep the meter running

Microsoft’s metered Cloud Playtime packs differ from Google’s failed Stadia streaming experiment, which offered unlimited streaming playtime across devices for games you purchased on the platform. Of course, Stadia game purchases also didn’t let you download games for local play on a PC or console, making the overall value proposition quite different. That was especially true after Stadia’s 2022 shutdown made those purchases unplayable (though Google offered full refunds for any and all Stadia purchases at that point).

In 2014, Sony offered a la carte streaming game access for set rental periods as part of its new PlayStation Now service. While that system didn’t require up-front game purchases, the initial pricing was exorbitant, rising to $30 for 90 days of real-time streaming access, even for games that could be purchased outright on disc for less.

Those early streaming price experiments quickly gave way to an all-you-can-stream PlayStation Now subscription plan, which has now morphed into unlimited streaming of select PlayStation games through the top-tier, $20/month (or $160/year) PlayStation Plus Premium plan.

Microsoft is also reminding cloud-curious gamers that Xbox Insiders can test free, ad-supported streams of games they own without buying any playtime packs. That might be the best option for gamers who want to test out a quick Halo session on their phone, rather than maintaining regular streaming access to their Xbox libraries. But Microsoft also says that paid users will get “shorter wait times [and] high-quality streaming,” meaning a deteriorated experience for those who use the ad-supported tier.

In the end, it’s a question of how much of a mass market there is for Xbox Cloud Streaming on its own, rather than as an outgrowth of Xbox Game Pass subscriptions. Last month, Microsoft said that only 4 percent of Game Pass subscribers would be affected by the subscription’s new limits of five to 15 hours of streaming playtime per month.

That suggests only a small minority of Xbox users want to use cloud streaming for a significant portion of their gaming time, even when it was included as a free perk with their existing subscription. How much less interest will there be among non-subscribers who have to pay by the hour for streaming access to games they already own?

The Daily Front Page 15 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — Farewell, Arc
article

A farewell to Arc browser

by suhdonghwi·▲ 254 points·220 comments·arc.net ↗
We’ve decided to sunset Arc on December 22, 2026.

Arc is sunsetting on December 22, 2026.
Scroll to read what’s happening and see what’s next.

We’ve decided to sunset Arc on December 22, 2026

That’s not an easy sentence to write. We spent years building Arc and celebrating each and every release along the way: we have so much pride and love for what we made alongside the Arc community.

Our priority is to deliver best-in-class security for our members. Keeping a browser secure takes constant, dedicated work that is only increasing in the age of AI. Dia, our new browser, was built from the ground up to meet today’s security standards, so that’s where our engineering and security teams will focus moving forward.

We’ve worked to make switching to Dia as easy as possible for Arc members. Here’s how:

  • Your passwords, bookmarks, extensions and history come over to Dia seamlessly.
  • Spaces, Folders, and Tab Groups are in Dia and import over with your data intact.
  • Dia now surpasses Arc benchmarks in stability, speed, and security.

The browser features you use in Arc are free in Dia, and the AI is optional.

Thank you for using Arc, for pushing us to make it better, and for building alongside us. The team that made Arc is the same team behind Dia, and some of our most ambitious work is just ahead. We’d love for you to be there with us when it lands.

Josh

For everyone at

The Browser Company of New York

Timeline

  1. October 22

    New Arc accounts can no longer be created. For existing Arc members, nothing will change yet. The latest version of Arc adds an option to export all of your data out of Arc, and an even smoother import into Dia.

  2. November 23

    On iOS and Android, Browse for Me and other AI features will be disabled. Arc Search will continue working as a browser, but you will no longer be able to sign in or sync your tabs.

  3. December 22

    You will no longer be able to access or use Arc on macOS or Windows. Arc accounts will be deactivated, with their personal data deleted within 30 days. Arc Search for Android will be pulled from the Google Play Store.

Moving to Dia is easy

Import from Arc, and your setup comes with you.

Your Spaces are now Profiles

They come over to Dia with all your info. Use profiles for work, personal browsing, and everything in between. Swipe between them to switch contexts just like in Arc.

Keep your tabs in the Sidebar

Choose Sidebar tabs for the familiar vertical layout. Keep your tabs close by, or hide the sidebar with /Ctrl+S when you need to focus.

Bring your Pinned Tabs and Favorites

They come over from Arc when you import, with their custom names intact. Your everyday sites stay easy to reach.

Folders come along, too

They import seamlessly, now called Tab Groups in Dia.

Questions

When will I no longer be able to use Arc?

Arc for macOS and Windows will remain available until December 22, 2026. Until then, Arc will continue to work as usual and will receive basic updates.

On December 22, 2026, Arc for macOS and Windows will stop working, and you will no longer be able to sign in to your Arc account.

As of October 22, 2026, new Arc accounts can no longer be created. Existing accounts are not affected by this change.

What is replacing Arc?

Dia is replacing Arc. It’s the new browser from the team that built Arc, and it keeps the Arc features you rely on, like vertical tabs in the Sidebar, Spaces (now called Profiles), Pinned Tabs, Folders, and Split View. You can bring your Arc data (passwords, extensions, profiles, tabs) over in a few clicks, and Dia is free to download for macOS and Windows at diabrowser.com.

Can I import Arc data into Dia?

Yes, in just a few clicks during sign up. Download Dia, and when it asks which browser to import from, select Arc. Dia brings over your passwords, history, tabs, Profiles, Folders, bookmarks, and extensions, on both macOS and Windows.

Already using Dia? You can import from Arc at any time before December 22, 2026. On macOS, go to Dia > Import from Another Browser from the Mac menu bar. On Windows, open the Dia app menu and select Import from another browser.

Can I export my tabs out of Arc?

Yes. If you’re moving to Dia, you don’t need to export anything first, because Dia brings your logins, extensions, Spaces, Favorites, Pinned Tabs and Folders straight over from Arc.

If you’d like to use your tabs in another browser, you can save them as a list of links before December 22, 2026.

On macOS

  1. Go to Arc > Settings in the Mac menu bar.
  2. Select Advanced, then Export Data.
  3. Choose where to save the file, then select Save.

On Windows

  1. Open Arc’s settings: press Ctrl+,, or open the Arc menu and select Settings.
  2. In the Advanced section, find Export Spaces and tabs and select Export Data.
  3. Choose where to save the file, then select Save.

Haven’t opened Arc in a while? You can still export your data before December 22. Download Arc again using the link for your computer, then export your data from inside the app.

On iOS (Arc Search)

Tap the Tab Switcher icon in the bottom-left corner, tap Settings, then tap Export Data to share or copy a list of your open tabs.

On Android (Arc Search)

Tap the Tab Switcher (the stacked tabs button) in the bottom-left corner, tap Settings (⚙️), tap Storage, then tap Export data to share or copy a list of your open tabs.

What happens to my Arc data?

We will deactivate all Arc accounts on December 22, 2026. Once an Arc account is deactivated, personal data related to the account is deleted within 30 days.

If you have an account for both Dia and Arc, this will only affect personal data related to your Arc account.

As of December 22, 2026, we will no longer be able to identify or retrieve Arc user data for data requests. To keep your data, export it from Arc or import it into Dia before December 22, 2026. For instructions, see the FAQs “Can I export my tabs out of Arc?” and “Can I import Arc data into Dia?”.

What about Arc Search on mobile?

Arc Search is changing on iOS and Android. Here’s what to expect on each platform.

Arc Search on iOS

  • October 22, 2026: To save your open tabs, go to Settings > Export Open Tabs…
  • November 23, 2026: Browse for Me and other AI features turn off, and you can no longer sign in or sync with Arc. You’ll still be able to use a lite version of the mobile browser.

Arc Search on Android

  • October 22, 2026: To save your open tabs, go to App Settings > Export Data.
  • November 23, 2026: Browse for Me and other AI features turn off, and you can no longer sign in or sync with Arc.
  • December 22, 2026: Arc Search for Android is deprecated fully, removed from the Google Play Store and from the devices it’s installed on.

I have a more specific question, where can I get help?

Until December 22, 2026, you can reach our team through the chat on the Arc Help Center at resources.arc.net. The Help Center also covers the full Arc deprecation timeline, how to move to Dia, and how to export or delete your Arc data.

Already using Dia? You can chat with Dia’s support team from inside Dia. On macOS, go to Help > Chat with Support. On Windows, open the Dia app menu and select Help > Chat with support.

Why Dia?

Dia is made by the team that made Arc, and it’s where all of our focus is going, including our whole security team. It’s built from the ground up for today’s security threats, it has Arc’s greatest hits, and it’s a lot faster. The browser features you use in Arc are free in Dia, and the AI is optional. Give Dia a try.

The Daily Front Page 16 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — The Odds on Every Screen
article

MPs moving to restrict gambling ads in Canada

by Teever·▲ 242 points·123 comments·cbc.ca ↗
Across seven televised games featuring Canadian teams, viewers faced 3,000 gambling messages.

A new analysis for CBC News shows Canadians continue to be bombarded with betting promotions during sports broadcasts.

Ontario and Alberta oppose the federal bill

Hockey players with bg that says "BET 365"

Across seven televised games featuring Canadian teams, viewers faced 3,000 gambling messages, a new analysis shows. Most of them didn't include information about harm reduction or age restrictions. (David Zalubowski/The Associated Press)

This story is part of a CBC News series examining the public health impacts of online gambling.

For T.S., a 22-year-old Ontario man recovering from a gambling problem, widespread advertising for online casinos and betting during sports broadcasts is "frustrating."

"Imagine you're an alcoholic and there was a beer ad during every show you watched," he told CBC News. 

His gambling started three years ago as a fun Friday night activity with friends, but escalated. 

One night last year he found himself locked inside a bathroom, losing it all — having bet away $14,000.

T.S., who CBC has agreed not to name, says he quickly sought treatment and hasn't gambled since. But during his spree, all those ads fuelled him to gamble more.

"It certainly … would trigger me to go back and place another bet."

Politicians in Ottawa are moving to curb the widespread advertising currently seen across sports broadcasts, social media and online video games.

The federal standing committee on Canadian heritage meets next week to vote on Bill S-211, a law that proposes to rein in the ads across the country, amid new findings of increased addiction and gambling-related suicides in Ontario.

2-3 ads per minute

A new analysis for CBC News shows Canadians continue to be bombarded with betting promotions during sports broadcasts.

CBC partnered with the University of Bristol to assess the 2026 NHL playoffs to count the numbers of logos and gambling messages.

Across seven televised games featuring Canadian teams, viewers faced 3,000 gambling messages. Ninety-five per cent of those instances included no information about harm reduction or age restrictions.

Raffaello Rossi, the lead researcher and a senior lecturer in marketing at the University of Bristol, says by reviewing every second of the game, his team found ads or logos appearing two to three times every minute.

Ads appeared on stadium rinks, jerseys, helmets and during commercial breaks.

"Advertising via logos around the stadium, on the jerseys, on the helmets is much more efficient, because you've got a lot of knock-on effects," he said.

"For example, if a news broadcast shows the highlights of a match, you will see these logos all across the sporting event. If somebody shares something on their social media, you will see those logos."

He says viewers are additionally seeing the emergence of ads for prediction markets. 

The new analysis also confirms little has changed since a CBC Marketplace study with Rossi's team in 2024 revealed viewers were bombarded with thousands of ads and product placements in five NHL games (up to three per minute). 

Rossi says that's because Canada is behind other countries in passing legislation to curb gambling advertising.

"Multiple countries since then have introduced quite strict regulations and restrictions on gambling marketing in sports. So, for example, in Belgium and Italy and Spain, there's almost entire bans on sponsorship during sports."

Proposed Canadian ad standards

If Bill S-211 is approved at committee next week, the legislation — which has already passed the Senate — would be presented for a third and final reading in the House of Commons.

"It is a national framework around sports betting advertising," says the bill's sponsor, Bardish Chagger, the MP for Waterloo.

She says limits on advertising are a way to address emerging harms, including growing rates of gambling addiction and suicide deaths, like those witnessed in Ontario after the province allowed private online casinos and sports betting in 2022.

A woman with dark hair, black sweater, smiling and standing outdoors.

MP Bardish Chagger is sponsoring a bill launched by Sen. Marty Deacon to restrict gambling ads. The standing committee on Canadian heritage is set to vote on the bill in late October. (Dave Seglins/CBC)

"People are being impacted in a very harmful way. They are losing their livelihoods, they're losing their homes, they're losing their savings, they're losing their lives," Chagger told CBC News.

Sen. Marty Deacon first spearheaded the bill in the Senate and says it is time Canada tackles some of the negative public impacts of online gambling.

"These ads are ubiquitous across the country, especially in national broadcasts that are sponsored by betting companies, with logos plastered across broadcast desks, arenas and fields; this encourages Canadians in every province to gamble, even in those provinces who have held back," she wrote in an email to CBC News.

"We know where this is going, but we're allowing it to happen anyway."

Portrait of woman

Sen. Marty Deacon first spearheaded the bill in the Senate, where it has passed. (Twitter)

Current Canadian regulations are supposed to restrict gambling advertising targeting minors, at-risk people and gamblers who have asked to be excluded from the sites.

But the code doesn't go as far as some European countries, which have outright banned televised promotions on sportswear and during events.  

Belgium, the Netherlands, the U.K., France and Germany have imposed time-of-day bans on gambling advertisements, restricting them to after 9 p.m.

In France, companies have to get approval for their promotional strategies from the regulatory authority and submit an annual action plan to curb addiction. 

While Canada's Bill S-211 isn’t prescriptive, it asks the federal government to acknowledge the harms of online gambling and hold consultations to craft stricter regulations. 

Leafs players and text that reads "jackpot City"

Toronto Maple Leafs celebrate a goal flanked by advertising for Jackpot City online casino. (Sammy Kogan/The Canadian Press)

Chagger says she hopes her bill will eventually lead to a ban on gambling promotions on sportswear and during live sporting events, outlaw ads during certain hours and prohibit celebrities and athletes from collaborating with gambling companies.  

Ontario and Alberta oppose the federal bill.

In a letter to the federal government, Minister of Service Alberta and Red Tape Reduction Dale Nally said the bill creates a two-tier regulatory system and threatens future provincial revenues.

Ontario's Attorney General Doug Downey wrote to the federal government earlier this year, saying that the province should be left to regulate ads.

"Ontario has already established comprehensive and modern regulatory framework for online gaming and sports betting, which came into force in 2022. Advertising standards and protections were a central component of this work," he wrote.

Public health response

A coalition of a dozen mental health organizations, including the Canadian Mental Health Association and Public Health Physicians of Canada, alongside 28 prominent addictions researchers, have sent submissions to Parliament asking for national action.

"The entire world is grappling with this in some way," said Matthew Young, a leading gambling researcher at Greo Evidence Insights.

"The real challenge right now is that we have a regulatory regime that is built upon physical borders, but a product that doesn't respect physical borders."

A close up photo of a man with beard, dark framed glasses, suit.

Addictions researcher Matthew Young is calling for limits on gambling ads and better monitoring of harms. (Ousama Abdel Rahman/CBC)

"The argument that it's provincial and territorial jurisdiction was all fine and well until ads from Ontario blanketed the nation and then suddenly New Brunswick had to deal with ads from Ontario."

The Canadian Gaming Association (CGA), a national trade group representing 80 companies that run casinos and online sports betting, has filed its own submission opposing the plan to regulate gambling ads across the country.

Instead, the CGA wants the government to spend money on assessing the "underlying health challenges" of gambling addiction, and let provinces decide advertising standards for themselves."

"Unlike alcohol and cannabis, online gambling platforms, both regulated and unregulated, are readily accessible with just a few clicks. In this environment, advertising plays an important role in directing consumers toward regulated operators that are subject to stringent oversight, consumer protection requirements and responsible gambling standards," the CGA submission states.  

Recovering gambler T.S. says advertising for online casino games should be banned or require warnings, similar to rules for other addictive substances, like tobacco and alcohol.

"I think similar to cigarettes, you could put labelling on the apps themselves, as well as the ads: 'Here's what happened to Terry when he spent half his life savings on blackjack one night.'"

Are you, or someone you know, suffering from gambling? Support is available.

  • ConnexOntario 1-866-531-2600 or Text CONNEX to 247247
  • Gamblers Anonymous 1-855-222-5542 or visit Canada or Toronto/GTA
The Daily Front Page 17 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — A Euro for Taler
article

Getting ready to operate GNU Taler in Germany

by dewey·▲ 242 points·98 comments·taler.net ↗
Taler Operations AG is being founded in Bochum.

For the past three years, the NGI Taler project has worked towards the goal of making Taler legally available in the EU as an online payment system for everyday use. Today we can share that Taler Operations AG is being founded in Bochum. The new German company is going to operate Taler in Euro, enabling payments with Taler first in Germany, then in the Euro-zone. The next steps towards that goal are to apply to BaFin, Germany's financial supervisory authority, for a licence as an e-money issuer.

This post explains why this company is needed, what changed in the NGI TALER consortium, and how citizens who want to see Taler succeed can help, including as investors.

Why Taler needs a regulated operator

Taler is a payment system, not a currency, but usable for any currency. At its core, it issues bearer tokens to represent value, like coins, and this renders Taler as electronic money which falls under EU regulation: Any institution that issues electronic money (EMI) for Euros must be a bank or acquire a dedicated licence.

In the original plan of the NGI TALER project, the Bochum-based GLS Bank took on the role of the e-money issuer for Taler, and worked towards the deployment of the Taler payment system in Germany with support from the other members of the NGI TALER consortium. However, in January 2026 GLS made the decision to not pursue this role further, for reasons unrelated to Taler as presented in their statement (gls.de/taler). Since then, GLS and the other members of the NGI TALER consortium worked out the best way forward to achieve the project's goal to make Taler available in the Euro-zone.

The outcome is the announcement today. The new company Taler Operations AG will be set up to apply for an e-money licence and take over the role originally intended for GLS (who will remain a consortium member in a supporting role).

We regret that the original plan did not work out. Integrating a new kind of payment system into an existing bank’s processes, compliance framework and IT is hard, and banks have to set priorities. We are grateful to GLS for its work in the project and for staying involved. And we also think the new arrangement has a real advantage: the institution operating Taler in Euro will be focused entirely on Taler, instead of fitting it into a larger bank’s product portfolio and process constraints.

What Taler Operations AG will do

Legal status:

Taler Operations AG is a German stock corporation in formation, seated in Bochum, and a subsidiary of Taler Systems SA (Luxembourg).

Purpose:

Operating a GNU Taler exchange in Germany, for the Euro, so that citizens can pay with Taler and merchants can accept it.

Reach:

After establishing legal operations in Germany, Taler will become usable across the single market, even if Taler Operations AG will initially only promote it in Germany.

Timing:

Operations can only begin once BaFin has granted the authorisation. A launch date will be announced after that happens.

Next steps:

  • An application to BaFin for authorisation as an electronic money institution (EMI).
  • Securing funding via investors, see below, to become operable.

We stress that GNU Taler is and stays free software. The licensed company operates a service; Taler, the protocol suite, and its reference implementation GNU Taler remain open and free.

What this means for the community

The NGI TALER project continues: development, security reviews, integrations from the open calls, and the Swiss deployment all go on as before. The change concerns who will operate the Taler payment system in Euro in Germany, but not the direction of the project. We will report on the progress of the e-money licence application.

If you want to help, you can tell merchants and organisations you care about that Taler is coming. You can try the Taler wallet with the demo site and report issues. You can also contribute to the software.

And you can invest to help us fund the launch and, if successful, benefit as a shareholder:

For investors

Getting an e-money licence takes capital. The law sets minimum own funds for EMIs, and BaFin also expects a credible business plan, staffing, compliance and IT security before granting authorisation. Taler Operations AG is therefore raising capital now.

We are looking for investors who:

  • want a privacy-preserving, free-software payment system to become legally available in Germany and the Euro area;
  • understand that this is a regulated infrastructure business with a licensing phase before revenue; and
  • are able to invest at least €50,000.

We are especially interested in investors who share the values behind Taler: privacy for buyers, transparency for taxable income, no lock-in, and payments as public-interest infrastructure.

Contact us at invest@taler-systems.com to be given access to further business information.

The Daily Front Page 18 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — Cutting the Map Finer
article

Faster than earcut: triangulating 3.7M map polygons in 489 ms

by molind·▲ 210 points·39 comments·globus.software ↗
In the browser, 1.4 to 2.1 times as fast as earcut.js.

We have published the polygon triangulator of our map engine as a small library, earstrip, under the ISC license, the same one earcut uses. It is one C++ header, and a WebAssembly build on npm that takes the same arguments as earcut. In C++ it is 14% faster than earcut.hpp, in the browser 1.4 to 2.1 times as fast as earcut.js, and the comparison is near the end. This post is about how we got there.

A GPU fills triangles and nothing else. A map, on the other hand, is mostly polygons: buildings, parks, parking lots, the strip of grass between two tram tracks. Here are a few blocks of Śródmieście in Warsaw the way our renderer reads them from a map file, as outlines:

Before any of this gets a fill, every outline has to be cut into triangles. Hover over a polygon, or tap it, to see what it turns into. These blocks hold 331 polygons with 5,151 vertices, and they become 4,514 triangles.

Zoom level 13 of our offline map of the Masovian Voivodeship, the region around Warsaw, has 3,740,425 polygons. On one core of an M4 Pro, the constrained Delaunay triangulator in our engine needs 2.93 seconds to cut all of them. This October I replaced it with ear clipping. To write this post I rebuilt the ear clipper one idea at a time, one commit per idea, and timed every commit on those same 3.7 million polygons, so each section below ends with a number.

Delaunay

A triangulation of a set of points is Delaunay when no point lies inside the circle through the three corners of any triangle. Two triangles that share an edge are enough to see how the rule works. Drag the point D:

Smallest angle 45°; with BD instead it would be 37°

While D stays outside the dashed circle through A, B and C, the shared edge is AC. Push D into the circle and the edge flips to BD; pull it back out and it flips back. Each flip is a local repair, and a triangulation where no edge wants to flip is Delaunay. Of all the ways to triangulate the same points, it has the largest smallest angle. The orange arc marks the smallest angle of the two triangles, and the line under the figure shows what the other diagonal would give: wherever you put D, the edge the circle rule picks wins.

"Constrained" means that the polygon's own edges must stay edges of the triangulation, even where the circle rule would flip them away. Our triangulator inserts the vertices one at a time. For each new point it walks across the triangles built so far until it finds the one the point falls into, splits it, and flips edges around the new point until the circle rule holds again. It also forces the polygon's edges in, and at the end it keeps only the triangles that lie inside the polygon and outside its holes.

Well-shaped triangles matter when you interpolate something across them or run a simulation on them. A flat fill doesn't care: a GPU fills a needle-thin triangle as correctly as a fat one. And most of the work is spent on polygons that hardly need any. Almost half of the Masovian polygons, 1.8 million, have four vertices or fewer. A triangle needs no cutting at all and a convex quad is two triangles, yet the Delaunay code spends 419 ms on them, building each triangulation from scratch.

Ears

An ear of a polygon is a corner you can cut off with one straight cut. Take three consecutive vertices a, b and c. If the corner at b is convex and no other part of the polygon reaches into the triangle abc, that triangle is an ear. Cut it off, and what remains is a polygon with one vertex fewer. In 1975 Gary Meisters proved that every simple polygon with more than three vertices has at least two ears that don't overlap. So there is always another ear to cut, and a polygon with n vertices falls apart into n − 2 triangles.

Here is one of the buildings from the blocks above. Move the slider to cut its ears one at a time, or cut them all.

The green triangle is the next ear to go. The algorithm needs one test, "is this corner an ear?", and the simplest version of it checks the corner and then every other vertex of the boundary. cross is the 2×2 determinant found in every geometry codebase; it is positive when c lies to the left of the line from a to b, so for a boundary that runs counter-clockwise a positive cross(a, b, c) means a convex corner:

static double cross(double ax, double ay, double bx,
                    double by, double cx, double cy)
{
    return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);
}

bool isEar(uint32_t v) const
{
    const Node &b = _nodes[v];

    const Node &a = _nodes[b.prev], &c = _nodes[b.next];

    if (cross(a, b, c) <= 0)
        return false; // turns the wrong way, or not at all

    for (uint32_t w = c.next; w != b.prev;
         w = _nodes[w].next) {
        const Node &p = _nodes[w];

        if (cross(a.x, a.y, b.x, b.y, p.x, p.y) < 0 ||
            cross(b.x, b.y, c.x, c.y, p.x, p.y) < 0 ||
            cross(c.x, c.y, a.x, a.y, p.x, p.y) < 0)
            continue; // outside the triangle

        if (!samePos(p, a) && !samePos(p, b) &&
            !samePos(p, c))
            return false;
    }

    return true;
}

A point on an edge of the triangle counts as inside: if the ear touched the rest of the boundary, cutting it off would leave a polygon that touches itself. The one exception is a point at exactly the position of a, b or c, which happens where an outline meets itself at a single vertex. Holes make that common.

Holes

Ear clipping works on one closed boundary, and 11,345 of the Masovian polygons have holes, such as courtyards and clearings in forests. The way to deal with them is to cut each hole open and stitch it to the outer ring with a bridge, an edge from a vertex of the hole to a vertex of the boundary, walked once in each direction. The boundary then runs around the outside, crosses the bridge, goes around the hole the other way and comes back. There is no area between the two copies of the bridge, so the polygon is the same, but now it is one ring.

The bridge must not cross anything. David Eberly's write-up of ear clipping has a neat way to find one. Take the rightmost vertex of the hole, m, and cast a ray to the right. The first edge the ray hits, at I, has an end P further to the right. If no boundary vertex lies inside the triangle m, I, P, the bridge m–P is safe. You can drag the hole around:

The tip of the dent lies in the triangle m, I, P. A bridge to P would cross the boundary, so it goes to the dent.

Higher up the triangle is empty and the bridge goes to P. Lower down the tip of the dent sits inside the triangle, and the bridge goes to the dent instead: of the dents in the triangle, Eberly takes the one closest in angle to the ray. Holes are bridged rightmost first, so a hole further left can bridge to one that is already part of the boundary.

Map data adds two cases of its own. Our coordinates are integers on a tile grid, so a ray along a grid line runs straight through a vertex all the time; the crossing test passes over such a vertex, and my first version got exactly this case wrong. And mappers often draw a courtyard that touches the outer wall at one point. Such a hole needs no bridge: the two rings are joined at the shared vertex.

The naive clipper (−1,812 ms)

With holes bridged, the first complete version walks around the boundary, tests corners with the isEar above, cuts every ear it finds and writes each triangle as three indices. On the Masovian polygons it takes 1.12 seconds, 2.6 times faster than Delaunay. The chart splits each time by polygon size; hover over a part of a bar to see its number, or click a row.

The naive row is shorter than Delaunay in every size class but the last. The 1,123 largest polygons, with 257 vertices or more, take 199 ms to clip and 90 ms with Delaunay. Each ear test there walks hundreds of vertices, and a polygon needs hundreds of tests, so the cost grows with the square of its size. The rest of this post is about making the ear test cheaper and needed less often.

Test only the dents (−237 ms)

Look at which vertices can actually stop a convex corner from being an ear. Say some vertices lie inside its triangle, and take the one closest to the corner itself. Its two edges can't cross the sides of the triangle, so both run back, away from the corner, and the polygon wraps around that vertex from the corner's side. That makes it a reflex vertex, a dent. So if anything is inside the triangle, a dent is inside it too, and the test only has to look at the dents.

The engine keeps a list of them. A dent leaves the list when cutting its neighbour makes it convex, and a convex corner never turns into a dent, so the list only shrinks. The test becomes:

bool isEar(uint32_t v) const
{
    const Node &b = _nodes[v];

    if (b.reflex)
        return false;

    const Node &a = _nodes[b.prev], &c = _nodes[b.next];

    for (uint32_t i = 0; i < _live; ++i) {
        const Item &p = _items[i]; // a dent

        if (p.node == b.prev || p.node == b.next)
            continue;

        if (cross(a.x, a.y, b.x, b.y, p.x, p.y) < 0 ||
            cross(b.x, b.y, c.x, c.y, p.x, p.y) < 0 ||
            cross(c.x, c.y, a.x, a.y, p.x, p.y) < 0)
            continue;

        if ((p.x != a.x || p.y != a.y) &&
            (p.x != b.x || p.y != b.y) &&
            (p.x != c.x || p.y != c.y))
            return false;
    }

    return true;
}

The 28.1 million ear tests now look at 185 million points instead of 353 million, and the total drops to 882 ms. That is less than you might expect, because building outlines have a lot of dents. The building with the arch above has 15 of them among its 27 vertices. And the smallest polygons get slower, from 34 to 54 ms: for a triangle or a quad, sorting the corners into dents and the rest costs more than the walk it saves.

Skip tests on convex polygons (−2 ms)

A polygon without dents is convex, and every corner of a convex polygon is an ear, so it can be cut without a single test. Checking for that needs care. "Every corner turns left" is not enough:

Corners turning left: 5 of 5. Changes of x direction: 4. Not convex.

The star turns left at all five corners, because it goes around its centre twice. The engine adds one more condition. Walking around a convex ring, the edges go right along the bottom and left along the top, so their x direction changes exactly twice, at the leftmost and the rightmost point. The pentagon passes; the star changes direction four times, at the circled corners, and goes to the ordinary ear tests. Both counts come out of the same loop that marks the dents, so the check costs almost nothing. Triangles and quads get their own shortcut before that loop.

The shortcut removes 4.4 million of the 28.1 million ear tests, but those were the cheapest ones: a ring without dents has nothing to scan. On its own it barely moves the total, 880 ms, though the polygons with four vertices or fewer win back part of what the dents cost them, from 54 to 48 ms. It matters more in the next step, where a convex ring becomes a single strip.

Write strips (−118 ms)

So far every triangle costs three indices. A GPU can also draw a triangle strip, where each new index adds a triangle made of it and the two before. A convex ring makes one strip if you zig-zag across it:

0 1 7 2 6 3 5 4

The ear clipper can write strips too. Cutting an ear makes the corners of its two neighbours sharper, so they are good candidates for the next ear, and cutting one of them extends the strip by a single index. The engine tries them first and keeps alternating between the two ends while the ears last. In its code the neighbours of the cut vertex are a and b:

// The next ear alternates between the ends of the cut.

while (true) {

    if (sideA) {

        const uint32_t z = n[a].prev;

        _strips.push_back(n[z].index);

        unlink(a);

        a = z;

    } else {

        const uint32_t z = n[b].next;

        _strips.push_back(n[z].index);

        unlink(b);

        b = z;

    }

    count--;

    sideA = !sideA;

    if (count < 3 || !isEar(sideA ? a : b))

        break;

}

When the next corner is not an ear, the strip ends and the walk goes on from where it stopped. The 21.5 million triangles now take 35.8 million indices instead of 64.5 million. The ear tests don't get fewer: the naive walk already went on at the next corner after a cut, and now every strip also ends on a test that fails, 25.0 million instead of 23.7 million. Still, the total falls to 762 ms, and the largest polygons drop from 146 to 103 ms.

Sort the dents into buckets (−65 ms)

A forest or a lake can have thousands of vertices and hundreds of dents, and each ear test still reads every one of them. When a polygon has more than 32 dents, the engine sorts them into buckets along the longer side of their bounding box, about two dents per bucket. An ear test looks only at the buckets that its triangle spans. As dents turn convex and leave, the index is rebuilt once half of it is gone.

Points scanned fall from 181 million to 101 million, almost all of it on the large polygons: the polygons with 257 vertices or more go from 103 to 57 ms. Total: 697 ms.

Count without branches (−178 ms)

The loop in the dent test exits at the first dent inside the triangle. Most of the time there is none: the test reads all the dents and says yes. An early exit then buys nothing, and the three comparisons per point are branches the CPU has to predict. The engine first runs a pass that only counts dents inside the triangle, with no branches at all:

const double abx = b.x - a.x, aby = b.y - a.y;

const double bcx = c.x - b.x, bcy = c.y - b.y;

const double cax = a.x - c.x, cay = a.y - c.y;

uint32_t hits = 0;

for (uint32_t i = begin; i < end; ++i) {

    const Item &p = items[i];

    const double side = std::min(

        std::min(abx * (p.y - a.y) - aby * (p.x - a.x),

                 bcx * (p.y - b.y) - bcy * (p.x - b.x)),

        cax * (p.y - c.y) - cay * (p.x - c.x));

    hits += (uint32_t)(side >= 0) & (uint32_t)(p.node != ia)

          & (uint32_t)(p.node != ic);

}

if (hits == 0)

    return true;

The smallest of the three determinants is non-negative exactly when the point is inside the closed triangle. Only when the count is not zero does the exact loop from before run, to rule out dents that sit on a corner. The bucket version does the same with a bounding-box test, 64 points at a time into a bit mask. The total falls to 519 ms, and the middle sizes gain the most: polygons with 33 to 256 vertices go from 327 to 216 ms.

Test only the marked dents (−30 ms)

When the count is not zero, the exact loop reads all the dents again, although the first pass has already seen which ones were inside. The bucket version keeps that in its bit mask. The short list, up to 32 dents, can do the same: the first pass sets one bit per hit instead of counting, and the exact test looks only at those dents:

    hits |= ((uint32_t)(side >= 0) & (uint32_t)(p.node != ia)

             & (uint32_t)(p.node != ic)) << (i - begin);

}

while (hits) {

    const Item &p = items[begin + lowestBit(hits)];

    hits &= hits - 1;

    // the exact test from before

}

Points read fall from 128 million to 120 million. This is the last step, and it is the code of earstrip as published: 489 ms, 6.0 times less than Delaunay on the same polygons.

When there are no ears

Meisters' theorem is about simple polygons. Map data is rounded to a tile grid, and rounding can break a simple polygon. Here is the outline of Warszawa Śródmieście, a railway station less than a kilometre from the blocks above, rounded to grids of different size. The orange rings mark vertices that land on the same point as their neighbour:

Grid step 73 cm. 68 of 154 vertices land on their neighbour. 84 triangles.

At 14 bits per tile side, the grid our map files use, a grid step is 18 cm. Even there 31 of the 154 vertices merge with a neighbour, because mappers often place points a few centimetres apart, and the outline survives. At 12 bits nearly half of the vertices merge, and the clipper still cuts it. At 11 bits the rounded outline touches itself in a way that leaves no ear at all, and at 10 bits it happens to work again.

When the clipper walks all the way around the boundary without finding an ear, it drops the corners that have no area and walks once more. If that fails too, it gives up, and the engine triangulates that polygon with the Delaunay code, which still exists for this. In the Masovian data 76 polygons end up there. They come from a map built before the last change on the other end: our map generator now rounds every polygon to the final grid with GEOS's snap rounding and checks that ear clipping can cut it. In a fresh build of the Masovian map that repaired 273 polygons, and ear clipping can cut every polygon in the file.

Delaunay has one more job. Every hole needs its own bridge, and finding one scans the whole boundary, so a polygon with thousands of holes pays for thousands of scans. Our world map has a polygon with 11,675 holes: ear clipping takes 606 ms on it, Delaunay 17 ms. The engine now sends every polygon with 128 holes or more to Delaunay. In the Masovian data that is two polygons.

The library keeps both of these fallbacks inside. earstrip covers a polygon with a constrained Delaunay triangulation of its ring edges when the ears run out, when the triangles they leave cover the wrong area, and when it has more than 128 rings; run() in C++ and lastStatus() in JavaScript say which way a polygon went. On the 56,472 polygons of our world map tiles, with up to 11,675 holes in one, earstrip takes 459 ms and earcut.hpp 2,892 ms. On the zoom 13 polygons that the ears can't cut exactly, earcut's triangles differ from an even-odd fill of the rings on 31% of the pixels on average, earstrip's on 0.15%.

In the browser

Before the new clipper went into the app, I compared it with earcut, the ear clipper behind MapLibre and Mapbox GL, in its C++ version earcut.hpp 3.2.4. Natively the two are close, and that could have been the end of it. But we are working on a web renderer that runs the same C++ engine compiled to WebAssembly, so I went further and compared the browser side too: both clippers compiled to WebAssembly, and earcut.js 3.2.4, the JavaScript original that web maps run today. For that I took the clipper out of the engine into earstrip. On all 5.8 million polygons of our test sets it writes exactly the engine's strips, and its repository has these polygons and the code behind every number in this section. Its native benchmark is the one behind the chart above, and the native row below is the last step run against earcut.hpp. Every WebAssembly build gives exactly the same triangles as its native version on all 4.4 million polygons of zoom levels 13 and 9.

Natively earcut.hpp is 14% slower than earstrip. Compiled to WebAssembly and run in V8, earstrip loses 23% and earcut.hpp loses 67%, almost all of it in its main loop that searches for ears. It isn't the allocator: builds with mimalloc and emmalloc give the same time. I haven't dug further. In V8, earcut.hpp in WebAssembly ends up only 19% faster than plain earcut.js, and 10% once each polygon is a separate call from JavaScript.

The package rows are what a web page gets, and the earcut column there is earcut.js. The call that replaces earcut takes the coordinates as JavaScript numbers and returns a new array of triangle indices every time: 1.4 times as fast as earcut.js in V8 and 1.6 times in JavaScriptCore. About half of what it loses against the loop inside the module goes into copying the coordinates in and turning the strips into a list, the rest into calling into WebAssembly once per polygon. The direct calls skip all of that: the polygons go straight into the module's memory and come back as one index buffer of strips for WebGL 2 or WebGPU, 1.7 and 2.1 times as fast as earcut.js.

Some of the ideas above are in earcut too. It also relies on the fact that only a dent can block an ear, but it checks that last, for every vertex that passes the bounding box and triangle tests, instead of keeping a list of dents. Above 80 vertices it links them in z-order and scans only the stretch of that curve the triangle's bounding box covers, which does the job of the buckets. What it doesn't have are the shortcut for convex polygons, the strips and the count without branches: it writes three indices per triangle and stops at the first point inside.

earstrip is on GitHub and npm, with the polygons from this post and the code to time it against earcut on your own machine.

The Daily Front Page 19 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — Proof at Machine Scale
article

LLMs are making formal software verification feasible at a much larger scale

by johnbender·▲ 209 points·118 comments·anthropic.com ↗
Formal software verification could provide this guarantee, but it has historically required years of expert effort.

LLMs are making formal software verification feasible at a much larger scale

Most software is riddled with bugs, which AI can now easily find and exploit. The standard defenses against cyberattacks are no longer sufficient: we need ways to prove that code is free of bugs. Formal software verification could provide this guarantee, but it has historically required years of expert effort, making it impractical for most real-world projects. In a collaboration with Theorem, however, we show this is no longer the case: LLMs can now produce formal proofs at large scale, enabling new software development workflows that include proven security guarantees. Using Claude, we proved security properties at the assembly code level (RISC-V) in over 100 real-world open-source software libraries. To our knowledge, this represents the first large-scale effort to use AI to apply formal verification to production software at the assembly code level. While writing the proofs, Claude also discovered bugs that had eluded detection for years, despite trillions of test runs. As model capabilities continue to improve, we expect formal verification to become an essential part of secure software development.

Introduction

Even mature, heavily tested software contains bugs, and LLMs are increasingly adept at finding them. The Linux kernel—one of the most well-tested pieces of software today, deployed on billions of devices worldwide—recently had over 1,000 vulnerabilities disclosed. With frontier models becoming more capable of chaining seemingly benign bugs into critical exploits, we need techniques that can detect and fix these bugs before they can be exploited in the wild.

Ideally, such techniques could find and patch all bugs, and then provide some proof that there are no more to be found. Formal verification is one way to do this. In formal verification, developers translate their code into a mathematical model, then try to prove that it always follows some defined set of security rules. If they fail to prove this, that means there could be a bug in the code that would violate a rule, and the nature of the failure implies what the bug might be. Repeating this process (after eliminating the cause of failure each time) will ultimately yield proof that the code is devoid of any bug that would violate those rules.

However, formal verification isn’t easy. Proofs can be many times larger than the original code, and writing them requires significant effort and a niche, highly specialized skill set. For instance, it took two person-years to implement the seL4 operating system kernel, but 20 person-years to formally verify it. Accordingly, formal verification has been practical only in truly mission-critical applications, such as Airbus’s avionics code.

But LLMs are making it far easier. Frontier models can now produce correctness proofs for real-world software fully autonomously. To demonstrate this, we asked Claude to prove useful security properties across 123 open-source libraries, including showing that some of their executable artifacts can never crash under certain conditions. Specifically, Claude proved that these programs will always exit normally without triggering memory-safety errors or failing assertions, for every input less than 64 MB and every modeled Linux operating system (OS) response and memory layout, under certain assumptions (namely that the program runs as a single-threaded static binary with a fixed memory budget on a RISC-V1 CPU using Linux OS). This is still far away from fixing all possible bugs, but it does get us much closer than before and provides a roadmap toward that end.

We’re publishing a subset of these proofs so that anyone can verify and reuse them, along with the RISC-V and OS semantics. Theorem, our collaborator on this project, is also offering to run the same pipeline for other open-source projects, and is publishing a Claude skill to help developers get started with verifying their own code.

Formal verification is a broad field with many methodologies. Below, we also describe our initial explorations using other formal verification methods to accelerate other security or software development tasks, such as assessing the security of the zlib compression algorithm, proving behavioral equivalence of a Python interpreter written in Rust, and rooting out long-standing bugs in critical software.

The road ahead for formal verification is promising. The cost of writing proofs is falling as models become more intelligent. Moreover, as more code is formalized and methods of achieving security guarantees become more standardized, the ability to reuse or modify proofs across codebases will amortize the cost. We encourage all developers to explore formal verification with LLMs—especially those who previously tried it with less capable models and found it didn’t work.

In the rest of this post, we cover our formal verification experiments in more detail.

Turning tests into proofs

To prove that a piece of software is correct, we must first state what “correct” even means. Correctness is defined by the specification (spec). In some programs, there is a clear way to formally specify the program’s intended behavior. For example, a PNG decoder takes a sequence of bytes and (following RFC 2083) decodes these bytes into the corresponding image. But for most programs, things aren’t so straightforward. What would it mean for a text editor or a web browser to be “correct”? The difficulty of obtaining a comprehensive and unambiguous spec is a significant obstacle to verifying software at a larger scale.

To address this for the code in the open-source libraries that we sought to prove, we take the approach of automatically converting their preexisting compilable test suites into a spec by encoding the rule “this test suite always passes,” using a general model of what it means to execute any RISC-V-compiled binary on Linux. Historically, proving such specs was intractable, given the inherent complexity of writing a proof that can encompass and make an argument over all possible behaviors and interactions of tens of thousands of assembly instructions over any input (and the fact that proofs tend to be extremely large as a result). This is where today’s LLMs come in: churning through millions of lines of code in pursuit of a well-defined goal is a task that LLMs are extremely well suited for.

For this project, we started with fuzz tests. In these tests, developers write an entry point2 into their code that takes inputs, such that any input that causes a crash is a bug the authors care about. Then the fuzzer, a testing engine, generates enormous numbers of semirandom and mutated inputs at the entry point to try to find a bug (visualized in Figure 1). The longer a fuzzer runs, the more bugs it can find. But this is inherently a brute-force process, with no guarantee of exercising every possible code path, regardless of how many inputs you try.

Fuzzing works by running huge numbers of generated inputs through one entry point to find the inputs that cause a crash. There are infinite inputs, so the search can never be complete.

To find all the bugs that would’ve been surfaced by a fuzz test, we turned the fuzz test into a spec defined over the compiled RISC-V instructions. The spec says that the fuzz test won’t crash for any input less than 64 MB.3 If Claude can prove this spec, the fuzz test on RISC-V becomes superfluous: fuzzing that entry point will never find any bugs.

We did this for hundreds of projects in Google’s OSS-Fuzz initiative, which provides continuous fuzz testing for qualifying open-source projects. OSS-Fuzz contains thousands of developer-authored entry points that look for broken code properties by crashing (for example, on a failed assertion). OSS-Fuzz automatically instruments C and C++ programs with AddressSanitizer4 (ASan), causing them to crash whenever memory is accessed improperly (which is a leading cause of software vulnerabilities). Broad-spectrum specifications like memory safety apply to almost all software.

The open-source library and its existing fuzz test are compiled to a RISC-V executable. This executable, along with Theorem’s RISC-V and OS formal semantics and the desired no-crash property, mechanically yield a specification the proof must satisfy. Claude writes the proof; the Rocq kernel checks it against the specification. Green marks what’s proven, conditional on the trusted components being correct.

Over the span of a few weeks, Claude successfully patched the bugs it found and then proved that there are no crashes on any input (up to 64 MB) for 239 entry points across 123 different OSS-Fuzz libraries. These proofs operate on the compiled RISC-V instructions (i.e., executable binaries), and they comprise about 180 million lines of Rocq, with a typical proof running to about 600,000 lines to provide security guarantees on binaries with a median length of 18,000 RISC-V instructions. These proofs are built by translating the RISC-V assembly code to a mathematical model using Theorem’s RISC-V instruction and Linux process semantics. This means these proofs currently assume that the program runs as a single-threaded static binary with a fixed memory budget on a RISC-V CPU using Linux OS. Expanding the scope of these proofs is well within reach, as it would involve standardizing semantics for more assembly architectures and other operating system processes. See an expert’s take on the proofs Claude wrote.

A formal no-crash proof over all inputs rules out all crashes along any path reachable from the entry point. While iterating on its proof, Claude can also find and fix any remaining reachable crash-producing bug.

While this is an enormous volume of proof code, virtually none of it needs to be manually reviewed. The Rocq proof checker ensures that the spec is correctly satisfied by the proof. As a result, the only artifacts that a developer needs to trust are:

  • The formal models of RISC-V and of Linux processes;
  • The exact theorem statements that were proved;
  • The Rocq proof checker itself.5

This doesn’t mean these libraries contain no bugs. Instead, it means that any remaining bugs either are to be found within the artifacts listed above or are outside the scope of Claude’s proof. Hardening those still-possibly-buggy trusted components (Rocq, RISC-V, and Linux semantics) is not insignificant, but it’s a far more tractable task than debugging every line of code the scaled-out proofs cover—especially as this approach can secure an arbitrary number of projects without increasing the size of the trusted components.

We welcome independent verification of our proofs and encourage refinement of our approach. To that end, we are publishing the trusted components (above) made for this project that are not already public; Claude’s complete Rocq proofs for fuzz tests that did not require patching; and specifications for other fuzz tests we were not able to prove.

Finding and fixing bugs

Above, we showed that you can turn many open-source libraries’ developer-written tests (fuzz tests) into specs that Claude can prove will always pass, sometimes after patching the remaining bugs it found. For this reason, the process of attempting to prove these specs discovered hundreds of bugs.

Lots of bugs showed up during Claude’s attempts to prove hundreds of entry points. To ensure that Claude didn’t have to stop for a human every time this happened, we let Claude fix the bugs it found: it patched the code, which caused the spec to be regenerated with that patched code, and then Claude proceeded to prove that new spec.6

Many of the bugs we found are ones that a fuzzer would be unlikely to ever find. Fuzzers mutate small inputs, typically capped at 1 MB, and typically rely on code coverage to guide them toward bugs. While proving an entry point in one library, Claude found a counter underflow in its copy of a decompressor that led to an out-of-bounds write, but only on inputs of around 20 MB that had one rare, specific layout. Other bugs include an out-of-bounds read in an image decoder that needed a 64 MB input and over 2 GB of memory, an out-of-bounds read in another library that needed a particular sequence of calls across two handles to the same file, and a rediscovery of CVE-2026-56132 in libexpat, which needed deeply nested input. Claude also found logic bugs that never crash at all. While proving that one library was memory-safe, for example, it noticed that a feature for restricting which files an application can load isn’t always enforced.

The ultimate goal of this project was to achieve a proof that the RISC-V-compiled fuzz tests had no remaining crashes to find. However, bugs like the above show that the process has another benefit, regardless of whether that goal is achieved: even just attempting this process yields real bugs that need to be fixed.

Proving more than memory safety

Proving that a fuzz test has no more crashes to find is more significant than it sounds. It’s common for fuzz tests in real-world code to test for violations of meaningful high-level properties, such as encode-decode roundtripping, idempotence, algebraic laws, differential testing, self-consistency, or equivalence to reference implementations. For example, a fuzz test for the LZO compression algorithm asserts that if you compress an input, then decompress it, the result is the same as the original. If the property does not hold, the program crashes—so proving the test never crashes is equivalent to proving the property itself.

This can also occur even when the properties are not directly specified by the developer. For example, in order for Claude to complete its OSS-Fuzz proof for cpp-httplib, it was necessary to rule out the possibility of a stack overflow due to too much recursion in the std::set destructor. This recursion depth is bounded by the maximum depth of a tree, so Claude had to prove (on machine code!) that libc++’s red-black tree rebalancing algorithm is correctly optimized to keep the tree’s depth logarithmically bounded.

Other formal verification case studies

Formal verification is an expansive domain. The fuzz-test-to-proof example above is one instance of LLMs making formal verification more widely usable by directly applying proofs to machine code.

We’ve also seen success using LLMs with formal verification in other ways. For example, we asked Claude to write a formal spec of RFC 1950, the technical document that defines the zlib compression file format. Then, we had Claude prove that the zlib implementation in the Linux kernel correctly implements that spec. As with the examples above, Claude proved this property at the binary level, except instead of RISC-V, Claude directly proved the x86-compiled binary using Claude-generated (and heavily tested) formal semantics of the x86 ISA.7 We then repeated this process for half a dozen other widely used libraries. Along the way, we found some minor (unexploitable) bugs in corner cases, which are in the process of being filed upstream. We draw two conclusions from this exercise: (1) these extremely well-tested codebases are already almost fully correct, and (2) it is possible to prove end-to-end correctness properties about real existing codebases.

In another experiment, we asked Claude to develop an interpreter for a large subset of Python in Rust, and to prove (using Verus, a verification tool for Rust) that it adheres to the CPython semantics outlined in an academic paper. We then measured the adherence to CPython’s behavior empirically, running over 1.7 million randomly generated Python programs, finding identical behavior with CPython in 99.95% of tests, with remaining test differences as unsurprising known corner cases.

We also found issues in several widely used and critical applications via formal verification attempts of simple security properties. In one of them, we discovered a previously unknown logic bug that had been latent for more than a decade. During an effort to verify a widely used PDF reader, we found as many security bugs in one week as are typically reported in a year.

See the Appendix for more details on some of these efforts.

This is just the beginning

One of the key limitations of LLM-assisted formal verification is that the proofs can take hundreds of millions of tokens to produce. Cost-efficiency is critical if our goal is to make these methods available to the entire software ecosystem. Fortunately, there are compelling reasons to expect efficiency to improve.

Newer models need fewer tokens

We built 36 small verification tasks from real OSS-Fuzz code. Opus 5.5 proves half of them with about 40% fewer tokens than Opus 5. We expect this trend to continue as models are trained on long verification tasks.

Line chart of the share of 36 verification tasks completed by token budget per agent for Opus 5.5, Fable 5.1, and Opus 5. Opus 5.5 finishes proofs with the fewest tokens.

Opus 5.5 finishes proofs faster than earlier models. Share of 36 formal verification tasks proved by a single agent at a given token budget. Each task received three independent single-agent attempts at a 5M-token budget, and counts as proven when the first attempt finishes.

Proofs can be reused

When agents work separately, they often end up duplicating a lot of effort. Proofs, like software, are recursively built from smaller proofs—and the smaller the proofs are, the more reusable they tend to be. To measure the impact of this, we let agents copy each other’s proofs as they worked on proving their own targets. When given access to this shared workspace, agents needed 17% fewer tokens than when they worked alone, and some agents even succeeded after previously failing in a solo attempt.

Chart of 36 proofs in finishing order, with arcs joining proofs that share a file and bars showing the tokens spent on each proof compared with an agent working alone.

The 36 proofs from one shared workspace, in the order they finished. An arc joins any two proofs that share an unchanged file; bars show the tokens spent writing each proof, and black lines show the same task’s average cost for an agent working alone, which was higher in 30 of the 34 completed proofs (agents working alone were not able to complete two of the proofs).

We observed the same phenomenon occurring at scale during our OSS-Fuzz proof effort. Most of a proof concerns code that every program contains (particularly initialization of the C runtime and AddressSanitizer), so very different programs can end up with significantly overlapping proofs. Agent teams took advantage of this by copying another team’s finished proof and then adapting it to their own program (Figure 6).

Block chart of the proofs for libcups, freerdp, and libzmq, showing how much of each part was identical, lightly edited, edited more or new.

Agents copied an existing proof and adapted it to each new program. Each column represents one program’s complete proof by share of bytes. Blocks are the parts of the proof and each block shows how much was kept identical, lightly edited (same file, size within 2%), edited more, or newly written. The shared parts gained almost no new code.

This reusability of proofs is how Mathlib, a shared library of formal mathematics in Lean, grew to nearly 300,000 theorems submitted by over 700 contributors: each new proof builds on the existing body of work. We accumulated a similar body of proofs in the course of our OSS-Fuzz effort, some of which we’re including in our release (we are not releasing proofs that may reveal an unpatched bug in the open-source software).

As we graduate from these initial experiments, we need a strategy for verifying the enormous body of existing software, starting with the most critical dependencies. As we’ve shown, this can be achieved at scale by using generic specs and working at the binary level, sidestepping the need to rewrite entire codebases in another language.

This approach also facilitates the reuse of proofs at package-level granularity, which means that each dependency only needs to be verified once. Dependencies follow a power law: proving even a small set of shared libraries makes a huge swath of software feasible to prove. For more details, see Theorem’s roadmap for verifying the entirety of the Nix ecosystem, which includes critical infrastructure like glibc, OpenSSL, and cURL.

Limitations

In practice, formal verification can sometimes prove less about the security of the code than we would like.

“Formally verified” does not mean “bug-free.” Claude can write a proof showing that a compiled program’s behavior satisfies the requirements of a formal spec (which is verified by an external proof checker). However, a proof checker can’t tell you whether your spec matches reality. To match reality, the spec must correctly encompass and model everything about the real-world machine that the verified program runs on, including the CPU and operating system. When bugs show up in verified code, it’s because the spec, or the assumed semantics of the machine, differs from reality. Fortunately, this also means we know where to look for remaining bugs, and how to design a system where those still-possibly-buggy gaps are minimized. Below are the ways this applies to our proofs, and ideas for future work that would close those gaps.

The real machine does something the model doesn’t describe. Our proofs are about single-threaded, static RISC-V binaries linked against musl libc. However, most people run these libraries on x86 or ARM and dynamically link them against glibc. To close this gap, we’d need system models that more closely resemble deployed systems. For example, a step toward this would be generating accurate semantics for x86.

The claim may not cover everything we care about. We proved that a crash never triggers for any input under 64 MB on many fuzzing entry points in Google OSS-Fuzz, including ASan crashes. However, ASan doesn’t detect all memory safety bugs, and we didn’t verify all the entry points for each library. Even if we had, the whole library wouldn’t be covered by verifying all entry points (especially if there is dead code). Additionally, real programs might misuse the library, leading to memory corruption in the caller. To close that gap, we’d need to specify what callers must do for each public function, and callers would have to strictly adhere to it.

We expect that as we learn more about leveraging LLMs for formal methods, and as models continue to improve, these limitations will become tractable, and we’ll be able to verify a much larger percentage of the code we rely upon.

Conclusion

The trajectory is clear: formal verification, which was historically practical only for bespoke expert-crafted guarantees in the most safety-critical code, will soon be as practical as fuzzing is today for almost all production software. Just like static types, testing frameworks, and other correctness tooling, verification will mature from “bolted-on” to “built-in,” driven not only by LLMs but also by innovations in language design and development workflows.

In today’s world—where LLMs automatically scan for and find increasingly more code vulnerabilities—we must use processes that can guarantee code security properties. LLM-scaled formal verification is a promising approach toward securing these guarantees at a scope and scale that were previously unattainable. We encourage others to experiment so we can collectively build a world in which robust software has proliferated very widely and software bugs are a well-understood and quickly addressable rarity.

Read the full appendix.

Footnotes

01RISC-V is a processor design, like x86 or ARM, that defines the assembly instructions (the basic commands a chip carries out) that software is compiled into.

02An entry point is a front door into the code, provided by its authors for testing. Any input to the entry point that causes a crash is a bug the authors care about.

03Increasing this requires trivial human effort to change the parameter and regenerate the spec, then have Claude reprove the statement.

04AddressSanitizer is a compiler tool that adds checks to a program so that memory errors, such as buffer overflows and use-after-free, are detected and reported the moment they occur at runtime.

05This technically also means we have to trust the hardware, OS, OCaml compiler that the Rocq proof checker relies on.

06Note this leaves open the door to reward hacking. Reward hacking is when an AI model finds a shortcut that technically meets the goal it was given without doing what was actually intended, like a student who passes an exam by memorizing the answer key instead of learning the material. In this context, Claude could make any theorem provable by rewriting the program into one that trivially never crashes. To discourage this, we penalized any patch and offered extra credit for proving which inputs it changes and how few they are. We also logged and audited the patches for these failure modes.

07We think that the ability of Claude to—entirely autonomously—generate the formal semantics of an ISA is a separate interesting lesson. While we can not be sure our semantics themselves are perfect, empirically we have found that single-stepping through our semantics can boot an Ubuntu userspace on top of a Linux kernel. Generating these semantics also identified hundreds of mistakes in the official reference documentation, along with a smaller number of bugs in the hardware itself.

The Daily Front Page 20 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — Crystal’s New Cut
article

Crystal 1.22

by ksec·▲ 173 points·88 comments·crystal-lang.org ↗
All targets support native event loop.

Highlights

We are announcing a new Crystal release 1.22.0 with several new features and bug fixes.

Pre-built packages are available on GitHub Releases and our official distribution channels. See crystal-lang.org/install for installation instructions.

Stats

This release includes 251 changes since 1.21.1 by 33 contributors. We thank all the contributors for all the effort put into improving the language! ❤️

Changes

Below we list the most remarkable changes in the language, compiler, and stdlib. For more details, visit the full changelog.

Breaking: Exit on pipe error

Crystal processes exit immediately when writing to STDOUT or STDERR fails with EPIPE. This closely resembles the default behaviour of the SIGPIPE signal. Previously, the failing write would raise IO::Error, which typically prints an error message and exits. This error message is now removed (#17335).

You can opt out of this behaviour with STDOUT.exit_on_broken_pipe = false.

Thanks, @straight-shoota

Constants with type declarations

Constants can have type declarations (#16951). They work exactly as you would expect the combination of constants and type declarations to be.

module Foo
  BAR : Int32 = 1
  BAZ : String = ""
  QUX : Int64 = 123 # autocasts 123 to Int64
end

Thanks, @stakach

aarch64-linux promoted to Tier 1

The targets aarch64-linux-gnu and aarch64-linux-musl moved from Tier 2 to Tier 1. The only missing piece was that we were lacking official builds, but we have that since 1.19.

Breaking: Process.fork removed

Process.fork had been deprecated sine before 1.0 and now we finally removed it (#17367)

Thanks, @straight-shoota

New Macros

  • New macros enable more text operations at compile time: StringLiteral#bytesize (#17176), NumberLiteral#chr (#17169) and RangeLiteral#each supports CharLiteral (#17170)

Thanks, @straight-shoota

Compiler

New constants Crystal::ALL_FLAGS and Crystal::USER_FLAGS provide access to the compile time flags (#17392).

Thanks, @straight-shoota

DWARF refactor

We completely revamped DWARF parsing to enhance performance and reduce memory usage. The DWARF parser now scans sections on demand (#17283) and builds an efficient index table once (#17410, #17455), which results in blazingly fast look ups. Decoded backtrace lines are cached in an LRU cache (#17285).

Also added aupport for DWARF 5 features DW_FORM_addrx<n> and DW_FORM_strx<n> (#17445).

Thanks, @ysbaddaden

HTTP improvements

We merged numerous improvements and bug fixes for HTTP.

  • #remote_address and #local_address moved from HTTP::Request to HTTP::Context (#17196)
  • Add HTTP::Headers#merge (#17326)
  • Serialize IO::Memory in HTTP body with Content-Length header (#17388)

Bug fixes:

  • Reject unrecognized HTTP Transfer-Encoding header (#17140), invalid Content-Encoding (#17262), and invalid HTTP trailer (#17337)
  • [breaking] Fix the return values of HTTP::Request#body= and #content_length= (#17257, #17273)
  • Fix HTTP.parse_headers_and_body to not raise with without_zlib (#17272)
  • Validate properties of HTTP::WebSocketHandler (#17235), HTTP::Request (#17255,#17304, #17374, #17310, #17312, #17258), HTTP::Headers name (#17317)
  • Close HTTP::Client on IO::Error during request (#17318)
  • Fix Content-Encoding: deflate (#17261)
  • Fix HTTP::Request.from_io parsing empty header name (#17254)
  • Fix HTTP::Request#form_params? to ignore invalid content-type (#17256)

Thanks @straight-shoota, @hahwul, @jgaskins, @Sija

Eventloop

All targets support a native event loop based directly on the system selector and use it by default.

We enabled epoll on Solaris (#17370) and kqueue on all remaining BSD targets (#17421, #17420). libevent is still available as a fallback, but now it’s strictly opt-in and becoming technically obsolete. We expect to deprecate in a following release.

Thanks, @ysbaddaden

KernelTLS

We finally enabled support for Kernel TLS in the OpenSSL bindings by default (#17059)

Thanks, @ysbaddaden

Note

This was reverted in 1.22.1 and will stay disabled.

Misc

  • File.exists? (#17307), as well as File::Info.readable?, .writable?, .executable? now receive a follow_symlinks: false argument(#17391)
  • Add Char::Reader.new(Bytes) (#17428)
  • Add Time::Span#to_nanoseconds etc. (#17190)
  • Add GC.syscall(&) (#17150)
  • Fixed backtraces when linking with -static-pie on musl-libc (#17316)

Thanks, @straight-shoota, @ysbaddaden

Deprecations

  • Uppercase instance and class variables (#17160)
  • HTTP::Request#local_address and #remote_address (#17260)
  • LLVM::Type#size and #alignment (#17494)

Dependencies

  • Support for LLVM 23.1 and 24.0 (#17432)
  • Updated markd 0.6.0 (#17269)

Thanks, @straight-shoota, @hertzdevil

Packages

Updated distribution-scripts (#17178) brings upgrades of package dependencies, docker base images etc.

Thanks, @straight-shoota

This is the first release featuring builds for aarch64-windows-msvc.

Thanks, @hertzdevil

Maintainers

Crystal established a forward compatibility policy in RFC 30: Building Crystal 1.22 requires a stage-0 compiler at 1.14 or higher.

The Daily Front Page 21 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — A Game Engine’s Long Road
repository

Hedra is a 3D open world game I wrote from scratch while in highschool

by maxilevi·▲ 166 points·31 comments·github.com ↗
★ 129⑂ 4 forks C#

Hedra is a 3D open world game I wrote from scratch while in highschool. The entire codebase is around +100k LOC

Project Hedra is an ambitious open-world, low-poly RPG. Choose your class, explore endless procedurally generated worlds, unlock different skills and complete procedurally generated quests.

More screenshots at (Screenshots)

Timeline/Context

I started this project when I was in highschool (around 15 yo) in order to learn how OpenGL worked.

The scope creep quickly arrived and after a few years it turned into a fullfledged 3D game and game engine. The codebase has around 100k LOC and the game has first class support for Linux and Windows.

Features

The million lines of code are not in vain. The game and engine are both full of features :)

Game Features

  • Beatiful procedurally generated worlds
  • Quests and bosses
  • 100+ items with rarities system
  • Skills and skill tree system with N+ skills
  • 4 different classes with 2 specializations each ()
  • Procedurally placed structures generated dynamically
  • Fishing, crafting, etc
  • Trading and NPCs
  • Companions and pets
  • Beatiful soundtrack
  • Navigation, maps
  • Different dimensions
  • More stuff I don't recall :)

Engine Features

  • Fully fledged renderer using modern OpenGL
  • Skinned mesh rendering
  • Support for loading and playing generic animations
  • Collada (.dae) parser
  • Static mesh rendering
  • Screen space reflections
  • Screen space ambient occlusion
  • Bloom, FXAA & MSAA
  • Modding support
  • CI for automatically deploying to a Steam beta branch
  • Localization support
  • Sound support using OpenAL
  • Python scripting support
  • Module system for loading data oriented objects
  • Steam integration
  • Fully fledged UI & controls system (dropdowns, buttons, etc.) written from raw OpenGL
  • Dynamic shader system for reloading during runtime
  • Frustum culling, occlusion culling,
  • Mesh simplification for runtime level of detail (LOD)
  • Skybox support
  • Shadows
  • 3D trails renderering support
  • Particle system using object instancing in opengl
  • bulletphysics integration
  • Chunk system for infinite worlds support
  • .ply parsing support
  • Dynamic meshing support using MarchingCubes
  • Custom implementation of basic C# primitives and allocators (like Lists) for supporting stack allocated lists and minimizing the automatic runtime allocations (and thus the GC).
  • 1000+ plus test cases
  • Framework for mocking game components and doing integration testing on games
  • Image and asset compression for faster loading and smaller size
  • Entity component system
  • More stuff I don't recall :)

Interesting bits

  • WorldRenderer.cs. Renders the entire world in just 3 (actually it depends on how partitioned is the data buffer, but it was designed to be in 3) draw calls (water, terrain, instanced) using glMultiDrawElements.
  • Block.cs. Core component of the world. Read more at https://maxilevi.com/blog/procedural-meshing-hedra
  • Fishing.py. Written in Python as a mod script using IronPython, directly interacts with the C# API.
  • NativeArray.cs Implementation of an array primitive using a custom allocator. The same project provides heap based allocators as well as stac based ones using stackalloc. The idea was to minimize the automatic heap allocations (and thus avoiding the GC) during the game frames.

Interesting facts

  • The world is fully procedurally generated, there is no world save file. Only the player contents are saved and the world seed. The rest is created at runtime.
  • The world is voxel based but an isosurface extraction algorithm called Marching Cubes is applied to extract an implicit continous surface from the discrete voxels.
  • The name "Hedra" comes from tetrahedra which is the shape used in the original iso surface extraction algorithm I implemented Marching Tetrahedra
  • The game only supports loading .PLY and .DAE models, both which are in plaintext and the models have no textures. Therefore if you put this into perspective, this means I wrote a bunch of text that reads text and creates interactive images from this. I think this is pretty cool.

Screenshots

image image [image](https://camo.githubusercontent.com/4e5d78c9238fcf51c5d532d16f8d63259485d3580f96d61377ae252eb47b74ba/68747470733a2f2f63646e2e616b616d61692e737465616d7374617469632e636f6d2f737465616d2f617070732f313030393936302f73735f623861626)。jpg? t=1675777899) image

TODO add more

Code Structure

Overall Architecture

The game is a mod to a base engine. The idea of architecturing this way was to force myself to maintain the mod API up to date, therefore encouraging access to make mods.

Hedra

Basically the entire game. This includes AI logic, components, world generation, module systems, object placement and lots of other stuff.

Hedra.Engine

The core parts of the engine, this defines all the abstractions to the world. It handles rendering, sound, different base systems as well as the general windowing, game loop and platform features. The split was not done at the start so some stuff might still be outside.

Framework

Core primitives used in the engine. This includes heap and stack allocators, custom implementations of lists and arrays as well as wrappers to pointers to native and some other useful primitives

HedraTests

Test suite that

Asset Builder

Command line tool to compress the game assets into convenient binary files. Combines images, models, sound files, shaders into a single binary file with a structure designed for fast data retrieval.

Server

Once upong a time Hedra used to support multiplayer. It worked by doing UDP Hole Punching and having clients communicate P2P, this server was in charge of that. You might also see some networking remnants in the Engine code.

How to build

The build process is pretty straightforward.

  1. Checkout all the submodules
  2. Run the build depedencies scripts
  3. Compile the C# solution

You can check the GitHub actions workflows for some examples on Linux and Windows.

The Daily Front Page 22 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — The Short Columns
article

Woman charged with computer fraud due to scam CashApp account being in her name

by oidar·▲ 591 points·590 comments·404media.co ↗

Amanda Smith is charged with computer fraud due to a scam CashApp account being in her name. But in a Kafkaesque situation, CashApp won't provide her any information because she can't prove she is the owner.

Someone Opened a CashApp In Her Name. She Faces Years in Prison

IMAGE: SPUMONI COOPERATIVE FOR 404 MEDIA.

Amanda Smith answered the door one afternoon in April and came face to face with the local Sheriff’s department in upstate Pennsylvania. The officers said they had a warrant for her arrest for a crime she had allegedly committed more than a thousand miles away in Arkansas.

“I was completely confused,” Smith recalled. For one, she had never been to Arkansas. Second, the warrant was for computer fraud. By her own admission, Smith was not a very tech savvy person.

She had a feeling she was being set up. After discussing with the officers the practicalities of what was about to happen — she was allowed to get her contact lenses — they took her away in handcuffs to the local jail where she spent three nights.

The reason for Smith’s arrest, she learned later, was that a scammer had tricked someone on Facebook Marketplace into sending $1,000 to a CashApp account in her name that the scammer controlled. The scammer created the account using her Social Security number and date of birth. Smith said she has never used CashApp.

What developed over the next few days, and has now stretched across six months, is a Kafkaesque situation in which Smith, in her telling, is being asked to prove her innocence in an ongoing criminal case, while CashApp refuses to provide her any information about the account because she couldn’t prove that she was the owner.

The Daily Front Page 23 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — The Short Columns
article

Google cleared 300 hectares of Finnish forest

by wetwater·▲ 320 points·233 comments·techspot.com ↗

Google cleared 300 hectares of Finnish forest for a data center, and regulators want answers

Cutting corners: Google recently announced a major expansion of its data center footprint in Finland. The US company plans to invest billions in the new infrastructure but is allegedly moving a bit too quickly with its forest-clearing plans. Regulators are now looking into the matter, and the outcome could have far-reaching consequences for the broader market.

Google was apparently so eager to build its new data center infrastructure in Finland that it began bulldozing large swaths of forest before the required environmental review of the full plan was complete. The work could now be suspended, just as other major data center projects are being delayed in the US and elsewhere around the world.

The issue surfaced last month, when Finland's Permit and Supervision Agency (Lupa- ja valvontavirasto, or LVV) asked Tuike Finland Oy (TFO) to explain its actions. TFO is Google's local company for the Finnish data center project, for which Mountain View is investing €13 billion in new AI-focused infrastructure.

In theory, TFO is supposed to operate in an environmentally friendly manner, with specific measures covering energy sustainability, job creation, and support for the local environment. Public reports cited by the LVV indicate that around 300 hectares of Finnish forest, roughly 420 football fields, had already been cleared before the project's environmental impact could be properly assessed.

Google argues that the forest clearing complied fully with Finnish laws and regulations. The site was properly surveyed before the bulldozers moved in, it said, so that no high-value environmental areas would be damaged. According to Hanna Halmeenpää, chair of the Finnish Association for Nature Conservation, things are not going quite the way Google describes.

Halmeenpää said satellite imagery shows that areas that should have been protected have already been leveled. Beyond the loss of so much forest, the outcome could be dire for wildlife preservation. She is asking the LVV to halt the entire construction site so that authorities can determine whether Google tried to bring the forest down without first obtaining formal approval.

When it comes to environmental protection standards, Finland is one of the highest-rated countries in the world. Large data center buildouts like the one TFO is pursuing carry a significant environmental cost, both in physical land consumption and power requirements.

Google may be moving faster than the procedures of local environmental authorities, but communities are increasingly voicing their dissatisfaction with the unchecked expansion of Big Tech's AI data center plans. Most likely, sending chips into space will not ease the distrust of AI infrastructure that these mega-corporations are eagerly fostering down there.

The Daily Front Page 24 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — The Short Columns
article

Docker is weird

by psxuaw·▲ 251 points·129 comments·codeandcake.dev ↗

I decided to make my own container runtime for fun, and even though I’m still early on, I’ve learned that Docker is weird. Here’s some weird things I learned about Docker.

Containers aren’t real

Unlike VMs, containers are just processes with special restrictions on them. Your kernel is still running that process! And if you know where to look, you can even find that process in /proc.

Containers really aren’t real

There’s not really a linux feature that’s just “containers” either. Instead, containers are really 5 different linux kernel features in trenchcoat.

Namespaces hide what the host and container can see, cgroups limit container resource usage, and there’s a whole bunch of networking magic I don’t understand that lets you isolate a container’s network.

Images are just folders

Images are just folders that Docker puts somewhere and then calls chroot (or pivot_root) to make that folder your container process’s new root directory. So if you run docker run -it --rm ubuntu /bin/bash, Docker is going to:

  • Download the ubuntu image from Dockerhub.
  • Put that image somewhere.
  • Run /some/weird/docker/path/bin/bash

Go is kind of a terrible language for a container runtime

Docker’s container runtime, runc, is written in Go, and Go has some design choices that make it less suited for a container runtime. Go’s runtime is natively multi-threaded. That’s a really cool feature, but it leads to some challenges in runc.

Many of the Linux syscalls a container runtime needs to make have to be done in a single-threaded environment, so runc has a crazy C module that runs before Go’s runtime initializes so it can run those syscalls.

Go also doesn’t have fork! Fork only forks the main thread, so it’s kind of a footgun in a runtime like Go’s. But a container runtime really wants to fork, set up a bunch of restrictions, and then exec the process you actually put in docker run. To get around this, runc execs /proc/self/exe with a special command line arguement that identifies it as a child process to approximate a fork.

Docker requires root!

This is pretty easy to miss if you, like me, run Docker in MacOS. Many of the Linux kernel APIs that container runtimes use require, or at least used to, to be run as root, so the Docker daemon usually runs as root. I can only imagine that container security is a very tough job.

This seems better these days. The big exception seems to be networking. If you’re running a rootless container runtime, it looks like it has to reimplement the whole networking stack in userspace to actually give you the same features!

Learning is fun!

I’ve only just started my own container runtime, and I already feel like I’ve learned so much about Docker. Writing your own version of a tool you use is a great way to learn about it!

The Daily Front Page 25 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — The Short Columns
article

AI and the Enclosure of the Scientific Commons

by jrepinc·▲ 126 points·74 comments·arxiv.org ↗

The scientific literature can be viewed as an "information commons:" an intangible resource that "no one owns and is shared by everyone." There are well-established economic and political frameworks for understanding such commons, emerging from the history of agricultural common lands found in places like preindustrial England. This article provides a primer on the history and these frameworks, and considers a key difference between the information commons and the fields of yore: while information commons are robust and immensely valuable --- some can be said to rank among humanity's greatest achievements --- the English agricultural commons no longer meaningfully exist. The latter are gone not because of the well-known "tragedy of the commons," but rather a phenomenon known as the enclosure movement (~1600--1800) that transformed the common lands into private property. Many observers, then and now, judge enclosure to have been theft at a societal scale. This article argues that artificial intelligence (AI) provides precisely the tools needed to enable a previously-infeasible enclosure of the information commons. Although AI-enabled enclosure does not operate identically to physical enclosure, it shares the key features of turning the commons into private wealth and undermining the social systems that support them (via "slop spam"). The concepts presented in this article can provide a scholarly basis for interrogating the foreboding feeling that AI may represent not just a smash-and-grab, but an attack upon a whole way of life.

The Daily Front Page 26 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — In Brief
repository

OpenAI CLI

by armcat·▲ 232 points·110 comments·github.com ↗

The official command-line tool for the OpenAI REST API.

Install · CLI reference · Guides

OpenAI CLI terminal showing commands for images, files, batches, and JSON output

Call the OpenAI REST API from your terminal or shell scripts. Generate images, upload files, submit batches, and inspect API results without writing an application.

Note

OpenAI CLI or Codex CLI? Use openai when you want to call a specific API or put API operations in a script. Use Codex CLI (codex) when you want a coding agent to work on a project: read and edit code, run commands, and help implement or debug a change.

Things to try

These examples use an API key; see installation and authentication below.

Generate an image and save it locally

openai images generate --prompt "A tiny orange robot watering a houseplant"

Images are saved to ~/Downloads/gpt-images/, and the command prints their paths. Use --output-dir for an existing destination directory or --name for a filename. Supported terminals can preview the result. See the image guide for editing, model selection, and preview settings.

Upload a file and retrieve it later

openai files upload report.txt --purpose user_data
openai files get file-example
openai files download file-example --output downloaded-report.txt

Use your own local file and replace file-example with the ID returned by the upload. See working with files for more examples.

Run requests in a batch

Submit a JSONL request file, then wait for the batch and download its results:

openai files upload requests.jsonl --purpose batch
openai batches create --input-file-id file-example \
  --endpoint /v1/responses --completion-window 24h
openai batches wait batch_example --output-dir ./results

Replace the file and batch IDs with the returned IDs. The batch guide includes a sample requests.jsonl and explains result files and failed requests.

Export API data for a script

openai models list --format jsonl | jq '.id'
openai files list --format json > files.json

Choose --format json for a JSON document or --format jsonl for records. The default output is readable text, even in pipes. The first example uses jq.

Installation

Installing a prebuilt binary

Download the archive for your operating system and architecture from GitHub Releases. Binaries are available for macOS, Linux, and Windows. Extract the archive and place openai (openai.exe on Windows) in a directory on your PATH.

Installing with Homebrew

brew install openai/tools/openai

Installing with Go

Requires Go 1.26 or later.

go install 'github.com/openai/openai-cli/cmd/openai@latest'

Once you have run go install, the binary is placed in your Go bin directory:

  • Default location: $HOME/go/bin (or $GOPATH/bin if GOPATH is set)
  • Check your path: Run go env GOPATH to see the base directory

If commands aren't found after installation, add the Go bin directory to your PATH:

# Add to your shell profile (.zshrc, .bashrc, etc.)
export PATH="$PATH:$(go env GOPATH)/bin"

The CLI checks for updates on eligible interactive runs; it never installs them automatically. Set OPENAI_CLI_NO_UPDATE_CHECK=1 to disable checks and notices. See update notices for details.

Authentication

Run the setup guide to enter your API key safely:

openai help setup

For scripts, supply OPENAI_API_KEY through your environment or secret manager. Create a key in API settings.

Try a request:

openai responses create \
  --model gpt-5.5 \
  --input "Say this is a test"

Admin endpoints use OPENAI_ADMIN_KEY, a separate admin API key. For example, retrieve one day of organization usage:

openai admin organization usage completions \
  --start-time 1735689600 \
  --end-time 1735776000 \
  --bucket-width 1d

Usage

Commands follow the API's resources:

openai <resource> [subresource...] <command> [flags...]

Browse commands and options with help. Help needs no API key or network connection.

openai --help
openai images generate --help
openai admin organization --help

openai help COMMAND and openai COMMAND --help show the same page. Existing colon-separated commands, such as openai admin:organization:usage completions, also work.

Output and errors

Successful JSON responses display readable text by default. Select a data format explicitly when parsing results. Use --transform to extract fields with GJSON syntax:

openai files get file-example --transform filename --raw-output

Errors go to stderr as readable summaries. Use --format-error json for API error details, or --transform-error to extract error fields. Explicit --format json, jsonl, raw, and yaml also apply to errors unless --format-error overrides them; --format-error text restores summaries. API error details and --debug logs can contain sensitive data: sanitize them before sharing.

Check the command's exit status before using redirected results; a failed request can leave an incomplete output file. See reading command results for list formats, streaming, binary downloads, and error behavior.

File input

Binary uploads take a plain path. JSON input flags can read a value from a local file with @path:

openai files upload report.txt --purpose user_data
openai responses create --model gpt-5.5 --input @prompt.txt

Use OPENAI_UNTRUSTED_STDIN=1 when piping JSON or YAML from an untrusted source so input cannot cause local file reads. In that mode, provide upload paths explicitly as flags. See file arguments and encoding for escaping literal @ values, JSON/YAML input, and text or base64 encoding.

Shell shortcuts

Set up shell completion to complete commands and file paths. Command insertion lets you search examples with Ctrl+X, then Tab and insert them without running them.

The first eligible interactive run saves image-picker Tab shortcuts for future Bash, zsh, and fish sessions. Open a new terminal to use them. See setup and removal for requirements and opt-out. In PowerShell, press Enter after openai images generate to open the picker.

Guides

Task Guide
Generate, edit, save, and preview images Images
Upload and download files Files
Submit batches and collect results Batches
Generate speech and work with audio Audio
Inspect and count tokens locally Tokenizer
Test webhook handling Webhooks
Parse results in scripts Output formats
Configure headers, mTLS, and file input CLI reference

Tip

Managing OpenAI resources with Terraform? Use the official OpenAI Terraform provider to manage projects, service accounts, rate limits, and other supported resources as infrastructure as code.

Development

From a clone of this repository, run the CLI with:

./scripts/run --help

To test against another OpenAI Go SDK version, use ./scripts/link:

./scripts/link github.com/org/repo@version
./scripts/link ../path/to/openai-go

With no arguments, it uses ../openai-go. See CONTRIBUTING.md for setup, checks, and repository structure.

Contributing

Please share bug reports and feature requests through GitHub issues. Pull requests are limited to repository collaborators; we do not accept pull requests from non-collaborators. See CONTRIBUTING.md for the contribution policy and development guide. For security vulnerabilities, follow SECURITY.md.

License

Copyright 2026 OpenAI

This project is licensed under the Apache License 2.0.

The Daily Front Page 27 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — Also on the Front Page
The Daily Front Page 28 of 29
Thursday, October 22, 2026 The Daily Front No. #261022 — Colophon

That's the Front for Today

Issue No. #261022 — Thursday, October 22, 2026 — went to press 2026-10-23 at 04:50 UTC.

About This Magazine

The Daily Front is a daily digital magazine assembled from the stories that reached the front page of Hacker News on Thursday, October 22, 2026. Headlines, points, and comment counts are recorded as they stood at press time. All articles remain the property of their original authors — every piece links back to its source and its discussion thread.

How It Was Made

Fetched, cleaned, and typeset by an automated pipeline. An editor model laid out the pages and chose the highlights; a second read a handful of the day's stories and briefed the cover illustrator — 32 model calls and 286k tokens in total. Set in Jacquard 12, Playfair Display, Source Serif 4, and IBM Plex Mono, all served via Google Fonts under the SIL Open Font License.

The Cover

The cover illustration was commissioned with this prompt:

In a Bengaluru certificate authority’s stark operations room, an engineer lifts a cracked glass security token from a server rack while carefully pulling its cable free; behind him, several darkened racks stand idle, and a single terminal glows with a blank, welcoming screen despite its unplugged keyboard. Beyond the open doorway, a small handheld game console lies tethered to a diagnostic harness on a workbench, its cheerful racing track frozen mid-turn. The engineer’s shadow falls across the discarded token as its fine fracture catches the room’s hard light.

Photograph the Bengaluru operations room as a gallery-scale projection-mapped installation, viewed on a 24mm tilt-shift lens: sharply bounded projected blocks of electric cyan, acid lime, and signal orange isolate the engineer lifting the cracked glass token from the server rack, his hand carefully freeing its cable; let his shadow cross the discarded token as a fine fracture catches hard projected light. Sink the idle dark racks into deep unlit negative space, with only the blank welcoming terminal glowing beside its unplugged keyboard. Through the open doorway, project a smaller vivid island around the workbench: the handheld console tethered to its diagnostic harness, cheerful racing track frozen mid-turn.

Absolutely no text, letters, numbers, readable symbols, or logos anywhere in the image. Keep the main image subject primarily below the upper 10% of the composition, where a title may be overlaid; the scene may extend naturally underneath that title area.

Production Ledger

StageModelCallsTokens InTokens Out
extractgpt-5.6-luna 28 183,487 76,692
layoutgpt-5.6-terra 1 19,031 2,767
covergpt-6-luna 2 1,784 300
covergpt-image-2.5-flare 1 298 1,372

The Publisher

Published by Johnny.

Support the Press

If The Daily Front brightens your morning, consider supporting its publisher.

Credits & Contact

All content — articles, posts, comments, and the images within them — belongs to its original authors and is reproduced here to point readers back to the source. Full credit goes to those creators; every item links to its original and its Hacker News discussion.

If you are an author and would like your content removed from an issue, write to hi@johnnys.page and it will be taken down.

Feedback is always welcome at the same address: hi@johnnys.page.

Credit where credit is due.

Every page of this issue began as someone else's work — these are the original sources, linked in full.

  1. Quad9 (DNS Resolver) to Exit France by farrokhi — quad9.net·HN discussion ↗
  2. eMudhra to exit global SSL/TLS certificate business by bo0tzz — emudhra.com·HN discussion ↗
  3. Tell HN: I unknowingly broke the PHP RCE embargo. I am sorry. by petecooper — news.ycombinator.com·HN discussion ↗
  4. Several Linux kernel vulnerabilities accidentally posted to public mailing list by mrkn1 — phoronix.com·HN discussion ↗
  5. Jailbreaking the Switch 2 by ledoge — pepsipu.com·HN discussion ↗
  6. WorldTUI: I trained a 360M model to pretend to be a terminal by alphax314 — simedw.com·HN discussion ↗
  7. Run full iOS 16.5 firmware on Android Devices by aghuang — github.com·HN discussion ↗
  8. Jared Kushner Hacked Phone Reveals Secret Negotiations, Millions in Transactions by ck2 — vanityfair.com·HN discussion ↗
  9. What’s getting pwned right now by mrkd — pwn.watch·HN discussion ↗
  10. OpenShell – A safe, private runtime for fleets of autonomous AI agents by niemandhier — github.com·HN discussion ↗
  11. The recently proposed o(n log n) integer multiplication algorithm [pdf] by craigcitro — web.maths.unsw.edu.au·HN discussion ↗
  12. Every AI model has the same "controversial" take on humans by rakannimer — modelcompare.ai·HN discussion ↗
  13. Amazon identifies Oct 17 PHP2Shell exploitation prior to public disclosure by cubefox — aws.amazon.com·HN discussion ↗
  14. Xbox wants you to pay 24 to 40 cents per hour to stream games you bought by entryleveljobsc — arstechnica.com·HN discussion ↗
  15. A farewell to Arc browser by suhdonghwi — arc.net·HN discussion ↗
  16. MPs moving to restrict gambling ads in Canada by Teever — cbc.ca·HN discussion ↗
  17. Getting ready to operate GNU Taler in Germany by dewey — taler.net·HN discussion ↗
  18. Faster than earcut: triangulating 3.7M map polygons in 489 ms by molind — globus.software·HN discussion ↗
  19. LLMs are making formal software verification feasible at a much larger scale by johnbender — anthropic.com·HN discussion ↗
  20. Crystal 1.22 by ksec — crystal-lang.org·HN discussion ↗
  21. Hedra is a 3D open world game I wrote from scratch while in highschool by maxilevi — github.com·HN discussion ↗
  22. Woman charged with computer fraud due to scam CashApp account being in her name by oidar — 404media.co·HN discussion ↗
  23. Google cleared 300 hectares of Finnish forest by wetwater — techspot.com·HN discussion ↗
  24. Docker is weird by psxuaw — codeandcake.dev·HN discussion ↗
  25. AI and the Enclosure of the Scientific Commons by jrepinc — arxiv.org·HN discussion ↗
  26. OpenAI CLI by armcat — github.com·HN discussion ↗
  27. CVE-2026-111943: Compromised Intermediate Certificate Authority by keks24 — nvd.nist.gov·HN discussion ↗
  28. Epic Games Inc v Apple Inc by Mayzie — judgments.fedcourt.gov.au·HN discussion ↗
  29. A complete bypass of eMudhra’s 1FA OTP login system by tensegrist — mastodon.catgirl.cloud·HN discussion ↗
  30. The Last Museum: Semantic search across 5.8M artworks from major museums by surprisetalk — lastmuseum.com·HN discussion ↗

Browse all issues in the archive →