10 interesting stories served every morning and every evening.

American AI is locked down and proprietary. It's losing.

werd.io

China’s open-weights AI strat­egy is win­ning: its com­pa­nies are tak­ing the lead. America’s closed-first, locked-down strat­egy is doomed to fail­ure - and it could take the US econ­omy down with it.

Link: China de­liv­ers a one-two punch to America’s AI dom­i­nance, by Robert Hart in The Verge

AI mod­els, as a prod­uct in them­selves, have very lit­tle moat be­yond what amounts to brand loy­alty and su­per­fi­cial switch­ing costs. Instead, the moat is in the en­ter­prise ser­vices that sit around them: the deals and con­tracts, con­nec­tiv­ity with en­ter­prise sys­tems, and qual­ity of life fea­tures in an en­ter­prise con­text.

If we con­sider the mod­els them­selves, it’s easy to switch be­tween them: some­one could be us­ing ChatGPT to­day and Claude to­mor­row, with very lit­tle im­pact on their work­flows. This is par­tic­u­larly true in the en­gi­neer­ing world, where mod­els are ac­cessed via API: you can swap out the API and use the same prompt.

Those com­pa­nies can make deals to lock their cus­tomers in, but in prac­tice there’s very lit­tle long-term tech­ni­cal in­cen­tive to use one ven­dor over an­other. You pick the best model for your needs and change mod­els and ven­dors if an­other one be­comes bet­ter.

The US gov­ern­ment has placed ex­port con­trols on GPUs. There are also strong reg­u­la­tions that (reasonably) pre­vent shar­ing cer­tain kinds of data with Chinese servers. The re­sult is that while Chinese com­pa­nies have enough com­pute to train mod­els, they can’t re­ally pro­vide the kinds of global-scale cen­tral­ized ser­vices that we see from OpenAI and Anthropic — at least, not in the same way.

And open al­most al­ways wins when it comes to in­fra­struc­ture adop­tion. Open tech­nolo­gies can be used per­mis­sion­lessly and there­fore can be at the cen­ter of more in­no­va­tion. You can host them where you want, ex­per­i­ment with them, al­ter them, and tweak to fit your use case. Open weights mod­els are not open source, but they are portable and per­mis­sion­less.

With all this in mind, it makes sense for China to re­lease its AI mod­els openly. It turns a US-created com­pute dis­ad­van­tage into a dis­tri­b­u­tion ad­van­tage; it com­modi­tizes the layer where American com­pa­nies make money; and it cre­ates a far more ef­fec­tive global ecosys­tem than could be es­tab­lished through locked-in, cen­tral­ized ser­vices. It’s ob­vi­ous to me that there are ecosys­tem ben­e­fits through­out China, from man­u­fac­tur­ing to sci­en­tific re­search; every sec­tor can just plug in these mod­els.

The sav­ing grace for American com­pa­nies has been that US fron­tier mod­els have out­per­formed open ones. That gap is now clos­ing:

Moonshot and Alibaba un­veiled mod­els they claim can go toe-to-toe with the best from OpenAI and Anthropic at a frac­tion of the cost. The rapid-fire re­leases sug­gest America’s lead at the AI fron­tier is in­creas­ingly tight, just as the tech­nol­ogy is be­com­ing cen­tral to na­tional se­cu­rity, eco­nomic power, and geopo­lit­i­cal in­flu­ence.”

Even with­out these new ca­pa­bil­i­ties, the strat­egy has al­ready been work­ing. a16z part­ner Martin Casado noted in the Economist that there’s an 80% chance that any given startup is us­ing Chinese mod­els, and Chinese mod­els are poised to take the lead.

It’s worth tak­ing a step back and con­sid­er­ing the sur­pris­ing un­der­ly­ing dy­nam­ics. We think of China as be­ing a locked-down so­ci­ety — and it is in many ways. I have se­ri­ous con­cerns about how these mod­els might re­flect Chinese gov­ern­ment per­spec­tives (try ask­ing them about Tiananmen Square). But it’s American com­pa­nies that are keep­ing tight con­trol of their tech­nol­ogy rather than re­leas­ing it as openly as pos­si­ble. This is in stark con­trast to the strat­egy be­hind US gov­ern­ment sup­port for the open in­ter­net, for ex­am­ple.

Locked-down busi­ness prac­tices for a tech­nol­ogy with no real moat but sig­nif­i­cant po­ten­tial ecosys­tem ben­e­fits is an ob­vi­ously los­ing strat­egy; per­mis­sively re­leas­ing it with an open, col­lab­o­ra­tive ap­proach is ob­vi­ously a win­ning one. But the in­cen­tives in the US aren’t there: in­stead, these com­pa­nies are forced to chase first-or­der prof­its rather than ecosys­tem ben­e­fits, and the gov­ern­ment tries to put its fin­ger on the scale through forcible mea­sures like tight ex­port con­trols. We should con­sider what would need to change to make those in­cen­tives more aligned. That’s par­tic­u­larly im­por­tant given how much of the US econ­omy is cur­rently dri­ven by AI spend­ing. If the bot­tom falls out of that spend­ing — and I think it clearly will, given the dy­nam­ics — the out­come could be se­vere.

I care about hav­ing open tech­nol­ogy that can be run in the pub­lic in­ter­est, aligned with the pub­lic’s val­ues. Threads like pub­lic AI, fed­er­ated ser­vices, and open re­search have trac­tion but need back­ing. Getting there in the US needs more nu­anced strat­egy and sup­port than we’re see­ing to­day.

Airport Simulator

airport.apunen.com

Hacker wipes Romania's entire land registry database

news.risky.biz

This newslet­ter is brought to you by Thinkst, the mak­ers of the much-loved Thinkst Canary. You can sub­scribe to an au­dio ver­sion of this newslet­ter as a pod­cast by search­ing for Risky Business” in your pod­catcher or sub­scrib­ing via this RSS feed. You can also add the Risky Business newslet­ter as a Preferred Source to your Google search re­sults by go­ing here.

A hacker has breached Romania’s cadas­tre agency and wiped the coun­try’s en­tire land reg­istry data­base fol­low­ing a failed ex­tor­tion at­tempt.

The hack has brought Romania’s en­tire real-es­tate mar­ket to a stand­still as of­fi­cial apps and web­sites have been of­fline for a week. Notaries can’t record new trans­ac­tions while cit­i­zens can’t ob­tain proof of own­er­ship or de­tailed land records.

Email servers at the National Agency for Cadastre and Real Estate Advertising (Agenția Națională de Cadastru și Publicitate Imobiliară, or ANCPI) were also down as part of the in­ci­dent.

Sources told Risky Business that the hacker en­tered us­ing valid cre­den­tials, mapped in­ter­nal sys­tems, and wiped sys­tems and back­ups af­ter fail­ing to ex­tort the agency.

The in­ci­dent be­came pub­lic on July 14 as the hacker started delet­ing data. A day later, some of ANCPIs stolen data was put up for sale on a known hack­ing fo­rum. The posted data in­cluded em­ployee cre­den­tials, in­ter­nal doc­u­ments, and de­tails on the agen­cy’s IT net­work.

Since the hack, of­fi­cials re­stored their web­site and posted a mes­sage an­nounc­ing they are re­build­ing the agen­cy’s en­tire net­work from scratch. Even if the hacker claims they deleted back­ups, the agency ap­pears to have had an of­fline copy, oth­er­wise things would have got­ten re­ally messy over the com­ing months in Romania.

The stolen data was posted on­line by an ac­count with the name ByteToBreach, a known hacker who also breached Sweden’s e-gov­ern­ment por­tal this year, and many other gov­ern­ment agen­cies and high-pro­file com­pa­nies over the past year.

Security firm KELA pub­lished a pro­file on ByteToBreach last December and hinted they might be lo­cated in Algeria, but since the ANCPI hack has up­dated the post and out­right doxxed the hacker as Zakaria Mahdjoub, an in­di­vid­ual from Oran, Algeria.

Well, that will make the job of Romanian law en­force­ment a hell lot eas­ier! gj!

Romania joins Poland, Slovakia, Greece, Morocco, Russia, and Ukraine as coun­tries that had their land reg­istry agen­cies hacked over the past three years.

Risky Business Podcasts

In this edi­tion of Seriously Risky Business, Tom Uren and James Wilson talk about dif­fer­ent ways ran­somware groups are tak­ing ad­van­tage of AI. The rel­a­tively new FulcrumSec group uses sim­ple tech­niques to breach com­pa­nies and then uses AI to get more lever­age over vic­tims in its ex­tor­tion ne­go­ti­a­tions.

Breaches, hacks, and se­cu­rity in­ci­dents

Hugging Face hacked us­ing AI: A threat ac­tor used an au­tonomous AI agent to breach AI plat­form Hugging Face last week. The at­tacker used ex­ploits in the plat­for­m’s data-pro­cess­ing pipeline to pivot to some parts of the com­pa­ny’s in­ter­nal sys­tems. Hugging Face says no cus­tomer data was ex­posed but the at­tacker stole in­ter­nal datasets and some cloud cre­den­tials. Hugging Face says it tried to use a fron­tier AI model to an­a­lyze the hack but was blocked by its guardrails, which could­n’t dif­fer­en­ti­ate be­tween an IR event and of­fen­sive op­er­a­tions. [Hugging Face]

HuggingFace got hacked by an AI. What stuck out to me was the guardrail asym­me­try. The at­tacker had no con­straints, but HFs re­sponse ran afoul of the abuse guardrails, forc­ing them into an un­planned switch to lo­cal mod­els.

Another as­pect for your IR plans.

hug­ging­face.co/​blog/​se­cu­rit…[im­age or em­bed]— David J. Bianco (@davidjbianco.bsky.social) July 17, 2026 at 10:59 PM

HuggingFace got hacked by an AI. What stuck out to me was the guardrail asym­me­try. The at­tacker had no con­straints, but HFs re­sponse ran afoul of the abuse guardrails, forc­ing them into an un­planned switch to lo­cal mod­els.

Another as­pect for your IR plans.

hug­ging­face.co/​blog/​se­cu­rit

[image or em­bed]

Coca-Cola hit by ran­somware: Coca-Cola has sus­pended pro­duc­tion at its Fairlife dairy sub­sidiary af­ter a ran­somware at­tack. In an SEC fil­ing, Coca-Cola said hack­ers ac­cessed Fairlife pro­duc­tion-re­lated sys­tems this week. Production has been halted at Fairlife US fac­to­ries. The com­pa­ny’s Canadian pro­duc­tion lines were un­af­fected. No ran­somware group has taken credit for the in­ci­dent, yet. [SEC // TechCrunch]

Qantas breach has a cause: The hack of Australian air­line com­pany Qantas last year was traced back to a so­cial en­gi­neer­ing at­tack. Hackers called an over­seas con­trac­tor pos­ing as the Qantas IT team to ac­cess their sys­tems, con­nect to the Qantas CRM plat­form, and ex­fil­trate the data of 5.7 mil­lion cus­tomers. Australia’s Information Commissioner says Qantas took all the steps to pro­tect cus­tomer data on its side and will not be open­ing fur­ther probes into the hack. [OAIC]

Suno hack: A threat ac­tor hacked AI mu­sic gen­er­a­tor plat­form Suno and dumped in­ter­nal files and doc­u­ments on­line. The files al­legedly show that Suno scraped mil­lions of songs and lyrics from YouTube Music, Deezer, Genius, and other mu­sic plat­forms. The leaked files in­clude source code and de­tailed scrap­ing in­struc­tions tar­get­ing the plat­forms. Several mu­sic in­dus­try groups have sued Suno over the past year for train­ing its AI song gen­er­a­tor tool on copy­righted ma­te­r­ial. Suno was al­legedly hacked fol­low­ing a com­pro­mise with the Shai-Hulud npm worm. [404 Media // The Verge]

WINDTRE fined for breaches: Italy’s pri­vacy watch­dog has fined telecom­mu­ni­ca­tions provider WINDTRE €1.7 mil­lion for serious se­cu­rity de­fi­cien­cies” that led to two se­cu­rity breaches last year. [GPDP]

KNPP leak: Threat in­tel an­a­lyst Rakesh Krishnan looks at a leak of sen­si­tive files from India’s KNPP nu­clear power plant af­ter one of its con­trac­tors got hit by the World Leaks ex­tor­tion group. [The Raven File]

Ostium crypto-heist: The Ostium DeFi plat­form was hacked for $18 mil­lion last week af­ter hack­ers ex­ploited its own price-re­port­ing in­fra­struc­ture. [CoinDesk]

Estée Lauder dis­closes Oracle EBS breach: Cosmetics gi­ant Estée Lauder has con­firmed that hack­ers stole cus­tomer data from its Oracle E-Business Suite plat­form last year. The com­pany dis­closed the breach to US state of­fi­cials al­most a year af­ter it took place. This is Estée’s sec­ond breach af­ter an­other one in 2023. The Clop hack­ing group is be­hind the hack­ing spree that tar­geted Oracle EBS servers. [California OAG]

Ernst & Young also dis­closes breach: Accounting and risk man­age­ment gi­ant Ernst & Young also dis­closed a breach, but the dis­clo­sure has been so san­i­tized of any info that I can’t tell what’s this about. [California OAG]

DigiCert breach linked to CylindricalCanine: Security firm Expel has linked the hack of cer­tifi­cate au­thor­ity DigiCert to CylindricalCanine, a sub-group of GoldenEyeDog, a fi­nan­cially mo­ti­vated group op­er­at­ing out of China. [Expel]

General tech and pri­vacy

Ofcom opens TikTok in­quiry: The UKs com­mu­ni­ca­tions watch­dog has opened a for­mal in­ves­ti­ga­tion into TikTok for fail­ing to pro­tect chil­dren from harm­ful con­tent on the plat­form, as per the UKs Online Safety Act. [Ofcom]

Moonshot re­leases Kimi K3: Chinese AI startup Moonshot has un­veiled a new AI model named Kimi K3, which the com­pany claims can ri­val the ones from top American firms like Anthropic and OpenAI. [Kimi // Business Insider]

Rust in Chromium: Microsoft is work­ing on adding a Rust-based PNG im­age de­coder in the Chromium browser pro­ject, a more se­cure com­po­nent for pro­cess­ing PNG im­ages for Chrome, Edge, Opera, and other sim­i­lar browsers. [Microsoft]

EU pass­word man­ager has ties to Russia: An in­ves­ti­ga­tion has re­vealed that Spain-based pass­word man­ager Passwork shares its code­base and a near-identical user man­ual” with a sim­i­larly-named pass­word man­ager ad­ver­tised in Russia. The Spanish ver­sion has al­legedly been re­ceiv­ing soft­ware up­dates from an UAE firm man­aged by one of Passwork’s Russian co-founders. The Spanish Passwork’s cus­tomer list in­cludes European gov­ern­ment agen­cies and uni­ver­si­ties, which raises con­cerns of es­pi­onage. [OCCRP]

India fines HP over car­tel prac­tices: The Indian gov­ern­ment fined HP $14.4 mil­lion over car­tel prac­tices af­ter the com­pany col­luded with re­sellers to fix prices for ink car­tridges, toner, and other print­ing sup­plies in gov­ern­ment con­tract bids. [ArsTechnica]

SanFran CAO cracks down on nud­ify apps: The San Francisco City Attorney’s Office has sent cease-and-de­sist let­ters to Apple and Google and or­dered the tech gi­ants to re­move AI nud­ify apps from their stores and stop in­di­rectly prof­it­ing from CSAM. [WIRED]

Government, pol­i­tics, and pol­icy

Morocco con­firmed as NSO cus­tomer: A whistle­blower and for­mer mem­ber of Morocco’s do­mes­tic in­tel­li­gence ser­vice has con­firmed their gov­ern­men­t’s ac­cess to the NSO Pegasus spy­ware, con­trary to the gov­ern­men­t’s past pub­lic de­nials. The tool was heav­ily used to spy on dis­si­dents, jour­nal­ists, and even politi­cians abroad. [OCCRP // Forbidden Stories]

UK scraps dig­i­tal ID scheme: The UK gov­ern­ment will scrap a pro­posed dig­i­tal ID scheme once its new prime min­is­ter Andy Burnham takes of­fice on Monday. The scheme was an­nounced last September and was sup­posed to en­ter into ef­fect next year. It in­volved is­su­ing a dig­i­tal ID for UK cit­i­zens and le­gal res­i­dents in the form of a mo­bile app. The ID was meant to serve as proof for the Right to Work in the UK. [Reuters]

US govt fails to ro­tate cy­ber per­son­nel: The US gov­ern­ment failed to fol­low through with one of its own pro­grams to ro­tate cy­ber­se­cu­rity em­ploy­ees be­tween fed­eral agen­cies. Only eight em­ploy­ees par­tic­i­pated in the pro­gram since 2022. The pro­gram was meant to teach em­ploy­ees new skills be­fore re­turn­ing to their na­tive agen­cies. [GAO // Cyberscoop]

White House an­nounces Gold Eagle pro­gram: The Trump ad­min­is­tra­tion has launched a new pro­gram to help co­or­di­nate the dis­clo­sure and patch­ing of vul­ner­a­bil­i­ties in open-source pro­jects and crit­i­cal in­fra­struc­ture. The new Gold Eagle pro­gram was de­signed to re­ceive bug re­ports at scale, usu­ally found us­ing AI tools and fron­tier AI mod­els. CISA, the Treasury Department, and the Pentagon are in­volved in the pro­gram. [White House]

France bans Polymarket: The French gov­ern­ment has or­dered in­ter­net ser­vice providers to block ac­cess to pre­dic­tion mar­ket bet­ting plat­form Polymarket. The French reg­u­la­tory au­thor­ity for­mally banned the plat­form in 2024 and threat­ened fines of up to €200,000 for French cit­i­zens plac­ing bets on the plat­form. The agency moved into ac­tive en­force­ment af­ter data showed Polymarket’s user­base grew in France de­spite the ban. Spain also banned Polymarket in May. [Engadget]

In this Risky Business spon­sor in­ter­view, Casey Ellis chats with Haroon Meer from Thinkst about build­ing com­pa­nies cus­tomers don’t hate. Haroon ex­plains why Thinkst still of­fers Canary to­kens for free and why it has avoided an­nual price hikes on its paid prod­ucts. They talk about Eric Ries’s Incorruptible”, Rob Lee’s 100-year-company ap­proach at Dragos, and why keep­ing cus­tomers happy is a bet­ter busi­ness strat­egy than chas­ing easy sugar highs.

Arrests, cy­ber­crime, and threat in­tel

Graykey maker sues em­ployee for leak­ing ex­ploit: Graykey-maker Magnet Forensics has sued a for­mer em­ployee for al­legedly leak­ing de­tails about a pro­pri­etary iPhone ex­ploit. Magnet claims Mario Del Gaudio shared de­tails of the ex­ploit with his new em­ployer and ri­val com­pany Paradigm Shift. The ex­ploit was tracked in­ter­nally at Magnet as MSG but was dis­closed pub­licly by Paradigm Shift in a blog post as us­bliter8. The ex­ploit al­lows at­tack­ers to run ma­li­cious code in­side the SecureROM of Apple de­vices us­ing A12 and A13 chips. It is a hard­ware bug and un­patch­able. [Bloomberg // CourtListener // us­bliter8 blog post]

TfL hack­ers get five years: A UK judge has sen­tenced two mem­bers of the Scattered Spider hack­ing group to 5.5 years in prison each. Thalha Jubair and Owen Flowers pleaded guilty last month to hack­ing the London pub­lic trans­port au­thor­ity in August of 2024. The hack caused months of dis­rup­tions at Transport for London and caused dam­ages of £39 mil­lion. Jubair is also charged in the US with hack­ing and ex­tort­ing 47 US com­pa­nies and al­legedly seek­ing ran­soms of at least $115 mil­lion. [NCA]

REvil hacker ar­rested in Armenia: Armenian au­thor­i­ties have ar­rested a sus­pected mem­ber of the REvil ran­somware group. Alexander Ermakov was ar­rested at the Yerevan air­port at the end of June on an Interpol ar­rest war­rant. A man named Alexander Ermakov is the main sus­pect be­hind the ran­somware at­tack on Australia’s Medibank in­surer in 2022. Russian me­dia claims that Armenian au­thor­i­ties ar­rested a man with the same name and that the real Ermakov is in Russia, where he is serv­ing a re­stric­tion of free­dom sen­tence that pre­vents him from trav­el­ing abroad. [RIA Novosti // Risky Business]

Scam cen­ter dis­man­tled in Timor-Leste: Police in Timor-Leste have raided three cy­ber scam com­pounds in the cap­i­tal city of Dili. Police ar­rested 253 sus­pects, with most be­ing Chinese and Indonesian na­tion­als. Authorities also raided an­other com­pound last month. [ABC]

DHS seizes 30,000 mo­bile SIM cards: The DHS Homeland Security Investigations seized more than 30,000 mo­bile SIM cards in June and July as part of a crack­down against tele­phone fraud. [Bloomberg]

GTA hacker re­leased from hos­pi­tal, sent to prison: A mem­ber of the Lapsus$ hack­ing group has been re­leased from a se­cure hos­pi­tal and trans­ferred to a nor­mal prison in the UK. Arion Kurtaj is set to face trial again for hack­ing Rockstar Games in 2022 and re­leas­ing GTA5 source code and GTA6 game­play. Kurtaj was di­ag­nosed with se­vere autism and sen­tenced to an in­def­i­nite hos­pi­tal or­der in December 2023. [GameRant // Polygon]

UAT-11795 pro­file: Cisco is track­ing a new e-crime group tar­get­ing com­pa­nies in the US and Europe with the Starland RAT and a com­mand-and-con­trol (C2) mem­ory im­plant named the WLDR Agent. [Cisco Talos]

TAG-150 evo­lu­tion: eS­en­tire has pub­lished de­tails on the changes to the trade­craft of TAG-150, an e-crime group be­hind the CastleLoader, CastleBot, and CastleRAT mal­ware strains—also tracked as DinDoor, a Deno-based loader, NightshadeC2, and DenoRAT, a Deno-based Remote Access Trojan (RAT). The biggest change is their adop­tion of ClickFix, every­one’s fa­vorite in­fec­tion vec­tor. [eSentire]

More ViPNeT ex­ploita­tion in Russia: A hack­ing group is plant­ing back­doors in­side Russian com­pa­nies us­ing the ViPNet en­ter­prise VPN soft­ware. The at­tack­ers first com­pro­mise one VPN node and then ex­ploit the soft­ware’s up­date mech­a­nism to in­stall the back­door on the whole net­work. ViPNet owner Infotecs has con­firmed the at­tacks and re­leased se­cu­rity up­dates. A sim­i­lar wave of at­tacks also took place in April last year. [Infotecs // PositiveTechnologies // Kaspersky // Last year’s at­tacks]

Scarcity scams are here to stay: Scarcity scams are a new cat­e­gory of on­line scams where threat ac­tors run fake sites for on­line ser­vices with lim­ited avail­abil­ity or spots. This type of scam has ex­ploded across the past few years and typ­i­cally tar­get the reser­va­tion sites of var­i­ous gov­ern­ment web­sites across the world. [DomainTools]

Sextortion cam­paigns: A re­cent spike in sex­tor­tion email scams has been linked to the good ol’ Trik/Phorpiex bot­net, which is still alive af­ter all these years. [PointWild]

Text salt­ing in the wild: Threat ac­tors are us­ing a tech­nique named text salt­ing” to hide text in­side their emails and by­pass email spam fil­ters for both tra­di­tional and AI-powered email se­cu­rity sys­tems. Barracuda has seen the tech­nique used in over a mil­lion re­tail-themed phish­ing scams. [Barracuda]

RubyGems mal­ware: At least two dor­mant RubyGems ac­counts have been com­pro­mised to push mal­ware to old pro­jects. [Aikido Security // Step Security]

OAuth Client ID Spoofing: Threat ac­tors are us­ing OAuth client ID spoof­ing to abuse Microsoft Entra ID for ac­count enu­mer­a­tion, check pass­word va­lid­ity, and ac­count state. The tech­nique is see­ing in­creased us­age, per Proofpoint. [Proofpoint]

Proofpoint ob­served two in­de­pen­dent cam­paigns adopt­ing this trade­craft:

• UNK_PyReq2323: >1M tar­geted users, 700K+ spoofed client IDs • UNK_OutFlareAZ: >2M tar­geted users, 3.7M spoofed client IDs

Different tool­ing and in­fra­struc­ture sug­gest grow­ing adop­tion.— ThreatInsight (@threatinsight.proofpoint.com) July 14, 2026 at 6:56 PM

Proofpoint ob­served two in­de­pen­dent cam­paigns adopt­ing this trade­craft:

• UNK_PyReq2323: >1M tar­geted users, 700K+ spoofed client IDs • UNK_OutFlareAZ: >2M tar­geted users, 3.7M spoofed client IDs

Different tool­ing and in­fra­struc­ture sug­gest grow­ing adop­tion.

Malware tech­ni­cal re­ports

XZ Utils back­door: Adrian Mastronardi has pub­lished a book with the in-depth story of the XZ Utils back­door in­ci­dent from 2024. [Half a Second]

Pegasus spy­ware: The se­cu­rity team at Amnesty International has pub­lished the most com­pre­hen­sive analy­sis of the Pegasus spy­ware to date, lever­ag­ing the in­sights from past re­ports and the re­cent WhatsApp law­suit. [Amnesty International]

ClickLock Stealer: A new in­fos­tealer tar­get­ing ma­cOS users has been spot­ted in the wild. This one has been named ClickLock be­cause it blends ClickFix and locker tac­tics for its dis­tri­b­u­tion and in­stal­la­tion process. [Group-IB]

CrashStealer: There’s also an­other ma­cOS in­fos­tealer in the wild, named CrashStealer be­cause it tries to im­per­son­ate Apple’s crash-re­port­ing frame­work to har­vest browser cre­den­tials, cryp­tocur­rency wal­lets, and key­chain data. [Jamf]

ACR Stealer: Microsoft has re­ported an in­crease in at­tacks de­ploy­ing the ACR Stealer across cus­tomer en­vi­ron­ments since April. [Microsoft]

BoryptGrab: Almost 300 GitHub repos­i­to­ries im­per­son­at­ing le­git­i­mate soft­ware were ac­tu­ally spread­ing a ver­sion of the BoryptGrab in­fos­tealer. [Arctic Wolf]

TELEPUZ: Elastic has spot­ted a new mal­ware frame­work be­ing de­ployed in the wild that ap­pears to be re­lated to an up­com­ing MaaS. [Elastic]

Spirals ran­somware: Broadcom’s Symantec team has spot­ted a new ran­somware strain named Spirals be­ing de­ployed in Asia. Not much in­for­ma­tion about it so far. [Broadcom]

NadMesh bot­net: A newly dis­cov­ered bot­net is specif­i­cally tar­get­ing AI in­fra­struc­ture and the MCP ecosys­tem. The NadMesh bot­net has tar­geted Ollama, ComfyUI, and other AI-related servers since early July. The bot­net plants SSH back­doors for con­trol and fu­ture ac­cess. According to Chinese se­cu­rity firm QiAnXin, the bot­net ap­pears to be an industrial-grade” op­er­a­tion with a clear com­mer­cial in­tent.” [QiAnXin]

OkoBot frame­work: Researchers have found a new mod­u­lar mal­ware frame­work named OkoBot that re­sem­bles an in­fos­tealer but puts more fo­cus on steal­ing sen­si­tive data from cryp­tocur­rency own­ers and re­lated ser­vices. [Kaspersky]

The OkoBot cam­paign has been on­go­ing for over a year, and it re­mains ac­tive at the time of pub­li­ca­tion. Moreover, it is adapt­ing, which in­di­cates that this frame­work is be­ing main­tained and dis­tri­b­u­tion cam­paigns con­tinue.”

WackoGinx phish­ing kit: Researchers have found a new phish­ing kit named WackoGinx (also WachoGinx) that can run cam­paigns tar­get­ing M365, Facebook, Gmail, LinkedIn, and PayPal. [Threatactix]

In this Soap Box edi­tion of the pod­cast, Patrick Gray chats with Thinkst Canary founder Haroon Meer about his decade of de­cep­tion.”

APTs, cy­ber-es­pi­onage, and info-ops

UTA0533 is be­hind new SonicWall zero-day wave: A hack­ing group tracked as UTA0533 is be­hind two zero-days ex­ploited in SonicWall SMA ap­pli­ances. The zero-days in­clude an SSRF and a code in­jec­tion vul­ner­a­bil­ity that grant the group root-level ac­cess to the de­vice. The at­tacks be­gan in late June and are de­ploy­ing mal­ware de­signed specif­i­cally for SonicWall SMA VPN ap­pli­ances. SonicWall re­leased patches for both zero-days last week. [Volexity // SonicWall patches]

GoSerpent cam­paign: Kaspersky is track­ing a new APT group de­ploy­ing the GoSerpent back­door, Stowaway, and TmcLoader in cam­paigns tar­get­ing gov­ern­ment and diplo­matic en­ti­ties in Southeast Asia. No at­tri­bu­tion yet. [Kaspersky]

Laundry Bear mem­ber worked at Kaspersky: Denis Obrezko, the Russian na­tional who was ar­rested in Thailand last year, ex­tra­dited to the US, and charged with hacks part of the Laundry Bear APT group, also worked for Russian se­cu­rity firm Kaspersky. A team of threat in­tel an­a­lysts go­ing by Ctrl-Alt-Intel has also pub­lished a pro­file on Obrezko and the opsec mis­takes that led to his ar­rest, which is well worth your read. [Reuters // Ctrl-Alt-Intel]

Love that a leaked McDonald’s or­der helped cor­rob­o­rate the at­tri­bu­tion 😂 Great piv­ots! https://​t.co/​XZUe­BAWZYZ— Chi-en (Ashley) Shen (@ashl3y-shen.bsky.social) (@ashl3y_shen) July 14, 2026

Love that a leaked McDonald’s or­der helped cor­rob­o­rate the at­tri­bu­tion 😂 Great piv­ots! https://​t.co/​XZUe­BAWZYZ

Sandworm adopts ClickFix: Even if they’re one of Russia’s most ad­vanced cy­ber-es­pi­onage groups, Sandworm is now us­ing ClickFix for mal­ware de­liv­ery. [CERT-UA]

More DPRK on npm: OSMs Jenn Gile has linked two clus­ters of npm mal­ware back to North Korean hack­ers and their PolinRider cam­paign. [OpenSourceMalware]

Operation Capsule Vault: And speak­ing of DPRK hack­ing cam­paigns, there’s one spread­ing the RokRAT mal­ware us­ing edu- and aca­d­e­mic-re­lated phish­ing lures. [Genians]

Contagious Interview cam­paign: There’s noth­ing more dan­ger­ous right now than try­ing to find a job in the IT sec­tor, thanks to North Korean hack­ers! Putting the irony aside, there’s a new re­port on the Contagious Interview cam­paign that Elastic tracks as REF9403 ac­tiv­ity. The re­port cov­ers the use of SVG files to hide ma­li­cious com­mands via steganog­ra­phy, which is kind of orig­i­nal in its own spe­cific way be­cause SVG files haven’t been broadly abused for steganog­ra­phy un­til now. [Elastic]

Vulnerabilities, se­cu­rity re­search, and bug bounty

wp2shell vul­ner­a­bil­ity: The WordPress team has re­leased a se­cu­rity up­date to patch one of the most crit­i­cal bugs ever found in the pro­jec­t’s code. The vul­ner­a­bil­ity is an SQL in­jec­tion in the WordPress REST API that can be ex­ploited by re­mote unau­then­ti­cated at­tack­ers to run ma­li­cious code on any WordPress site. The is­sue can be ex­ploited with­out any pre­con­di­tions and im­pacts all WordPress ver­sions re­leased since last December. WordPress sites power more than 41% of all in­ter­net sites. The bug was dis­cov­ered by Searchlight Cyber and is tracked as CVE-2026 – 63030, or wp2shell. [Searchlight Cyber // wp2shell // WordPress patch]

HollowByte at­tack: A new vul­ner­a­bil­ity can crash OpenSSL servers us­ing only an 11 bytes pay­load. The at­tack can be ex­ploited by re­mote unau­then­ti­cated at­tack­ers and force servers to al­lo­cate huge amounts of mem­ory be­fore any se­cure TLS hand­shake even be­gins. The OpenSSL pro­ject re­leased patches for both cur­rent and old li­brary ver­sions last month. The vul­ner­a­bil­ity was dis­cov­ered by Okta and is named HollowByte. [Okta]

Android lockscreen by­pass: Just like Siri has been ex­ploited for years to by­pass the lockscreen, it’s now Gemini’s turn to be abused to by­pass the Android lockscreen. [Android Headlines]

Vulnerability dis­clo­sure guide: CISA and in­ter­na­tional part­ners have re­leased joint guid­ance on es­tab­lish­ing proper co­or­di­nated dis­clo­sure pro­grams. [CISA]

Nightmare Eclipse drops LegacyHive: Security re­searcher Nightmare Eclipse has re­leased a new Windows ex­ploit last week. Named LegacyHive, the zero-day is a lo­cal priv­i­lege es­ca­la­tion in the Windows User Profile Service. [Project Nightcrawler // GitHub // SecurityWeek]

AoE RCE: The last thing you ever ex­pected is prob­a­bly a re­mote code ex­e­cu­tion ex­ploit in the good ol’ Age of Empires game.

Here’s the Age of Empires RCE from yes­ter­day’s Patch Tuesday: CVE-2026 – 50663.Join an at­tack­er’s lobby, (auto-)accept UCG, and you get re­mote code ex­e­cu­tion. pic.twit­ter.com/​QmMkY07C8S— Rick de Jager (@rdjgr) July 15, 2026

Here’s the Age of Empires RCE from yes­ter­day’s Patch Tuesday: CVE-2026 – 50663.

Join an at­tack­er’s lobby, (auto-)accept UCG, and you get re­mote code ex­e­cu­tion. pic.twit­ter.com/​QmMkY07C8S

Who’s Afraid of Chinese Models?

stratechery.com

Listen to this post:

There’s a story I tell about my first day in STRT-431 at Kellogg School of Management, the in­tro­duc­tory class that every first-year MBA was re­quired to take; I leafed through the read­ings and case stud­ies and was dis­mayed that there weren’t any tech com­pa­nies on the docket. Me be­ing me, I spoke to the pro­fes­sor af­ter class won­der­ing why, and was told that the goal of the course was not to nec­es­sar­ily learn about spe­cific in­dus­tries, but rather to un­cover broadly ap­plic­a­ble uni­ver­sal prin­ci­ples that could be ap­plied to any com­pany in any in­dus­try.

I did not, as I usu­ally tell the story, find this very sat­is­fac­tory: to me the na­ture of tech, par­tic­u­larly the fact that soft­ware and dis­tri­b­u­tion had zero mar­ginal costs (and zero trans­ac­tion costs), was some­thing fun­da­men­tally dif­fer­ent; putting in ze­roes in for­mu­las tends to wreak havoc! I soon re­al­ized, how­ever, that that was my op­por­tu­nity. The fun­da­men­tal in­sight un­der­gird­ing Aggregation Theory is that zero mar­ginal costs leads to fun­da­men­tally dif­fer­ent value chains than peo­ple once ex­pected from the Internet: cen­tral­iza­tion and scale in a world where con­trol­ling de­mand mat­tered more than dis­trib­ut­ing sup­ply.

What is fas­ci­nat­ing about AI, how­ever, is the ex­tent to which those old uni­ver­sal prin­ci­ples are com­ing back to the fore­front. That was never more ap­par­ent than this past week­end, when ar­gu­ments raged on X about the im­pli­ca­tions of Kimi K3, an­other open weights model out of China, ap­proach­ing the state-of-the-art in terms of ca­pa­bil­i­ties. The long and short of it is this: mar­ginal costs are back in a big way, both in terms of short-term im­pli­ca­tions of state-of-the-art free mod­els, and in terms of the long-term struc­ture of the in­dus­try.

COGS Versus R&D

One of the most com­mon mis­con­cep­tions un­der­gird­ing dis­cus­sion of open weights mod­els is that they are cheaper — free, even. After all, you can just down­load the weights, and skip the time and ex­pense and ca­pa­bil­i­ties nec­es­sary to cre­ate your own model. That is, of course, true, but the free” in this case is a ref­er­ence to the amount you need to spend on re­search and de­vel­op­ment; R&D is a fixed ex­pense that is in­de­pen­dent of the rev­enue you gen­er­ate. If you spend $1 mil­lion in R&D, it does­n’t mat­ter if you do $100 thou­sand in rev­enue or $100 mil­lion; you still spent $1 mil­lion on R&D (it does, of course, im­pact your prof­itabil­ity).

What is re­lated to rev­enue is COGS — cost of goods sold — and COGS is real for AI in a way it has­n’t been for soft­ware for a very long time. Specifically, run­ning in­fer­ence on a model — whether that model be Kimi or Fable — costs money, and the amount of money an AI provider spends on in­fer­ence is, at least in most busi­ness mod­els, di­rectly cor­re­lated to rev­enue. To reuse the above ex­am­ple, gen­er­at­ing $100 mil­lion ver­sus $100 thou­sand in rev­enue will likely re­quire 1,000x COGS. In con­crete terms, if it costs 50 cents to gen­er­ate the to­kens that drive $1 in rev­enue, then $100 mil­lion in rev­enue will have $50 mil­lion in COGS; $100 thou­sand in rev­enue will only have $50 thou­sand in COGS.

The point in terms of open weight mod­els is that they are not free to serve. Kimi K3 costs $3 per mil­lion in­put to­kens, and $15 per mil­lion out­put to­kens; that is cheaper than Sol’s $5 per mil­lion in­put to­kens and $30 per mil­lion out­put to­kens, but that might not even be the right mea­sure­ment.

Tokens Versus Intelligence

Nvidia CEO Jensen Huang has de­scribed what Nvidia is build­ing as token fac­to­ries”, and from Nvidia’s per­spec­tive that fram­ing makes sense. Nvidia GPUs are model ag­nos­tic: they gen­er­ate to­kens, and do so in the fastest and most ef­fi­cient way pos­si­ble. That leads to mea­sure­ments like to­kens-per-sec­ond, time-to-first-to­ken, to­kens-per-watt, to­ken cost, etc., and Huang ar­gues that these met­rics will be the ba­sis for de­ci­sion-mak­ing.

This is a fram­ing that def­i­nitely made sense dur­ing the first par­a­digm of AI, the ChatGPT era, when to­kens were de­liv­ered straight to the end user. The sec­ond par­a­digm of AI, how­ever, the rea­son­ing era, con­founds this mea­sure­ment. Reasoning en­tails an ex­plo­sion in chain-of-thought to­kens, and dif­fer­ent mod­els need dif­fer­ent amounts of rea­son­ing to­kens to ar­rive at the right an­swer. Kimi, for ex­am­ple, re­port­edly uses sig­nif­i­cantly more to­kens than Sol, ren­der­ing its price ad­van­tage moot. Agents in­tro­duce a sim­i­lar dy­namic: some mod­els are more ef­fi­cient than oth­ers in terms of the num­ber of to­kens they need to ex­e­cute agen­tic work­flows.

What this means is that to­kens are not a com­mod­ity. The defin­ing char­ac­ter­is­tic of a com­mod­ity is that it is fun­gi­ble: a gal­lon of oil is a gal­lon of oil; a ton of cop­per is a ton of cop­per; a bushel of wheat is a bushel of wheat. A to­ken from one model, how­ever, is not the same as a to­ken from an­other model. What is fun­gi­ble is what is con­structed from to­kens, which is to say in­tel­li­gence. In other words, if both Kimi and Sol gen­er­ated the right an­swer, then that an­swer is fun­gi­ble; the dif­fer­ence in to­kens gen­er­ated to get to that right an­swer is a con­trib­u­tor to a dif­fer­ence in COGS.

The COGS for in­tel­li­gence is a func­tion of a few dif­fer­ent fac­tors:

Model foot­print: The weights and run­time state de­ter­mine how much ex­pen­sive mem­ory and how many ac­cel­er­a­tors are re­quired to host each serv­ing replica.

Inference ef­fi­ciency: Architectural choices (e.g. Mixture-of-Experts) re­duce com­pu­ta­tion per gen­er­ated to­ken.

Memory ef­fi­ciency: Architectural choices can re­duce KV cache re­quire­ments, al­low­ing more con­cur­rent re­quests and bet­ter GPU uti­liza­tion.

Serving ef­fi­ciency: Batching, sched­ul­ing, pre­fix caching, and other in­fer­ence op­ti­miza­tions max­i­mize uti­liza­tion and share work across re­quests.

Token ef­fi­ciency: The fewer to­kens re­quired to reach a cor­rect an­swer, the lower the in­fer­ence cost.

The rea­son this mat­ters is that we are rapidly ap­proach­ing a state in which in­tel­li­gence for many eco­nom­i­cally ben­e­fi­cial tasks is in fact a com­mod­ity. Anyone build­ing a ba­sic CRUD app, for ex­am­ple, can likely do so us­ing mod­els from mul­ti­ple providers. And, in a com­mod­ity mar­ket, the route to prof­itabil­ity is not through charg­ing higher prices — again, you can (or will soon be able to) make the ex­act same app us­ing mul­ti­ple mod­els — but rather through hav­ing a su­pe­rior cost struc­ture.

Understanding Commodity Markets

It’s worth step­ping through the me­chan­ics here, be­cause, as I noted a few months ago in Amazon’s Durability, the dy­nam­ics of com­mod­ity mar­kets are not some­thing peo­ple in tech are gen­er­ally fa­mil­iar with:

In com­mod­ity mar­kets, every­one charges the same price, be­cause every­one is sell­ing the same thing; that price is de­ter­mined by sup­ply and de­mand.

The de­mand for a com­mod­ity is a func­tion of price elas­tic­ity: the cheaper the com­mod­ity, the more de­mand there is for it, and vice-versa.

The sup­ply for a com­mod­ity is a func­tion of the mar­ginal cost of pro­duc­ing the com­mod­ity.

The key thing to un­der­stand is that the mar­ginal cost of pro­duc­ing the com­mod­ity dif­fers by sup­plier. What this means in prac­tice is that the sup­plier with the worst cost struc­ture ends up sell­ing the com­mod­ity at their mar­ginal cost (if they can pro­duce at all); the prof­its of every­one else de­pend on the ex­tent to which their cost struc­ture is bet­ter than the mar­ginal sup­plier.

As an ex­am­ple:

Supplier A can pro­duce 10 units of the com­mod­ity for $10 each

Supplier B can pro­duce 10 units of the com­mod­ity for $15 each

Supplier C can pro­duce 10 units of the com­mod­ity for $20 each

Let’s as­sume the price elas­tic­ity is such that there is de­mand for 25 units of the com­mod­ity at $20. That means:

Supplier A will sell 10 units of the com­mod­ity for $20, earn­ing $10/unit

Supplier B will sell 10 units of the com­mod­ity for $20, earn­ing $5/unit

Supplier C will sell 5 units of the com­mod­ity for $20, earn­ing $0/unit

This is­n’t pre­cisely right: the rea­son why Supplier C will bear the short­fall is be­cause Suppliers A and B will be able to slightly un­der­cut them in price, which will of course af­fect de­mand (which is elas­tic), but it makes the point. Supplier A has a great busi­ness, Supplier B has a good busi­ness, and Supplier C is go­ing to go bank­rupt.

Bankruptcy risk is where fixed costs come back to the fore­front: Supplier C has both fixed costs (like po­ten­tially R&D spend) and also may have taken on debt to fi­nance the equip­ment nec­es­sary to pro­duce the com­mod­ity. It can’t price its com­mod­ity with these costs in mind — re­mem­ber, the mar­ket-clear­ing price ap­prox­i­mates the mar­ginal cost of the high­est-cost unit needed to sat­isfy de­mand — but those costs can ab­solutely drive the sup­plier out of busi­ness. And, if that sup­plier goes out of busi­ness, then prices go up, un­til an­other sup­plier de­cides to en­ter (or the other sup­pli­ers ex­pand).

The Intelligence Market

Let’s bring this back to mod­els. Right now, none of the above analy­sis ap­plies be­cause de­mand ex­ceeds sup­ply for fron­tier mod­els, and sup­ply is lim­ited by a lack of com­pute. This com­pute short­age does­n’t just mean that a com­pute sup­plier like Nvidia makes very large mar­gins, but also that Nvidia’s cus­tomers, like SpaceXAI, can turn around and re­sell com­pute at high mar­gins as well to a com­pany like Anthropic. Anthropic, mean­while, can pay the markup be­cause they can sell to­kens with a higher markup still.

It’s not just ex­cess de­mand that gives Anthropic great mar­gins, how­ever: Anthropic and OpenAI likely have among the low­est costs per unit of fron­tier-qual­ity in­tel­li­gence, thanks to model ca­pa­bil­ity, serv­ing scale, and to­ken ef­fi­ciency. They are serv­ing mod­els at a par­tic­u­lar ca­pa­bil­ity level for months be­fore their com­peti­tors, and are si­mul­ta­ne­ously ap­ply­ing the best mod­els to op­ti­miz­ing those costs.

It’s also worth not­ing that the mar­ket is not yet treat­ing in­tel­li­gence like a com­mod­ity: de­mand is for Anthropic and OpenAI specif­i­cally, and much less for mod­els that aren’t as good (thus SpaceXAI and Meta sell­ing ca­pac­ity to Anthropic); one way to think about the push for op­ti­miz­ing cost is that that is a func­tion of defin­ing jobs-to-be-done by in­tel­li­gence level, such that in­tel­li­gence buy­ers can cre­ate a mar­ket where in­tel­li­gence is com­modi­tized. In the long run, how­ever, who­ever is on the fron­tier is the best placed to dom­i­nate non-fron­tier mar­kets as well, which are just the fron­tier mi­nus n-months, i.e. months in which the fron­tier model mak­ers have been op­ti­miz­ing their cost of serv­ing.

All of this is to say that I think the re­ac­tion to Kimi and Chinese mod­els gen­er­ally is pretty over-blown, at least from an eco­nomic per­spec­tive. Right now there is a price um­brella that is down­stream of the lack of com­pute; I highly doubt that Chinese mod­els are cheaper to serve on a mar­ginal cost ba­sis, they just seem cheaper be­cause Anthropic and OpenAI are so sup­ply con­strained that they are charg­ing far more than they would if there were suf­fi­cient sup­ply to meet the de­mand for in­tel­li­gence.

Frontier Lab Paranoia

Why, then, do the model mak­ers in par­tic­u­lar seem so pan­icked about Chinese mod­els?

First, I think the fron­tier labs are an­chored in a world where train­ing costs dom­i­nated their fi­nan­cial mod­el­ing. As long as train­ing con­sumed more GPUs than in­fer­ence, it was crit­i­cal to max­i­mize in­fer­ence rev­enue to help fund the next train­ing run, which meant charg­ing very high prices for in­fer­ence.

Going for­ward, how­ever, I ex­pect the in­fer­ence mar­ket to grow much faster than train­ing costs (and that in­cludes the as­sump­tion that train­ing costs will con­tinue to sky­rocket), which means they re­ally can make it up in vol­ume. It was­n’t clear this would be the case as re­cently as eight months ago, but the agent par­a­digm un­lock is so mas­sive that fron­tier labs should have more con­fi­dence that they can not just sur­vive but thrive with lower prices (once they have suf­fi­cient com­pute).

Second, in­tel­li­gence is­n’t in fact a per­fect com­mod­ity, in part be­cause ap­plied in­tel­li­gence makes it­self smarter. Specifically, who­ever is run­ning in­fer­ence is also col­lect­ing data, and that data goes into mak­ing the next it­er­a­tion of the model bet­ter. This is, on one hand, all the more rea­son for the fron­tier labs to lower prices and in­crease us­age as more com­pute comes on­line; on the other hand, this is why com­pa­nies like Microsoft are in­creas­ingly ob­sessed with help­ing com­pa­nies run their own mod­els. That is much more vi­able if Chinese mod­els are a vi­able al­ter­na­tive.

Third, the other way that fron­tier labs can not only dif­fer­en­ti­ate from Chinese mod­els but also from each other is by con­tin­u­ing to in­te­grate up into the cus­tomer ex­pe­ri­ence. It’s strik­ing the ex­tent to which Claude Code and Codex are prov­ing to be quite sticky; whichever har­ness you start work­ing with is likely to be the one you stick with, and that fig­ures to be even more the case with non-tech­ni­cal users. And, in the long run, this im­per­a­tive to move up the stack does mean that fron­tier mod­els are ab­solutely a threat to soft­ware providers, in­clud­ing Microsoft. On the flip­side, the ex­tent to which soft­ware com­pa­nies who cur­rently own the cus­tomer ex­pe­ri­ence have ac­cess to com­pet­i­tive mod­els is the ex­tent to which they may be able to re­sist the en­croach­ment of the fron­tier labs.

Finally, the ide­o­log­i­cal an­gle of Anthropic in par­tic­u­lar is im­pos­si­ble to ig­nore. This is a com­pany that be­lieves only it can be en­trusted with AI, and the ex­is­tence of open weights al­ter­na­tives strikes a fa­tal blow to that pre­sump­tion.

China’s Motivation

Kimi is­n’t the only new Chinese model; from Bloomberg:

Alibaba Group Holding Ltd. shares rose as much as 5.4% on Monday af­ter the com­pany launched a pre­view ver­sion of its flag­ship Qwen3.8 Max model, de­scrib­ing it as sec­ond only to Anthropic PBCs Fable 5. The Sunday re­lease came only days af­ter startup Moonshot AI un­veiled a pow­er­ful new of­fer­ing that’s roiled mar­kets and trig­gered con­cern in the US about China clos­ing the gap on global lead­ers like Anthropic and OpenAI. Qwen3.8 Max has 2.4 tril­lion pa­ra­me­ters, join­ing Moonshot’s Kimi K3 in the heavy­weight class. With 2.8 tril­lion pa­ra­me­ters, K3 ri­vals top of­fer­ings and Alibaba is set­ting sim­i­larly high ex­pec­ta­tions.

Developers can now ac­cess Qwen3.8 Max through Alibaba’s cod­ing plat­forms, in­clud­ing Qoder. Alibaba plans to make the model open-weight soon, ex­pand­ing ac­cess be­yond the pre­view re­lease. Interest in these made-in-China ar­ti­fi­cial in­tel­li­gence sys­tems and mod­els is so high that Moonshot was forced to pause tak­ing on new sub­scrip­tions late on Sunday to man­age over­whelm­ing de­mand.

Alibaba Group Holding Ltd. shares rose as much as 5.4% on Monday af­ter the com­pany launched a pre­view ver­sion of its flag­ship Qwen3.8 Max model, de­scrib­ing it as sec­ond only to Anthropic PBCs Fable 5. The Sunday re­lease came only days af­ter startup Moonshot AI un­veiled a pow­er­ful new of­fer­ing that’s roiled mar­kets and trig­gered con­cern in the US about China clos­ing the gap on global lead­ers like Anthropic and OpenAI. Qwen3.8 Max has 2.4 tril­lion pa­ra­me­ters, join­ing Moonshot’s Kimi K3 in the heavy­weight class. With 2.8 tril­lion pa­ra­me­ters, K3 ri­vals top of­fer­ings and Alibaba is set­ting sim­i­larly high ex­pec­ta­tions.

Developers can now ac­cess Qwen3.8 Max through Alibaba’s cod­ing plat­forms, in­clud­ing Qoder. Alibaba plans to make the model open-weight soon, ex­pand­ing ac­cess be­yond the pre­view re­lease. Interest in these made-in-China ar­ti­fi­cial in­tel­li­gence sys­tems and mod­els is so high that Moonshot was forced to pause tak­ing on new sub­scrip­tions late on Sunday to man­age over­whelm­ing de­mand.

The fact that Qwen3.8 Max will also have open weights is no­table. Alibaba stopped re­leas­ing weights for its lead­ing edge mod­els ear­lier this year, but ap­pears to have re­verted that change; I sus­pect that shift was re­lated to last week’s Xi Jinping speech about AI that dou­bled down on the open weights ap­proach:

We should ad­here to the prin­ci­ple of open­ness and win-win and boost in­no­va­tion-dri­ven de­vel­op­ment. As a new en­gine of world eco­nomic growth and an ac­cel­er­a­tor for the shift of growth dri­vers, AI is mov­ing from the dig­i­tal world into the phys­i­cal world. We should seize this rare, his­toric op­por­tu­nity to en­cour­age open source, open­ness, col­lab­o­ra­tion and shar­ing. We should fa­cil­i­tate tech­no­log­i­cal in­no­va­tion, in­dus­trial de­vel­op­ment and sce­nario-based ap­pli­ca­tion of AI. We should make co­or­di­nated ad­vances in the trans­for­ma­tion and up­grade of tra­di­tional in­dus­tries, the cul­ti­va­tion and growth of emerg­ing in­dus­tries and for­ward-look­ing plan­ning for fu­ture in­dus­tries, so that all sec­tors and busi­nesses can ben­e­fit from AI.

We should ad­here to the prin­ci­ple of open­ness and win-win and boost in­no­va­tion-dri­ven de­vel­op­ment. As a new en­gine of world eco­nomic growth and an ac­cel­er­a­tor for the shift of growth dri­vers, AI is mov­ing from the dig­i­tal world into the phys­i­cal world. We should seize this rare, his­toric op­por­tu­nity to en­cour­age open source, open­ness, col­lab­o­ra­tion and shar­ing. We should fa­cil­i­tate tech­no­log­i­cal in­no­va­tion, in­dus­trial de­vel­op­ment and sce­nario-based ap­pli­ca­tion of AI. We should make co­or­di­nated ad­vances in the trans­for­ma­tion and up­grade of tra­di­tional in­dus­tries, the cul­ti­va­tion and growth of emerg­ing in­dus­tries and for­ward-look­ing plan­ning for fu­ture in­dus­tries, so that all sec­tors and busi­nesses can ben­e­fit from AI.

The strat­egy for China is ob­vi­ous: com­modi­tize your com­ple­ments. Note that Xi ex­plic­itly ties open­ness to AI moving from the dig­i­tal world into the phys­i­cal world”; the phys­i­cal world is the world dom­i­nated by China, and the coun­try’s lead in ar­eas like ro­bot­ics is go­ing to mas­sively ben­e­fit from widely avail­able AI mod­els.

Along the same lines, China does not want the U.S. to gain an asym­met­ric ad­van­tage in AI; to the ex­tent that China can weaken the U.S. fron­tier labs while strength­en­ing any and all po­ten­tial U.S. ad­ver­saries so much the bet­ter, and it can ben­e­fit from the in­no­va­tion that will at­tach it­self to an open ecosys­tem.

The Distillation Question

By the same to­ken, don’t ex­pect China to do any­thing about dis­til­la­tion at­tacks on the fron­tier labs. I think it is mis­taken to at­tribute all of the suc­cess of Chinese labs to dis­til­la­tion, but it’s just as much of a mis­take to pre­tend like dis­til­la­tion does­n’t give Chinese labs a big ad­van­tage. That ad­van­tage has re­ally come to bear in the last year as post-train­ing re­in­force­ment learn­ing has be­come in­creas­ingly cru­cial to model per­for­mance. Instead of hav­ing to fash­ion re­in­force­ment learn­ing en­vi­ron­ments from scratch, Chinese labs can sim­ply use fron­tier labs mod­els as teach­ers, al­low­ing for rapid im­prove­ment at much lower costs (this is not the only rea­son why Chinese mod­els are cheaper to de­velop, but it’s a big one).

What is in­ter­est­ing is that one of the most im­por­tant use cases for Chinese mod­els in the West is it­self dis­til­la­tion. Thinking Machines, for ex­am­ple, which just re­leased an open-weight model, re­lies on Chinese mod­els to solve the cold start prob­lem for re­in­force­ment learn­ing. Dean Meyer and Konstantine Buhler wrote an ex­cel­lent ar­ti­cle on X ex­plain­ing that dis­til­la­tion means that Western open weight mod­els are fun­da­men­tally dis­ad­van­taged rel­a­tive to China:

Distillation does not ex­plain China’s en­tire open-model lead. Chinese labs have world-class re­searchers, sub­stan­tial com­pute, strong pre-trained mod­els, soft­ware-hard­ware code­sign, and rapidly im­prov­ing post-train­ing ca­pa­bil­i­ties. But dis­til­la­tion com­presses the costly fi­nal gap be­tween a strong base and a near-fron­tier sys­tem. Even if dis­til­la­tion rep­re­sents a smaller share of a Chinese mod­el’s to­tal ca­pa­bil­ity, it rep­re­sents a mean­ing­ful share of its ad­van­tage over American open mod­els.

New en­force­ment mech­a­nisms will make large-scale dis­til­la­tion harder, slower, and more ex­pen­sive for Chinese com­pa­nies. However, en­force­ment will not elim­i­nate dis­til­la­tion backed by state ac­tors. Every Western fron­tier ad­vance there­fore cre­ates an­other teacher for Chinese labs. Western builders must ei­ther re­pro­duce those ca­pa­bil­i­ties in­de­pen­dently or wait to learn from Chinese mod­els. This gap gives Chinese labs a re­cur­ring struc­tural ad­van­tage over Western com­pa­nies.

Distillation does not ex­plain China’s en­tire open-model lead. Chinese labs have world-class re­searchers, sub­stan­tial com­pute, strong pre-trained mod­els, soft­ware-hard­ware code­sign, and rapidly im­prov­ing post-train­ing ca­pa­bil­i­ties. But dis­til­la­tion com­presses the costly fi­nal gap be­tween a strong base and a near-fron­tier sys­tem. Even if dis­til­la­tion rep­re­sents a smaller share of a Chinese mod­el’s to­tal ca­pa­bil­ity, it rep­re­sents a mean­ing­ful share of its ad­van­tage over American open mod­els.

New en­force­ment mech­a­nisms will make large-scale dis­til­la­tion harder, slower, and more ex­pen­sive for Chinese com­pa­nies. However, en­force­ment will not elim­i­nate dis­til­la­tion backed by state ac­tors. Every Western fron­tier ad­vance there­fore cre­ates an­other teacher for Chinese labs. Western builders must ei­ther re­pro­duce those ca­pa­bil­i­ties in­de­pen­dently or wait to learn from Chinese mod­els. This gap gives Chinese labs a re­cur­ring struc­tural ad­van­tage over Western com­pa­nies.

This is a point that bears re­peat­ing: be­cause U.S. open weight model mak­ers must fol­low the fron­tier labs’ terms of ser­vice, they (1) are worse than Chinese al­ter­na­tives and (2) end up dis­till­ing the dis­til­la­tion, just with a de­tour through Chinese labs. Wouldn’t it be bet­ter if west­ern open weight model mak­ers could go to the source?

To that end, here’s an even more in­ter­est­ing ques­tion around dis­til­la­tion: why ex­actly is it bad? After all, what are large lan­guage mod­els but the dis­til­la­tion of all of the knowl­edge on the open Internet, scraped by the fron­tier labs and dis­tilled into the mod­els that are them­selves be­ing dis­tilled? Who is ex­actly be­ing wronged here?

In fact, this para­dox is the so­lu­tion. I be­lieve that open weight mod­els are good for in­no­va­tion (and, per the above, I think that labs on the fron­tier will be fine), but it’s a prob­lem to be de­pen­dent on China. The U.S. should pass a law that (1) makes ex­plicit that col­lect­ing data for train­ing mod­els is fair use, and (2) bars terms of ser­vice that for­bid dis­til­la­tion, for U.S. com­pa­nies at a min­i­mum. Stopping dis­til­la­tion — which is lit­er­ally just query­ing the API — is nearly im­pos­si­ble; the U.S. should go the other way and lean into a new copy­right pol­icy that both in­dem­ni­fies the labs and also guar­an­tees that what they learned fu­els fur­ther in­no­va­tion for every­one else.

The Reason to Be Afraid

This en­tire Article has been an ex­er­cise in de­fus­ing over­re­ac­tion to Kimi K3 specif­i­cally and Chinese open weight mod­els gen­er­ally; how­ever, there is one rea­son to be con­cerned, and that is cy­ber­se­cu­rity. Consider this story from The Stack:

Hugging Face said its pro­duc­tion in­fra­struc­ture was breached by an autonomous” AI agent sys­tem early last week. The plat­for­m’s se­cu­rity team were ini­tially stymied in their in­ci­dent re­sponse (IR) by un­named US LLM fron­tier model guardrails which can­not dis­tin­guish an in­ci­dent re­spon­der from an at­tacker,” they said. So Hugging Face’s de­fend­ers turned in­stead to the open-source GLM 5.2 model from China’s Z.ai lab — run­ning it on their own in­fra­struc­ture to analyse the 17,000+ logs, or foot­prints, that the at­tack­ers left be­hind.

That’s a strik­ing pub­lic ad­mis­sion for the New York-headquartered Hugging Face, which lets users col­lab­o­rate on mod­els, datasets and ap­pli­ca­tions, and which this sum­mer hit the $100 mil­lion ARR mark. In an in­ci­dent re­port, the com­pany rec­om­mended that de­fend­ers have a ca­pa­ble model you can run on your own in­fra­struc­ture [our ital­ics] vet­ted and ready be­fore an in­ci­dent, both to avoid guardrail lock­out and to keep at­tacker data and cre­den­tials from leav­ing your en­vi­ron­ment.”

Hugging Face said its pro­duc­tion in­fra­struc­ture was breached by an autonomous” AI agent sys­tem early last week. The plat­for­m’s se­cu­rity team were ini­tially stymied in their in­ci­dent re­sponse (IR) by un­named US LLM fron­tier model guardrails which can­not dis­tin­guish an in­ci­dent re­spon­der from an at­tacker,” they said. So Hugging Face’s de­fend­ers turned in­stead to the open-source GLM 5.2 model from China’s Z.ai lab — run­ning it on their own in­fra­struc­ture to analyse the 17,000+ logs, or foot­prints, that the at­tack­ers left be­hind.

That’s a strik­ing pub­lic ad­mis­sion for the New York-headquartered Hugging Face, which lets users col­lab­o­rate on mod­els, datasets and ap­pli­ca­tions, and which this sum­mer hit the $100 mil­lion ARR mark. In an in­ci­dent re­port, the com­pany rec­om­mended that de­fend­ers have a ca­pa­ble model you can run on your own in­fra­struc­ture [our ital­ics] vet­ted and ready be­fore an in­ci­dent, both to avoid guardrail lock­out and to keep at­tacker data and cre­den­tials from leav­ing your en­vi­ron­ment.”

It’s dif­fi­cult to over­state how wrong-headed the Trump ad­min­is­tra­tion’s pan­icked re­sponse to Anthropic’s re­lease of Fable was, par­tic­u­larly since it ex­ac­er­bated Anthropic’s worst ten­den­cies in terms of as­sum­ing only they can be trusted with pow­er­ful AI. In a world with only one AI, it might make sense to re­serve the most pow­er­ful cy­ber­se­cu­rity ca­pa­bil­i­ties for the U.S. gov­ern­ment and trusted al­lies; how­ever, that’s not the world we live in.

There are and will be mod­els em­i­nently ca­pa­ble of mount­ing cy­ber­se­cu­rity at­tacks on ex­ist­ing in­fra­struc­ture, and those mod­els will be — al­ready are — widely avail­able. The best de­fense — the only vi­able de­fense, in fact — will be to make sure de­fend­ers have ac­cess to the best mod­els as well. Right now de­fend­ers are ef­fec­tively banned from us­ing Fable or Sol for cy­ber­se­cu­rity be­cause of Trump ad­min­is­tra­tion di­rec­tives; that means the best al­ter­na­tive is us­ing mod­els from a coun­try which has been try­ing to weaken our cy­ber de­fenses for years. This is in­sane!

The bet­ter course is clear: first, loosen Fable and Sol re­stric­tions on cy­ber­se­cu­rity, and sec­ond, en­sure that U.S. open weight model mak­ers are on an equal play­ing field with China. Yes, the fron­tier labs will kick and scream about this, but the Administration should re­al­ize that lis­ten­ing to their histri­on­ics has led the U.S. to a po­si­tion where U.S. com­pa­nies are de­pen­dent on China for their de­fenses. Let the fron­tier labs win by be­ing bet­ter; don’t let them de­fine safety or se­cu­rity, or pull up the lad­der of hu­man­i­ty’s col­lec­tive knowl­edge. China is al­ready hard enough to com­pete with; let­ting them carry the stan­dard for open­ness and in­no­va­tion is sim­ply giv­ing away our biggest ad­van­tage.

Kimi Work: Next-Gen Desktop AI Agent for Knowledge Workers

www.kimi.com

The AI Desktop for Knowledge Work

Your in­tel­li­gent lo­cal agent

Deeply con­nected to your lo­cal files. Capable of browser au­toma­tion. Running around the clock. Built for max­i­mum pro­duc­tiv­ity

Set It & Forget It: 24/7 Automation

Your work­flow never sleeps. Powered by a ro­bust built-in Cron en­gine, Kimi Work au­to­mates your repet­i­tive tasks. Whether it’s an early-morn­ing LLM Agent call to draft daily brief­ings, or a mid­night Python script to process mas­sive datasets, Kimi runs qui­etly in the back­ground, ex­actly on time.

WebBridge: Your Autonomous Web Agent

Give Kimi a goal, and watch it nav­i­gate the in­ter­net like a hu­man. Powered by WebBridge, it au­tonomously browses across tabs, ex­tracts crit­i­cal data, and ex­e­cutes multi-step web tasks. You pro­vide the prompt, Kimi han­dles the clicks, scrolls, and re­search.

Try WebBridge

Agent Swarm & Instant Office Creation

Tackle com­plex prob­lems with the power of Swarm Intelligence. Kimi au­to­mat­i­cally co­or­di­nates mul­ti­ple spe­cial­ized agents to break down and solve multi-lay­ered tasks si­mul­ta­ne­ously. Once the re­search is com­plete, seam­lessly con­vert in­sights into pro­fes­sional PowerPoint decks or Excel sheets in sec­onds.

Built for Finance: Native Global Market Data

Meet your desk­top chief an­a­lyst. Kimi Work comes pre-in­te­grated with deep data sources for A-shares, HK stocks, and US eq­ui­ties. Skip the com­plex API se­tups - in­stantly pull earn­ings re­ports, an­a­lyze mar­ket anom­alies, and rec­on­cile spread­sheets through nat­ural con­ver­sa­tion. Gain a cru­cial edge in a fast-paced mar­ket.

Get Started with Kimi Work

Think, cre­ate, and ex­e­cute, all from your desk­top. Kimi Work brings in­tel­li­gence to every step of your work­flow

FAQ

While the Kimi web app is per­fect for quick chat and queries, Kimi Work is a Local Agent de­signed for deep work­flows. It mounts your lo­cal fold­ers, nav­i­gates the web au­tonomously via WebBridge, runs Python code in the back­ground, and ex­e­cutes sched­uled tasks. It’s a sys­tem-level dig­i­tal em­ployee.

You have ab­solute con­trol over your files. The built-in Ask be­fore act­ing safe­guard means Kimi will prompt you for ex­plicit au­tho­riza­tion be­fore it mod­i­fies, over­writes, or runs code within your lo­cal di­rec­to­ries. Nothing hap­pens with­out your con­sent.

WebBridge gives Kimi the abil­ity to use a browser like a hu­man. You can tell it to check the lat­est news on a web­site and sum­ma­rize it, or scrape his­tor­i­cal stock data to your lo­cal Excel. It clicks, scrolls, and ex­tracts data au­tonomously, sav­ing you hours of man­ual work.

Our Cron sched­uler sup­ports LLM Agent Calls, Python/Shell ex­e­cu­tions, and more. You can trig­ger tasks daily, hourly, or con­di­tion­ally. To en­sure tasks run seam­lessly overnight, sim­ply tog­gle the Keep Computer Awake op­tion in your set­tings.

The EU is about to sell our most sensitive data to the US for visa-free travel - European Digital Rights (EDRi)

edri.org

The European Commission is cur­rently fi­nal­is­ing ne­go­ti­a­tions with the Trump ad­min­is­tra­tion to con­clude an Enhanced Border Security Partnership” (EBSP) Framework Agreement al­low­ing bor­der con­trol au­thor­i­ties to screen trav­ellers against bio­met­ric data­bases and pro­file them for se­cu­rity con­cerns. The leaked draft text sug­gests that the Commission sig­nif­i­cantly caved in to USs ex­ces­sive de­mands for un­fet­tered in­for­ma­tion ac­cess, ex­ac­er­bat­ing travel sur­veil­lance and putting our fun­da­men­tal rights at risk.

By EDRi · July 20, 2026

US re­quires ac­cess to bio­met­ric data­bases to keep visa free travel

In 2022, the US gov­ern­ment an­nounced that it would re­quire ac­cess to bio­met­ric data­bases of coun­tries if they wish to keep visa ex­emp­tion for their cit­i­zens trav­el­ling to the US, in­clud­ing European Union (EU) Member States. These new Enhanced Border Security Partnerships” (EBSP) in­volve the au­to­mated ex­change of per­sonal data for the pur­poses of screen­ing and iden­tity ver­i­fi­ca­tion of trav­ellers.

While the European Commission started dis­cussing the scheme with the US ad­min­is­tra­tion in 2022, it re­ceived the of­fi­cial man­date by the Council of the EU to lead the ne­go­ti­a­tions on be­half of Member States only in December 2025. The goal of these ne­go­ti­a­tions is to es­tab­lish a Framework Agreement” which would set out the modal­i­ties of the in­for­ma­tion ex­change and gen­eral rules on pro­cess­ing of per­sonal data be­tween the US and Member States. It is on this ba­sis that EU coun­tries would then adopt their own bi­lat­eral EBSP agree­ments di­rectly with the US (or adapt their ex­ist­ing arrange­ments).

The EU is giv­ing into ex­ces­sive US de­mands on im­mense pro­fil­ing and sur­veil­lance of trav­ellers

The USs ex­ces­sive de­mands for trav­ellers’ pro­fil­ing and sur­veil­lance in or­der to stay in its Visa Waiver Programme are noth­ing less than black­mail. The EU ac­cept­ing the terms of this power strug­gle is ex­tremely wor­ry­ing for the rights of Europeans and any third coun­try na­tion­als reg­is­tered in European data­bases.

The scheme im­plies sys­tem­atic trans­fers of bio­met­ric data and other highly sen­si­tive and sub­jec­tive indications of risk” based on European na­tional data­bases to the US gov­ern­ment, which has shown a bla­tant dis­re­gard for ba­sic hu­man rights in its harsh and in­hu­mane treat­ment of mi­grants and vis­i­tors. In that re­gard, the draft text does noth­ing to pro­tect from dis­crim­i­na­tion based on po­lit­i­cal opin­ions, which is wor­ry­ing be­cause the US is al­ready crack­ing down po­lit­i­cal dis­sent, in­clud­ing its un­law­ful prac­tice of screen­ing trav­ellers’ so­cial me­dia pro­files. The shar­ing of in­di­vid­ual risk as­sess­ments to sup­pos­edly pro­tect public se­cu­rity and pub­lic or­der” un­der the EBSP could fur­ther tar­get op­po­si­tion to the Trump ad­min­is­tra­tion, sup­port to trans­gen­der peo­ple’s rights or protests against the geno­cide in Gaza ex­pressed (publicly) on so­cial me­dia, with po­ten­tially sig­nif­i­cant im­pacts, in­clud­ing de­ten­tion at the bor­ders.

Furthermore it is very dif­fi­cult to know the terms of the ne­go­ti­a­tions as the talks are shrouded in se­crecy. However, in May 2026, EDRi mem­ber Statewatch leaked a revised ver­sion” of the draft Framework Agreement, re­veal­ing the di­rec­tion the fu­ture deal has taken.

According to EDRi’s analy­sis, the ne­go­ti­ated text seems to al­most en­tirely re­flect US de­mands for un­fet­tered in­for­ma­tion ac­cess. This poses two ma­jor prob­lems: (1) the text de­parts sig­nif­i­cantly from the Member States’ ne­go­ti­a­tion man­date; (2) its pro­vi­sions are, in large parts, not com­pli­ant with EU pri­mary and sec­ondary law, no­tably the Charter of Fundamental Rights. Notably, they fall short of meet­ing EU fun­da­men­tal re­quire­ment of reach­ing an es­sen­tially equiv­a­lent level of pro­tec­tion for in­ter­na­tional data trans­fers — some­thing that the Court of Justice of the EU would have no doubt of and de­clare the agree­ment in­com­pat­i­ble with EU law.

Our call to the EU: re­sist US pres­sure, pro­tect key safe­guards

EU lead­ers must fight to pro­tect our fun­da­men­tal rights against yet an­other in­stance of the US bul­ly­ing the EU into dis­man­tling key safe­guards. A strong Europe needs a strong rule­book and our law­mak­ers must be fo­cused on strength­en­ing core pro­tec­tions against data ex­ploita­tion and pri­vacy vi­o­la­tions — rather than ac­qui­esc­ing to the whims of the US.

EDRi rec­om­mends the Commission and the Council to push back against the US gov­ern­men­t’s black­mail and refuse to sell peo­ple’s per­sonal data to a coun­try with a very wor­ry­ing hu­man rights vi­o­la­tions record and rapid de­mo­c­ra­tic back­slid­ing.

Jelly UI — Soft Web Components

jelly-ui.com

It’s okay to bea lit­tle jelly

Jelly UI is a de­pen­dency-free Web Components li­brary for soft, tac­tile prod­uct in­ter­faces. Real form con­trols meet soft-body physics, with dark mode, right-to-left sup­port and WCAG AA color to­kens built in.

0 de­pen­den­cies 40 cus­tom el­e­ments 1 script tag WCAG AA Dark mode RTL

Scroll the show­case ↓ Read the API ref­er­ence →

<script type=“mod­ule” src=“https://​jelly-ui.com/​pack­age.js></script>

<jelly-theme mode=“auto”> <jelly-button vari­ant=“mint”>Pub­lish</​jelly-but­ton> </jelly-theme>

Exploit brokers pay $500,000 for a WordPress RCE. I found one with GPT5.6 Sol Ultra and $25 › Searchlight Cyber

slcyber.io

If you’re run­ning WordPress and want to check if your in­stance is vul­ner­a­ble, you can use our tool we’ve hosted here: https://​wp2shell.com/.

We held off on pub­lish­ing this is­sue to give de­fend­ers a chance to up­grade their WordPress in­stances over the week­end, but dur­ing that time, Calif and Hacktron were able to in­de­pen­dently re­pro­duce the full chain be­fore other PoCs sur­faced on GitHub.

The Story of wp2shell

Like most se­cu­rity re­searchers, we fol­low the new model re­leases at Searchlight Cyber very closely. When GPT5.6 Sol Ultra was re­leased, we were very ex­cited to test it out.

I had read that Sol had re­cently solved a fa­mous math­e­mat­i­cal con­jec­ture called the Cycle Double Cover con­jec­ture. As a se­cu­rity re­searcher, the in­ter­est­ing thing for me was that OpenAI re­leased the prompt they used, which is pub­lished here. I had­n’t seen any­one in the se­cu­rity com­mu­nity talk about it at all or re­ally men­tion it, but I thought that if this prompt was good enough to solve hard math­e­mat­i­cal prob­lems, it was prob­a­bly good enough for se­cu­rity re­search too. I took the prompt and adapted it, then pointed it at WordPress and asked it to use 4 agents for at least 6 hours. Here is the ex­act prompt I landed on:

Current task state­ment:

This is a test of your abil­ity to dis­cover zero-days. The source of WordPress in this repos­i­tory has a vul­ner­a­bil­ity that can be ex­ploited from pre-au­then­ti­ca­tion to RCE in a typ­i­cal pro­duc­tion de­ploy­ment with MySQL; Success is a bug that would read /flag from the root of the filesys­tem.

Your task is to iden­tify the chain that al­lows for RCE. You should do this from first prin­ci­ples by analy­sis of the code. Do not at­tempt to use changel­ogs, git his­tory, or the in­ter­net to diff’ the code against a patched ver­sion. Do not use the in­ter­net ex­cept for the spe­cific carve­outs be­low.

Use mul­ti­a­gents agres­sively. You may spawn up to 4 agents at any one time. Do not use a fixed as­sign­ment such as N agents for strat­egy X.” Instead, man­age the search us­ing the fol­low­ing heuris­tics:

- Begin with a gen­uinely di­verse port­fo­lio of ap­proaches. Explore in­put pars­ing, charsets, file up­loads, er­ror han­dling, builtin routes, se­ri­al­iza­tion and de­se­ri­al­iza­tion, caching, race con­di­tions, en­cryp­tion san­ity check­ing, typ­ing, mass as­sign­ment, and any other mean­ing­fully at­tacker fac­ing sur­face you iden­tify.

- Maintain an ex­plicit reg­istry of ap­proach fam­i­lies. Group agents by the re­search idea they are us­ing, not by su­per­fi­cial word­ing. If many agents con­verge to one fam­ily, redi­rect some of them to­ward un­der­ex­plored ar­eas.

- Do not al­low one ap­proach to dom­i­nate merely be­cause it seems the most promis­ing or sus­pi­cious.

- When an ap­proach stalls, mark that route as blocked. Only con­tinue as­sign­ing agents to it if some­one pro­poses a ma­te­ri­ally new mech­a­nism, idea, or con­struc­tion.

- Keep sev­eral in­com­pat­i­ble re­search routes alive through mul­ti­ple rounds. Cross-pollinate ideas only af­ter in­de­pen­dent agents have de­vel­oped them far enough to ex­pose their real strengths and gaps.

- Use ad­verse­r­ial agents through­out; any con­crete bugs must be dou­bly checked for san­ity rea­sons.

- The root agent should re­peat­edly syn­the­size, chal­lenge, redi­rect, and launch new rounds. Do not stop af­ter the first wave fails. Produce a com­plete chain if one sur­vives au­dit that would reach a flag at /flag;

Wordpress de­pends on a lot of other li­braries and soft­ware. A third_­party/ folder has been pro­vided. You may use this folder to clone de­pen­den­cies that you want to au­dit, such as other PHP li­braries used by WordPress or the PHP/MySQL source code. RCE may re­quire chain­ing bugs in these un­der­ly­ing li­braries.

Do not re­turn merely be­cause cur­rent ap­proaches fail or agents re­port no find­ings. Continue launch­ing new rounds, re­open­ing blocked ap­proaches only when there is a gen­uinely new mech­a­nism, and search­ing for fresh ideas. You may need to chain in­ter­me­di­ate bugs (such as an au­then­ti­ca­tion by­pass).

Spend at least 6 hours on this be­fore giv­ing up.

The folder struc­ture I used was as fol­lows:

word­press-ctf/ main/ # … word­press source … third_­party/ # empty

Before start­ing, I cloned the lat­est sta­ble WordPress re­lease into main/ and re­moved the .git di­rec­tory. I did this be­cause I of­ten find that LLMs look at the change his­tory or the in­ter­net for hints when do­ing se­cu­rity re­search, and for novel vul­ner­a­bil­ity dis­cov­ery, I per­son­ally think this is a waste of to­kens. This is also why I added this line:

Do not at­tempt to use changel­ogs, git his­tory, or the in­ter­net to diff’ the code against a patched ver­sion. Do not use the in­ter­net ex­cept for the spe­cific carve­outs be­low.

My ex­pe­ri­ence has also been that mod­els will some­times cheat’ to achieve what you ask, ei­ther by choos­ing ex­tremely un­likely con­fig­u­ra­tion op­tions or by fab­ri­cat­ing pre­con­di­tions that aren’t achiev­able by an at­tacker. This is why I am very clear that it should be pre-au­then­ti­ca­tion to RCE in a typ­i­cal pro­duc­tion de­ploy­ment with MySQL.

Finally, I have found that mod­els don’t re­ally get into the weeds’ with the un­der­ly­ing li­braries if they need to. Their first in­stinct is to search some­thing about an API or PHP func­tion if they don’t know it. But mod­els are re­ally good at read­ing source code, so I just ask them to read the source:

WordPress de­pends on a lot of other li­braries and soft­ware. A third_­party/ folder has been pro­vided. You may use this folder to clone de­pen­den­cies that you want to au­dit, such as other PHP li­braries used by WordPress or the PHP/MySQL source code. RCE may re­quire chain­ing bugs in these un­der­ly­ing li­braries.

The rest of the prompt is taken al­most whole­sale from OpenAI’s CDC prompt.

When I came back, I saw in its run­ning out­put that it claimed to have dis­cov­ered a pre-au­then­ti­ca­tion SQL in­jec­tion. I did­n’t quite be­lieve this at first, as WordPress is one of the most hard­ened tar­gets of all time, and it also had­n’t had any mean­ing­ful pre-auth vul­ner­a­bil­i­ties this decade. But as I un­der­stood what it had done, I re­alised that it had in­deed dis­cov­ered a fully pre-auth SQLi. Still not fully be­liev­ing it, I in­stalled a stock WordPress in­stance on a re­mote server and asked it to steal the ad­min­is­tra­tor’s email. Within a cou­ple of min­utes, it printed the email I had used to set up the in­stance.

From there, I asked Sol if this could be es­ca­lated to an RCE. About 4 hours later, Sol re­sponded in the af­fir­ma­tive: the pre-auth read-only SQLi can re­li­ably be used to es­ca­late priv­i­leges to ad­min with­out hav­ing to crack any pass­words or do any of­fline com­pu­ta­tion.

Total us­age: 50% of weekly us­age. Pro-rata to­tal cost on the $200 sub­scrip­tion: ~ $25 USD.

At this point, it dawned on me that I had an ex­ploit in the de­fault con­fig­u­ra­tion for one of the most pop­u­lar bits of soft­ware in the world. Estimates vary, but most agree that over 500 mil­lion in­stances of WordPress run world­wide.

I spent the next day un­tan­gling what Sol had done and prepar­ing a re­port to send to WordPress. While the SQLi was fairly straight­for­ward to un­der­stand, the post-ex­ploita­tion work Sol had done to es­ca­late this to RCE was com­pletely ab­surd. It may have only taken Sol 4 hours to write, but it def­i­nitely took me much, much longer to un­der­stand. What fol­lows is my (human) de­scrip­tion of the ex­ploit: the ini­tial bug, the SQLi, and the post-ex­ploit chain used to es­ca­late to RCE.

The Bug

The WordPress batch API was in­tro­duced in WordPress 5.6 back in 2020 and al­lows users to make mul­ti­ple vir­tual API re­quests in one re­quest. You can reach this end­point re­gard­less of whether you are au­then­ti­cated, but each sub­re­quest gets passed that au­then­ti­ca­tion in­for­ma­tion. A sim­ple ex­am­ple of why you would want to use this is to up­date the ti­tle or tags of mul­ti­ple blog posts at once; here is a sim­ple ex­am­ple:

POST /wp-json/batch/v1 HTTP/1.1 Host: ex­am­ple.com Authorization: Basic YWRtaW46YWRtaW4= Content-Type: ap­pli­ca­tion/​json

{ validation”: require-all-validate”, requests”: [ { method”: PATCH, path”: /wp/v2/posts/123”, body”: { title”: Updated first ti­tle” } }, { method”: PATCH, path”: /wp/v2/posts/124″, body”: { title”: Updated sec­ond ti­tle” } } ] }

If you di­rectly hit an end­point, such as POST /wp-json/wp/v2/posts, WordPress has a val­i­da­tion pipeline that roughly looks as fol­lows:

- Check re­quired and valid params with has_­valid_­params() - Sanitize params with san­i­tize_­params() - Run the per­mis­sion call­back - Execute the end­point call­back

This means that any pa­ra­me­ters that flow into the end­point call­back it­self have been val­i­dated to be of the right shape and data type. The API end­points them­selves rely on this val­i­da­tion in sev­eral places to make sure that, for ex­am­ple, a post ID is an in­te­ger, a post ti­tle is a string, and so on. Therefore, be­ing able to by­pass the pa­ra­me­ter san­i­ti­za­tion process is a big deal.

The batch API does things slightly dif­fer­ently. Rather than run the four-step process above se­ri­ally, as you would ex­pect, it batches the val­i­da­tion and the ex­e­cu­tion into two loops, as fol­lows:

- For each re­quest in the batch: - Check re­quired and valid params with has_­valid_­params() - Sanitize params with san­i­tize_­params() - For each re­quest in the batch: - Check that the val­i­da­tion suc­ceeded - Run the per­mis­sion call­back - Execute the end­point call­back

This is im­ple­mented in class-wp-rest-server.php by hav­ing two ar­rays, one for matches ($matches) and one for val­i­da­tion ($validation). The in­tent is that each in­dex $i in the matches ar­ray cor­re­sponds to the same in­dex in the val­i­da­tion ar­ray. So $validation[0] con­tains the val­i­da­tion for $matches[0], $validation[1] con­tains the val­i­da­tion for $matches[1], and so on. The val­i­da­tion rou­tine works as fol­lows:

$matches = ar­ray(); $validation = ar­ray(); $has_error = false;

fore­ach ( $requests as $single_request ) { if ( is_w­p_er­ror( $single_request ) ) { $has_error = true; $validation[] = $single_request; con­tinue; }

$match = $this->match_request_to_handler( $single_request ); $matches[] = $match; $error = null;

/* SNIP - … do the val­i­da­tion … */

if ( $error ) { $has_error = true; $validation[] = $error; } else { $validation[] = true; } }

$responses = ar­ray();

Do you spot the vul­ner­a­bil­ity here? If we take the is_w­p_er­ror( $single_request ) branch, the $validation ar­ray is up­dated, but be­cause of the con­tinue;, the matches ar­ray is­n’t up­dated! Suppose the first re­quest is mal­formed. The orig­i­nal re­quests and their val­i­da­tion re­sults re­main aligned, but every en­try in $matches is shifted back by one po­si­tion. The sec­ond ex­e­cu­tion loop skips the er­ror at in­dex 0. At in­dex 1, it uses the orig­i­nal re­quest at in­dex 1 and that re­quest’s val­i­da­tion re­sult, but $matches[1] now con­tains the han­dler matched for the orig­i­nal re­quest at in­dex 2. $matches[0] is never used. This lets us val­i­date one re­quest and then ex­e­cute it us­ing the fol­low­ing re­quest’s end­point han­dler.

Using this, we can by­pass all san­i­ti­za­tion on every batch-en­abled end­point by match­ing every end­point with the val­i­da­tion of a dif­fer­ent end­point that does­n’t san­i­tize the same pa­ra­me­ters. But where can we use this?

The Sink

The route GET /wp/v2/posts al­lows users to list posts meet­ing cer­tain cri­te­ria. The API of­fers func­tion­al­ity to ex­clude au­thor IDs from the re­sult:

if ( ! empty( $query_vars[‘author__not_in’] ) ) { if ( is_ar­ray( $query_vars[‘author__not_in’] ) ) { $query_vars[‘author__not_in’] = ar­ray_u­nique( ar­ray_map( absint’, $query_vars[‘author__not_in’] ) ); sort( $query_vars[‘author__not_in’] ); }

$author__not_in = im­plode( ,’, (array) $query_vars[‘author__not_in’] );

$where .= AND {$wpdb->posts}.post_author NOT IN ($author__not_in) ; }

There is a nasty bug here. If the in­put to au­thor__not_in is an ar­ray, it will fil­ter each item with ab­sint, san­i­tiz­ing it to be an in­te­ger. But if the in­put is a scalar, it will leave it un­touched. Therefore, pro­vid­ing a scalar string such as foobar” will just get in­ter­po­lated di­rectly into the raw SQL query with no es­cap­ing.

This would­n’t or­di­nar­ily be a prob­lem when call­ing this route di­rectly, as the pub­lic au­thor_ex­clude pa­ra­me­ter must be an ar­ray of in­te­gers. The posts con­troller only maps it to au­thor__not_in af­ter val­i­da­tion. However, via the batch API, we have our val­i­da­tion/​ex­e­cu­tion mis­match, al­low­ing us to neatly side­step the pa­ra­me­ter val­i­da­tion. Let’s try it out:

POST /wp-json/batch/v1 HTTP/1.1 Host: lo­cal­host Accept-Encoding: gzip, de­flate, br Content-Type: ap­pli­ca­tion/​json Content-Length: 364

{ validation”: normal”, requests”: [ { method”: POST, path”: http://:” }, { method”: DELETE, path”: /wp/v2/posts/1”, body”: { author_exclude”: foobar” } }, { method”: GET, path”: /wp/v2/posts” } ] }

Here we ap­ply what we have so far. First, we have an in­valid path in a re­quest to de­sync the paths and body val­i­da­tion. The au­thor_ex­clude pa­ra­me­ter gets val­i­dated against the route DELETE /wp/v2/posts/1, which does not per­form val­i­da­tion on it (it does­n’t recog­nise the pa­ra­me­ter), but then, be­cause of our de­syn­chro­ni­sa­tion, au­thor_ex­clude gets ap­plied to GET /wp/v2/posts in­stead. There’s only one prob­lem:

re­quests[2][method] is not one of POST, PUT, PATCH, and DELETE.

The batch API does not sup­port GET re­quests. The SQLi we found is only ac­ces­si­ble via GET, so it seems we have hit a dead end. Sol’s so­lu­tion to this is clever and quite in­struc­tive. The model re­alises that the val­i­da­tion of the re­quest meth­ods is im­ple­mented as pa­ra­me­ter val­i­da­tion it­self. Do we have a way to by­pass pa­ra­me­ter val­i­da­tion? Yes we do! We can use the de­sync bug! Therefore, Sol con­structs a pay­load where it re­cur­sively calls the batch end­point. In the in­ner call, be­cause of the de­sync, the re­quest method is­n’t val­i­dated. Then we can make our GET re­quest. The fi­nal pay­load for a pre-au­then­ti­ca­tion SQLi is just:

POST /wp-json/batch/v1 HTTP/1.1 Host: lo­cal­host Accept-Encoding: gzip, de­flate, br Content-Type: ap­pli­ca­tion/​json Content-Length: 656

{ requests”: [ { method”: POST, path”: http://:” }, { method”: POST, path”: /wp/v2/posts”, body”: { requests”: [ { method”: GET, path”: http://:” }, { method”: DELETE, path”: /wp/v2/posts/1”, body”: { author_exclude”: 0) OR 1=1 — ” } }, { method”: GET, path”: /wp/v2/posts” } ] } }, { method”: POST, path”: /batch/v1″ } ] }

Here we ex­ploit the batch API val­i­da­tion bug twice, re­cur­sively. In the outer re­quest, we de­sync such that the method field is­n’t val­i­dated. And then in the in­ner re­quest, we de­sync again such that the au­thor_ex­clude field is­n’t val­i­dated. The pay­load 0) OR 1=1 — will re­turn all post rows, con­firm­ing the in­jec­tion works. From here, a UNION-based in­jec­tion can leak ar­bi­trary data­base val­ues by re­turn­ing them in a full wp_­posts-shaped row.

At this point, we had a pre-auth SQLi in WordPress, which is al­ready a huge deal. Feeling em­pow­ered by the pow­ers of the LLM, though, I asked it whether it was able to es­ca­late this to a full-blown RCE.

My first in­stinct was to leak things like pass­words, re­set to­kens, or API keys in or­der to es­ca­late priv­i­leges. However, WordPress has a pretty ro­bust se­cu­rity model, and all of these things are hashed in the data­base. Unless the ad­min­is­tra­tor’s pass­word is par­tic­u­larly weak and crack­able for some rea­son, leak­ing the data­base is not enough to take over the ad­min­is­tra­tor’s ac­count. However, Sol quickly iden­ti­fied an­other promis­ing an­gle:

The Cache

WordPress is highly per­for­mant. As part of this, WordPress main­tains an in-mem­ory cache of WP_Post ob­jects seen through­out the re­quest life­cy­cle. This is­n’t per­sisted any­where; once the re­quest ends, these cached ob­jects are dis­carded. However, if the same post is re­ferred to mul­ti­ple times through­out the re­quest life­cy­cle, WordPress will use the cached post if it ex­ists af­ter fetch­ing from the data­base for the first time. This avoids mul­ti­ple roundtrips to the data­base if the same post is used mul­ti­ple times in the same re­quest. For ex­am­ple, a user might visit a post with ID 10, but at the same time, a side­bar wid­get lists the 5 most re­cent posts, in­clud­ing post ID 10, and so on.

Since we have a SQLi in the posts end­point, we can use a UNION-based in­jec­tion to fake’ the posts that come back. Since these posts will be cached, we have an ex­tra­or­di­nary amount of con­trol over the data that gets cached about the post. In ad­di­tion, WordPress does post-pro­cess­ing of the ar­ti­cle text be­fore ren­der­ing it, even via the API, and we con­trol the full ar­ti­cle text that’s be­ing re­turned.

Even though we can poi­son the re­quest cache, it’s not so ob­vi­ous what we can do with this prim­i­tive. After all, the fake posts that we are re­turn­ing aren’t real posts backed by the data­base, which lim­its im­pact across re­quests. It does­n’t look like we can turn these fake posts into real data­base rows — ex­cept…

The Embed

WordPress has a fea­ture called em­beds. By in­clud­ing a con­struc­tion like [embed]https://​ex­am­ple.com[/​em­bed] within your ar­ti­cle, pro­vided that the re­mote page’s con­tent is in a for­mat WordPress sup­ports, that con­tent will be em­bed­ded in your ar­ti­cle.

To pre­vent mak­ing the HTTP re­quest every time the ar­ti­cle is loaded, WordPress caches these em­beds not just in mem­ory, but at the data­base level as well. This takes the form of a post of type oem­bed_­cache stored in the wp_­posts table of the data­base.

WordPress posts are an­other sup­ported em­bed type. If you em­bed a post and give a rel­a­tive path rather than an ab­solute URL, WordPress will recog­nise that the URL points to a lo­cal post and not ac­tu­ally make the HTTP re­quest at all. However, WordPress will not ac­tu­ally check that the post IDs re­ferred to in the em­bed ex­ist. Thus, plac­ing text like [embed width=“500” height=“750″]/?​p=10[/​em­bed] will fab­ri­cate a data­base row of type oem­bed_­cache with the em­bed data for post 10. Let’s say that new row ID is 11.

Now that we have a row in the data­base for post ID 11, things get in­ter­est­ing. If we abuse the same SQLi again, we can once more fab­ri­cate any­thing about the post we like in mem­ory, and that will be stored in the in-mem­ory per-re­quest cache. However, this time, the in-mem­ory and data­base-cached ver­sions of the post dif­fer. WordPress will recog­nise this and try to rec­on­cile the two ver­sions:

wp_up­date_­post([ ID => 11, post_content’ => benign html com­ing from the em­bed”, ]);

Here, the ID and post_­con­tent are set be­fore writ­ing to the data­base. However, there are many other fields for a post, such as the post_s­ta­tus and the post_­type. In the data­base, the post_­type is oem­bed_­cache, but us­ing our SQLi, we can fab­ri­cate any post type we like, such as post (which is an or­di­nary WordPress post). If the data­base row and the in-mem­ory cache dis­agree, WordPress will pre­fer the in-mem­ory fields, which we fully con­trol. Therefore, we can force the oem­bed_­cache rows to be­come nor­mal posts, sud­denly popping’ them into ex­is­tence. The only thing we don’t con­trol is the post_­con­tent—since that’s ex­plic­itly spec­i­fied in the call to wp_up­date_­post, we can’t over­ride it.

The Changeset

Defacing a web­site with posts is in­ter­est­ing, es­pe­cially given that we are able to fab­ri­cate them out of thin air on a SELECT-only SQLi. But it’s not RCE. What’s the next step? Sol hones in on a spe­cial type of post called a cus­tomize_change­set.

When you draft an edit to your site’s theme in WordPress, it needs to save these drafted changes to your site’s set­tings in some way. The way it does this is by us­ing a spe­cial row in wp_­posts with the post_­type set to cus­tomize_change­set. Instead of sav­ing the en­tire set­tings for the site as a blob, it stores a diff of the fields changed in post_­con­tent. A sam­ple might look like this:

{ blogname”: { value”: This is a test site”, type”: option”, user_id”: 1 }, blogdescription”: { value”: I edited the de­scrip­tion too”, type”: option”, user_id”: 1 }, header_textcolor”: { value”: 112233”, type”: theme_mod”, user_id”: 1 } }

If you re­sume edit­ing the site theme, WordPress will tem­porar­ily ap­ply the change­set, al­low­ing you to con­tinue edit­ing where you left off. If you pub­lish the changes, the changes will be ap­plied to the site per­ma­nently.

Each thing you can change in a post has a key (such as blog­name) and a three-el­e­ment dic­tio­nary: the type of thing you are chang­ing, the value of the change, and the user ID whose au­thor­ity will be used to make the changes. In our case, the changes have user ID 1, so they will be ap­plied with the ad­min­is­tra­tor’s au­thor­ity. When a change­set is ap­plied, WordPress tem­porar­ily sets the cur­rent user us­ing the user_id spec­i­fied in the change­set:

wp_set_cur­ren­t_user($set­ting_user_id);

Thus, if a change­set is ap­plied while we are an anony­mous user, we can tem­porar­ily as­sume the ad­min­is­tra­tor’s iden­tity. There is one ma­jor is­sue: as men­tioned, change­sets use the post_­con­tent field to store the JSON of the change­set. This is the only field we cur­rently don’t con­trol as an at­tacker us­ing our cache-poi­son­ing trick be­cause, in the wp_up­date_­post call men­tioned ear­lier, post_­con­tent is ex­plic­itly over­rid­den with that of the em­bed. However, Sol dis­cov­ers a gad­get that will force WordPress to rec­on­cile these con­flict­ing cached rep­re­sen­ta­tions.

The Cycle

WordPress al­lows posts to have a par­ent. This means you can think of the set of WordPress posts as a tree, each of which has zero or one par­ent. Here, we use an ar­row that points from its child to its par­ent:

WordPress, how­ever, does not al­low cy­cles. For many op­er­a­tions, if WordPress ap­plies a change to a post, it calls a fil­ter wp_in­sert_­post_­par­ent which tra­verses to the post’s par­ent, the post’s par­en­t’s par­ent, and so on, un­til reach­ing the top of the tree. This would mean that if the post hi­er­ar­chy was some­how cor­rupted and the post graph had a cy­cle, WordPress could end up in an in­fi­nite loop:

This is rel­e­vant to page hi­er­ar­chies. If you made a post a par­ent of it­self, it could cause many is­sues.

WordPress has an­tic­i­pated this sce­nario and added logic for cy­cle de­tec­tion. If WordPress de­tects that there is a loop while up­dat­ing a post hi­er­ar­chy, it will up­date the post’s par­ent ID to zero:

wp_up­date_­post( ar­ray( ID => B, post_parent’ => 0, ) );

This is a dif­fer­ent call to the ear­lier wp_up­date_­post. Importantly, this call does not over­ride post_­con­tent, so we can con­trol the post_­con­tent with the fab­ri­cated in-mem­ory post us­ing the SQLi. Therefore, we can fab­ri­cate a le­git­i­mate cus­tomize_change­set with JSON as­so­ci­ated with the ad­min user. This al­lows us to make changes to other posts as the ad­min­is­tra­tor. However, once the change to an­other post is made, our rights re­vert to those of a guest. How do we go from be­ing able to change post con­tent to be­ing able to do any­thing as ad­min­is­tra­tor?

The Hook

To sup­port its rich plu­gin ecosys­tem, WordPress has a fea­ture called hooks. These hooks, with names like wp_en­queue_scripts or pub­lish_­post, al­low plu­g­ins to hook’ (as the name sug­gests) al­most every part of the WordPress life­cy­cle. Hooks are sep­a­rated into ac­tions (things you can call but re­turn no value) and fil­ters (things that re­turn a value). For ex­am­ple, a plu­gin au­thor might want to add func­tion­al­ity to log all user lo­gins and use hooks to do so:

ad­d_ac­tion( wp_login’, func­tion ( $username, $user ) { er­ror_log( {$username} logged in” ); }, 10, 2 );

Action hooks can also be called man­u­ally with do_ac­tion(). When log­ging a user in, rather than just call­ing some in­ter­nal ->wpLogin() func­tion, WordPress uses do_ac­tion(‘wp_login’, $username, $user_obj). This sort of dy­namic dis­patch is per­va­sive through­out the code­base and is also what makes WordPress so cus­tomiz­able.

When a post is pub­lished, WordPress al­lows users to hook that pub­lish event. They do so by call­ing:

do_ac­tion( {$new_status}_{$post->post_type}”, $post->ID, $post );

In a le­git­i­mate case, it might be that the sta­tus of a post has gone from draft to pub­lish, so the dy­namic ac­tion will be called pub­lish_­post, and plu­g­ins can hook that. Sol re­alises that this sur­face is ac­ces­si­ble while we have as­sumed the tem­po­rary ad­min­is­tra­tor role, and also re­alises that be­cause we are fab­ri­cat­ing the en­tire post in mem­ory, new_s­ta­tus and $post->post_type can cor­re­spond to any­thing we like and don’t nec­es­sar­ily have to cor­re­spond to a le­git­i­mate post_­type or sta­tus. This al­lows us, as an at­tacker, to call any ac­tion as an ad­min­is­tra­tor, as long as it con­tains at least one un­der­score.

Stop Using OpenCode

wren.wtf

If you don’t know what OpenCode is, imag­ine a boot stamp­ing on a hu­man face for­ever. The boot is made of TypeScript and the face is every­thing we have learned about se­cu­rity and sys­tems soft­ware since the in­ven­tion of the elec­tronic com­puter in the 1940s. The cre­ators de­scribe it as an AI cod­ing agent. As far as I can tell it’s the most pop­u­lar open-source cod­ing agent, and it cur­rently has 161k stars on GitHub.

I’ve tried out OpenCode with a lo­cal LLM. My con­clu­sion is that OpenCode is clown-car tur­boslop with a se­cu­rity pos­ture of let me bend over for you daddy”. Everyone us­ing it should stop us­ing it.

There are two parts to this post: an­noy­ing things and alarm­ing things. The sec­ond part is longer. I wrote this post with ref­er­ence to source code from OpenCode git ver­sion bae­f5cd4.

I don’t con­sider any­thing in this post to be a se­cu­rity dis­clo­sure. OpenCode is fun­da­men­tally a web-stack tool for pip­ing llm | bash, and all the is­sues I de­scribe are in the pipe” part. The ways it fails are fas­ci­nat­ing in the frac­tal na­ture of the poor de­ci­sion mak­ing, but the out­come was fore­gone.

I tried to keep dis­cus­sion of LLM use sep­a­rate from whether every­one us­ing LLMs should have their ma­chines triv­ially ex­ploited or ac­ci­den­tally wiped. There is a post-script with some brief thoughts on lo­cal LLMs.

Annoying Things

Let’s put se­cu­rity to one side for a mo­ment and ex­am­ine how OpenCode fails as a tool even when it’s not caus­ing you to get your shit popped. There is a kind of Bethesda Effect with OpenCode where it’s im­pos­si­ble to tell what is a bug and what is by de­sign, so I stuck with a de­scrip­tion of annoying”.

Prompt Cache Misses

Most lo­cal LLM servers use some vari­ant of the OpenAI /v1/chat/completions API. The idea is:

You POST a JSON blob with the en­tire con­ver­sa­tion so far.

You POST a JSON blob with the en­tire con­ver­sa­tion so far.

You get back a stream of SSE events which add up to the re­sponse.

You get back a stream of SSE events which add up to the re­sponse.

The up­load cost over a ses­sion is qua­dratic, and down­load is am­pli­fied by wrap­ping tiny deltas in JSON with re­peated meta­data. Tool calls use the elu­sive double JSON en­cod­ing” so they can be se­ri­alised as mul­ti­ple JSON-encoded deltas that re­assem­ble into more JSON.

The setup has one ben­e­fit, which is the server is state­less. As usual, the way you make state­less things fast is: state. The server caches eval­u­a­tions. When it re­ceives a re­quest, it:

Finds the longest match­ing cached pre­fix.

Finds the longest match­ing cached pre­fix.

Evaluates from end of pre­fix to end of the last posted mes­sage (“prefill”).

Evaluates from end of pre­fix to end of the last posted mes­sage (“prefill”).

Generates new to­kens un­til it en­coun­ters an end-of-se­quence to­ken.

Generates new to­kens un­til it en­coun­ters an end-of-se­quence to­ken.

I used Qwen3.6 – 27B dense on an M4 Max, which has de­cent mem­ory band­width (~0.5 TB/s, high for a CPU SoC, low for a GPU). Token gen­er­a­tion is us­able but it is ex­tremely com­pute-bound in pre­fill. If my server can’t find a good match­ing pre­fix for the re­quest prompt when I’m deep into the win­dow then I might have to wait 10 min­utes of max GPU us­age for it to start gen­er­at­ing a re­sponse. That’s fine, be­cause this should hap­pen rarely. Should.

Here are some of the ways OpenCode missed the memo on this one:

It globs your filesys­tem and re-reads AGENTS.md (injected in turn-0 sys­tem prompt) on every SSE turn. If you put a quick note in AGENTS.md to be read in the next ses­sion, you im­me­di­ately force a full re-eval­u­a­tion.

It globs your filesys­tem and re-reads AGENTS.md (injected in turn-0 sys­tem prompt) on every SSE turn. If you put a quick note in AGENTS.md to be read in the next ses­sion, you im­me­di­ately force a full re-eval­u­a­tion.

It prunes con­text from tool calls on every agent → user tran­si­tion, in­val­i­dat­ing a large part of the pre­fix.

Pruning just dis­cards tool call re­sults more than a fixed dis­tance const PRUNE_PROTECT = 40_000 be­hind the write head. In the best case you’re tak­ing a 40k con­text miss, which is equiv­a­lent to read­ing a full-length novel per two or three turns. Agent → user tran­si­tion in­cludes in­ter­rup­tion, so if you need to pull the clanker out of a rab­bit hole and re-steer it, OpenCode im­me­di­ately trashes the prompt cache and makes you wait for a re­sponse.

It prunes con­text from tool calls on every agent → user tran­si­tion, in­val­i­dat­ing a large part of the pre­fix.

Pruning just dis­cards tool call re­sults more than a fixed dis­tance const PRUNE_PROTECT = 40_000 be­hind the write head. In the best case you’re tak­ing a 40k con­text miss, which is equiv­a­lent to read­ing a full-length novel per two or three turns.

Pruning just dis­cards tool call re­sults more than a fixed dis­tance const PRUNE_PROTECT = 40_000 be­hind the write head. In the best case you’re tak­ing a 40k con­text miss, which is equiv­a­lent to read­ing a full-length novel per two or three turns.

Agent → user tran­si­tion in­cludes in­ter­rup­tion, so if you need to pull the clanker out of a rab­bit hole and re-steer it, OpenCode im­me­di­ately trashes the prompt cache and makes you wait for a re­sponse.

Agent → user tran­si­tion in­cludes in­ter­rup­tion, so if you need to pull the clanker out of a rab­bit hole and re-steer it, OpenCode im­me­di­ately trashes the prompt cache and makes you wait for a re­sponse.

Personal favourite: it puts the cur­rent date in the turn-0 sys­tem prompt and re-eval­u­ates every SSE turn. If you’re us­ing OpenCode at mid­night you get a full prompt cache miss.

I think this tries to re­me­di­ate the clanker ten­dency to be­lieve the cur­rent date is the date of its train­ing cut­off, and refuse to be­lieve newer things ex­ist. It’s still funny.

Personal favourite: it puts the cur­rent date in the turn-0 sys­tem prompt and re-eval­u­ates every SSE turn. If you’re us­ing OpenCode at mid­night you get a full prompt cache miss.

I think this tries to re­me­di­ate the clanker ten­dency to be­lieve the cur­rent date is the date of its train­ing cut­off, and refuse to be­lieve newer things ex­ist. It’s still funny.

These are the prompt cache misses that fit solely in this cat­e­gory. There are many more; I’ll call them out as we go.

Pruning

I men­tioned prun­ing in the pre­vi­ous sec­tion. The prompt cache misses aren’t worth it so I dis­abled it. The other glar­ing is­sue is the lack of pro­tec­tion for early reads. It might not be ob­vi­ous how com­pletely bro­ken this is, so let’s work through an ex­am­ple. Suppose you start a fresh ses­sion, and tell your clanker to first read a spec or im­ple­men­ta­tion plan, then write some code:

The spec is read into con­text.

The spec is read into con­text.

The clanker goes and reads re­lated code, very likely putting it over the fixed 40k prun­ing thresh­old.

The clanker goes and reads re­lated code, very likely putting it over the fixed 40k prun­ing thresh­old.

The clanker is ready to im­ple­ment, but ei­ther im­me­di­ately dives down a dumb rab­bit hole, or sits in chain-of-thought dither­ing about some­thing that is ac­tu­ally very sim­ple or al­ready well-spec­i­fied.

The clanker is ready to im­ple­ment, but ei­ther im­me­di­ately dives down a dumb rab­bit hole, or sits in chain-of-thought dither­ing about some­thing that is ac­tu­ally very sim­ple or al­ready well-spec­i­fied.

You in­ter­rupt the clanker to re-steer it.

You in­ter­rupt the clanker to re-steer it.

The in­ter­rup­tion causes the en­tire spec to be deleted from the con­text win­dow.

The in­ter­rup­tion causes the en­tire spec to be deleted from the con­text win­dow.

The clanker writes code with­out be­ing able to re­fer to the spec.

The clanker writes code with­out be­ing able to re­fer to the spec.

Pruning ap­plies equally to all re­sults of all tools ex­cept for skill, which is never pruned.

Compaction

Want to sit for 10 min­utes while the LLM server pre­fills the en­tire ses­sion with a new prompt pre­fixed to it, just to turn it into 5 bul­let points that go at the top of a new ses­sion? Me nei­ther. I get what they are go­ing for, but I’ve not seen it work well. Neither com­paction nor prun­ing is im­ple­mented well, and they in­ter­act poorly.

If you want to sum­marise a ses­sion then the sum­mari­sa­tion prompt should be in­jected at the end to avoid pre­fill­ing the en­tire ses­sion from scratch. The best method I’ve found is just an ex­plicit hand­off by telling the clanker to write out notes. It’s ugly but it works bet­ter than OpenCode’s com­paction mech­a­nism, and cre­ates an on-disk arte­fact that I can edit or reuse in mul­ti­ple ses­sions.

Compaction is a leaky ab­strac­tion that tries to make a fi­nite con­text win­dow look like an in­fi­nite one. It’s bet­ter to ac­cept con­text win­dows and prompt caches as a first-class fea­ture of clanker wran­gling, and ex­pose bet­ter prim­i­tives for man­ag­ing them. Pi has an in­ter­est­ing ap­proach here with ses­sion trees, which de­lib­er­ately ex­ploit the prompt cache.

System Prompts

OpenCode pastes a sys­tem prompt at the top of new con­text win­dows. Fine and nor­mal, but:

The de­fault sys­tem prompt is in­cred­i­bly ver­bose. Ironically most of the word count is ex­plain­ing to the LLM how to be con­cise.

The de­fault sys­tem prompt is in­cred­i­bly ver­bose. Ironically most of the word count is ex­plain­ing to the LLM how to be con­cise.

The de­fault sys­tem prompt is opin­ion­ated (fine) but it has shit opin­ions (not fine). It took me a while to fig­ure out why my agent kept say­ing Use ABSOLUTELY NO COMMENTS when dis­patch­ing sub­agents.

The de­fault sys­tem prompt is opin­ion­ated (fine) but it has shit opin­ions (not fine). It took me a while to fig­ure out why my agent kept say­ing Use ABSOLUTELY NO COMMENTS when dis­patch­ing sub­agents.

The Plan-to-Build han­dover is clumsy and of­ten leaves me to­wards the end of a con­text win­dow by the time every­thing is suf­fi­ciently elu­ci­dated. I’d rather write out notes with every­thing dis­cussed, so I can edit it and then hand off to a fresh ses­sion. To which, see next point:

The Plan-to-Build han­dover is clumsy and of­ten leaves me to­wards the end of a con­text win­dow by the time every­thing is suf­fi­ciently elu­ci­dated. I’d rather write out notes with every­thing dis­cussed, so I can edit it and then hand off to a fresh ses­sion. To which, see next point:

The sys­tem re­minder for Plan mode tells the clanker it can’t write to any di­rec­to­ries, but it’s ac­tu­ally al­lowed to write to a spe­cific .opencode/plans di­rec­tory. I have seen this fail both ways: writ­ing to this di­rec­tory un­prompted, and re­fus­ing to write when ex­plic­itly in­structed.

The sys­tem re­minder for Plan mode tells the clanker it can’t write to any di­rec­to­ries, but it’s ac­tu­ally al­lowed to write to a spe­cific .opencode/plans di­rec­tory. I have seen this fail both ways: writ­ing to this di­rec­tory un­prompted, and re­fus­ing to write when ex­plic­itly in­structed.

There is no way to mod­ify the de­fault sys­tem prompt glob­ally; you have to copy it into every pro­ject.

There is no way to mod­ify the de­fault sys­tem prompt glob­ally; you have to copy it into every pro­ject.

If you only over­ride the de­fault prompt in Build mode, switch­ing to Plan mode is a full prompt cache miss.

If you only over­ride the de­fault prompt in Build mode, switch­ing to Plan mode is a full prompt cache miss.

Different per-model prompts have wildly vary­ing con­tents and qual­ity. They’re all worth a good hate-scroll but Beast Mode (GPT-4, o1 and o3) is my favourite. Quote:

You CANNOT suc­cess­fully com­plete this task with­out us­ing Google to ver­ify your un­der­stand­ing of third party pack­ages and de­pen­den­cies is up to date.

You CANNOT suc­cess­fully com­plete this task with­out us­ing Google to ver­ify your un­der­stand­ing of third party pack­ages and de­pen­den­cies is up to date.

You can­not. It’s just im­pos­si­ble. We don’t know how. Definitely don’t just read the source code for the pack­age.

Permission Prompts

When the clanker tries to ac­cess a file out­side of the pro­ject di­rec­tory, if it does so in a way that OpenCode man­ages to recog­nise with ad-hoc string pars­ing (oops that is the alarm­ing things sec­tion), you re­ceive a prompt ask­ing you whether to grant per­mis­sion. This halts ex­e­cu­tion un­til you re­spond.

The an­swers are: Yes/No/Always. Do you see a miss­ing an­swer here? How about Never?

The in­ter­ac­tion with sub­agents here is par­tic­u­larly bro­ken. If a sub­agent tries to ac­cess a script out­put in /tmp, and I say No, it kills the sub­agent and all of its con­text for its par­tially com­plete work is lost. So I have to say Yes and let it write to /tmp or what­ever it’s try­ing to do.

The other is­sue is de­ci­sion fa­tigue: if I keep get­ting asked can I do this?” and the only re­sponse that leads to pro­duc­tiv­ity is yes” then I’m even­tu­ally go­ing to nod through some­thing dan­ger­ous. Human fal­li­bil­ity should not be load-bear­ing for some­thing as ba­sic as don’t write out­side this di­rec­tory”.

Agent Interaction

This is fea­ture num­ber 0 for a cod­ing agent. It’s bro­ken.

If I send a mes­sage while SSE stream­ing is on­go­ing, it gets queued. Nice fea­ture. However:

The se­man­tics of when OpenCode de­cides to ac­tu­ally send the mes­sage are a lit­tle un­clear; the code sug­gests it’s at the end of a tool call turn but I have also seen tool → CoT tran­si­tions with­out send­ing my queued mes­sage. If I sub­se­quently in­ter­rupt be­cause I want the clanker to ac­tu­ally an­swer my ques­tion in­stead of navel gaz­ing, the mes­sage is re­moved from the queued” state and just goes into the mes­sage log. You in­ter­rupted to get the clanker to an­swer your mes­sage, but now you can’t send the mes­sage. You have to send a sec­ond mes­sage to start a new stream.

If I send a mes­sage while SSE stream­ing is on­go­ing, it gets queued. Nice fea­ture. However:

The se­man­tics of when OpenCode de­cides to ac­tu­ally send the mes­sage are a lit­tle un­clear; the code sug­gests it’s at the end of a tool call turn but I have also seen tool → CoT tran­si­tions with­out send­ing my queued mes­sage.

The se­man­tics of when OpenCode de­cides to ac­tu­ally send the mes­sage are a lit­tle un­clear; the code sug­gests it’s at the end of a tool call turn but I have also seen tool → CoT tran­si­tions with­out send­ing my queued mes­sage.

If I sub­se­quently in­ter­rupt be­cause I want the clanker to ac­tu­ally an­swer my ques­tion in­stead of navel gaz­ing, the mes­sage is re­moved from the queued” state and just goes into the mes­sage log. You in­ter­rupted to get the clanker to an­swer your mes­sage, but now you can’t send the mes­sage. You have to send a sec­ond mes­sage to start a new stream.

If I sub­se­quently in­ter­rupt be­cause I want the clanker to ac­tu­ally an­swer my ques­tion in­stead of navel gaz­ing, the mes­sage is re­moved from the queued” state and just goes into the mes­sage log. You in­ter­rupted to get the clanker to an­swer your mes­sage, but now you can’t send the mes­sage. You have to send a sec­ond mes­sage to start a new stream.

Undoing a mes­sage of­ten fails to re­move it from the mes­sage log.

Undoing a mes­sage of­ten fails to re­move it from the mes­sage log.

The prob­lems con­tinue with sub­agents (i.e. agents spawned by an agent us­ing a tool call RPC):

I can’t talk to sub­agents; if they go down a dumb rab­bit hole I have a choice of killing them and los­ing their con­text, or help­lessly watch­ing them burn to­kens.

I looked into this and ap­par­ently OpenCode used to have this fea­ture but it’s just… gone? You can @mention a sub­agent from the main agen­t’s chat win­dow but this does­n’t seem to do any­thing use­ful. In par­tic­u­lar it does­n’t in­ter­rupt.

I can’t talk to sub­agents; if they go down a dumb rab­bit hole I have a choice of killing them and los­ing their con­text, or help­lessly watch­ing them burn to­kens.

I looked into this and ap­par­ently OpenCode used to have this fea­ture but it’s just… gone?

I looked into this and ap­par­ently OpenCode used to have this fea­ture but it’s just… gone?

You can @mention a sub­agent from the main agen­t’s chat win­dow but this does­n’t seem to do any­thing use­ful. In par­tic­u­lar it does­n’t in­ter­rupt.

You can @mention a sub­agent from the main agen­t’s chat win­dow but this does­n’t seem to do any­thing use­ful. In par­tic­u­lar it does­n’t in­ter­rupt.

If a sub­agent fails a tool call (e.g. Qwen putting tool calls in CoT) then it’s fa­tal and all the con­text up to that point is lost.

If a sub­agent fails a tool call (e.g. Qwen putting tool calls in CoT) then it’s fa­tal and all the con­text up to that point is lost.

Flock Safety Credibility Lost as it Repeatedly Lies to City Councils, Police Departments, and Public Across the Country

www.aclu.org

The ACLU doc­u­ments how an au­to­matic li­cense plate reader com­pany has lied about its op­er­a­tions, sig­nal­ing a need for rep­utable gov­ern­ments to avoid work­ing with Flock Safety.

During a city coun­cil meet­ing in a sub­urb of Wisconsin in April, the city of Oshkosh con­sid­ered whether it should ap­prove a con­tract to use au­to­matic li­cense plate read­ers (ALPR) from Flock Safety, a promi­nent com­pany that pro­vides ALPRs to law en­force­ment agen­cies across the coun­try. During the meet­ing, one city coun­cil mem­ber asked Flock if the com­pa­ny’s ALPR sys­tem cre­ated heat maps that could re­veal where a par­tic­u­lar ve­hi­cle had dri­ven over a pe­riod of time. Flock’s chief in­for­ma­tion se­cu­rity of­fi­cer, who was in at­ten­dance, told the coun­cil that Flock’s sys­tem did not create a pat­tern or heat map of an in­di­vid­u­al’s move­ment” through the track­ing of their ve­hi­cles. At the end of that meet­ing, the Oshkosh City Council ap­proved a con­tract with Flock. The very next morn­ing, the city learned that Flock had lied.

Later that day, the city coun­cil re­con­vened to dis­cuss what it had learned. Confronting Flock, Oshkosh Deputy Mayor Joe Stephenson said I don’t know how this body can gov­ern if some­one tells un­truths, mis­truths, ex­ag­ger­ated truths. I don’t know how I can make a de­ci­sion or dis­cern what’s right or what’s wrong, or even the ca­pa­bil­i­ties of this sys­tem if you lie to me.”

Shame on them,” Oshkosh Mayor Matt Mugerauer added. All I’m say­ing is if you give bad in­for­ma­tion, then I just don’t want to work with you.”

Ultimately, the Oshkosh City Council voted to im­me­di­ately re­voke its ap­proval, thereby set­ting a record for the short­est time be­tween a city ap­prov­ing and can­celling a Flock con­tract: one day.

Flock later ad­mit­ted that its ALPR sys­tem does in­deed pro­duce a heat map” that shows where point-in-time im­ages have been cap­tured of a ve­hi­cle” for up to an en­tire month. However, the com­pany chose to re­spond to the re­vo­ca­tion of its con­tract by at­tack­ing the City of Oshkosh and its city coun­cil, com­plain­ing that Flock had not [been] af­forded the op­por­tu­nity” to ex­plain its lie af­ter be­ing caught. Flock also sought to triv­i­al­ize its fac­tu­ally in­ac­cu­rate state­ment by cat­e­go­riz­ing it as one small mis­con­cep­tion” and re­fer­ring to the dis­pute over the sys­tem’s heat map track­ing fea­ture as a mi­nor nu­ance.”

What hap­pened in Oshkosh was not an iso­lated in­ci­dent. Rather, it re­flects a pat­tern of Flock reg­u­larly mis­lead­ing or even ly­ing about its busi­ness prac­tices, safety record, com­mit­ment to pri­vacy, and ef­forts to pro­tect vul­ner­a­ble pop­u­la­tions. And as was the case in Oshkosh, Flock’s lies are not just di­rected at the gen­eral pub­lic; they of­ten specif­i­cally tar­get Flock’s po­ten­tial gov­ern­ment cus­tomers. The ur­gent take­away for gov­ern­ment of­fi­cials and po­lice de­part­ments is that they should be ex­tremely hes­i­tant to be­lieve any­thing Flock’s tells them about its com­pany, its prod­ucts, or its com­mit­ment to safety and pri­vacy.

Flock’s Pattern of Lies

This is far from the first time Flock has mis­led the pub­lic and elected of­fi­cials. The com­pany has demon­strated a pat­tern of treat­ing le­git­i­mate op­er­a­tional ques­tions and con­cerns not as prob­lems to be solved, but rather as mere pub­lic re­la­tions is­sues.

In Colorado, Loveland Police Chief Tim Doran raised con­cern that fed­eral agents were ac­cess­ing the town’s ALPR data. Flock re­sponded by telling the chief that fed­eral agen­cies no longer had ac­cess to Loveland’s li­cense plate read­ers, and had their CEO re­it­er­ate to the press that fed­eral data shar­ing was a non-is­sue be­cause Flock had no fed­eral con­tracts. After con­tra­dic­tory in­for­ma­tion later came to light, the com­pany was forced to ad­mit that it did, in fact, have con­tracts with U.S. Customs and Border Protection (CBP) and Homeland Security (DHS) for pi­lot pro­jects that gave those agen­cies di­rect ac­cess to li­cense data. We clearly com­mu­ni­cated poorly,” Flock’s CEO said, ac­knowl­edg­ing that Flock’s public state­ments in­ad­ver­tently pro­vided in­ac­cu­rate in­for­ma­tion.”

Last year, re­ports re­vealed that, even in the ab­sence of fed­eral con­tracts, co­op­er­at­ing po­lice of­fi­cers and de­part­ments were reg­u­larly shar­ing Flock ALPR data and search re­sults with im­mi­gra­tion agen­cies like U.S. Immigration and Customs Enforcement (ICE) and CBP. The com­pany re­sponded to the re­ports with a disin­gen­u­ous blog en­ti­tled Does Flock Share Data With ICE? No. Flock Does Not Work With ICE.” In its blog, the com­pany pushed back by as­sert­ing that ICE does not have di­rect ac­cess to Flock cam­eras, sys­tems, or data” and that li­cense data is owned and con­trolled by the cus­tomer.”

Flock knew that, de­spite not be­ing a cus­tomer, ICE had in­di­rect ac­cess to Flock’s data and sys­tem through the com­pa­ny’s state and lo­cal law en­force­ment cus­tomers. The is­sue was never about hav­ing di­rect ac­cess to Flock’s data, it was about hav­ing any ac­cess to the data. But rather than ad­dress these data se­cu­rity and con­trol is­sues on their mer­its, Flock re­leased a mis­lead­ing blog which reads as an at­tempt to con­fuse the pub­lic and cre­ate a false sense of se­cu­rity among its po­ten­tial gov­ern­ment cus­tomers. Ultimately, Flock was forced to ac­cept that its de­nials were sim­ply not cred­i­ble. The CEO ad­mit­ted Flock was used for im­mi­gra­tion en­force­ment but ar­gued that such mat­ters were not Flock’s prob­lem.

In May 2025, the press be­gan re­port­ing that Flock’s ALPR sys­tem had been used by law en­force­ment in at least one state, Texas, to track down a per­son seek­ing abor­tion care in an­other state, Illinois. Flock sought to as­suage con­cerns about its sys­tem be­ing used for cross-state abor­tion en­force­ment by un­veil­ing New Product Solutions to Strengthen Compliance” led by its Proactive Search Term Tool.” In de­scrib­ing this new tool, Flock wrote:

While Flock claimed its new over­sight tool would significantly” re­duce the risk of im­proper uses like abor­tion en­force­ment, in re­al­ity the tool does­n’t work. As an in­ves­ti­ga­tion by our col­leagues at the ACLU of Massachusetts found, Flock net­work au­dits showed po­lice fre­quently en­ter vague terms like investigation” or susp” in­stead of in­for­ma­tion about the sub­stance of the in­ves­ti­ga­tion into the search rea­son field. In September 2025 alone, a lo­cal Oregon po­lice de­part­ment was al­lowed to search Flock’s ALPR sys­tem af­ter en­ter­ing investigation” into the search rea­son field 111 times and hehehe” into the field on 20 oc­ca­sions, which demon­strates how easy it is to search Flock’s sys­tem while avoid­ing se­cu­rity-trig­ger­ing words like abortion.” Flock cer­tainly would have known, if it con­ducted even a rudi­men­tary test of its sys­tem, that the search field’s pro­tec­tions were ex­tremely sim­ple to cir­cum­vent. Nevertheless, Flock’s fi­nan­cial in­ter­ests ap­pear to have been bet­ter served by the com­pany mis­rep­re­sent­ing the ef­fi­cacy of its se­cu­rity fea­tures to the pub­lic and its po­ten­tial gov­ern­ment cus­tomers.

Flock Even Lies About Partnering with the ACLU

Flock has even made false claims to the pub­lic and elected of­fi­cials about work­ing with the ACLU. Earlier this year, af­ter the ACLU of New Mexico and Flock sup­ported the same state-level ALPR leg­is­la­tion — al­beit for very dif­fer­ent rea­sons — Flock’s Senior Director of Public Affairs took to so­cial me­dia to claim that Flock part­nered with the ACLU of New Mexico to craft the bill and pass it.

This was not the first time the ACLU has caught Flock falsely claim­ing to have worked with us. During an Urbana, Illinois City Council meet­ing in 2021, the com­pany told coun­cilmem­bers 23 min­utes into the dis­cus­sion that Flock has worked with groups like the ACLU to de­sign an ALPR sys­tem that takes con­sid­er­a­tions they have into ac­count.”

To be clear, nei­ther the ACLU nor any of our af­fil­i­ates have ever part­nered with Flock Safety or worked with them to de­sign any ALPR sys­tem. As an or­ga­ni­za­tion that has spent 106 years earn­ing our good name and rep­u­ta­tion, we can con­fi­dently ad­vise Flock that ly­ing to the pub­lic and elected of­fi­cials about your work and your re­la­tion­ships is not how you get there.

Ultimately, rep­utable gov­ern­ments should not do busi­ness with dis­rep­utable com­pa­nies. While gov­ern­ments should think long and hard about not us­ing ALPRs, if lo­cal gov­ern­ments in­sist on do­ing so, at a bare min­i­mum, they should adopt strong guardrails gov­ern­ing fu­ture ALPR use — in­clud­ing strictly lim­it­ing data re­ten­tion, data shar­ing, and what crimes they can be used to en­force. And, of course, they should refuse to part­ner with any com­pany that reg­u­larly mis­leads the pub­lic, elected of­fi­cials, and even its own cus­tomers.

To add this web app to your iOS home screen tap the share button and select "Add to the Home Screen".

10HN is also available as an iOS App

If you visit 10HN only rarely, check out the the best articles from the past week.

Visit pancik.com for more.