AI Skeptics: The Biden/Trump/Bolsonaro AI Policy Episode (with Clara Langevin)
Math Babe
mathbabe.org
2026-10-19 10:28:26
We were fascinated to hear from AI Policy expert Clara Langevin from the Federation of American Scientists, who talked to us about federal AI policy in the US and Brazil: Apple Spotify YouTube...
We were fascinated to hear from AI Policy expert
Clara Langevin
from the Federation of American Scientists, who talked to us about federal AI policy in the US and Brazil:
Steinar H. Gunderson: Decompilation patterns, part 16: Tail reduplication
PlanetDebian
blog.sesse.net
2026-10-19 16:00:28
We're nearing the end soon, I promise. Here's one that I see all the time:
...
} else {
var_t0_5 = temp_a0_3 - 0x140;
var_a2_5 = 0xA0 - temp_a3_5;
goto block_45;
}
} else {
var_t0_5 = 0xA0 - temp_a0_3;
var_a2_5 = t...
So, eh, what's that goto doing there? What happened was that the compiler
helpfully figured it could help with some tail deduplication; someone
wrote the same code twice, and the compiler figured taking the cost
of a branch was better than keeping it duplicated. (In a sense, it's
the opposite of inlining. Ish.) In most cases, it's as simple as
copying the block and then you can remove the label:
Sometimes, these are nested, with multiple tails goto-ing into each other,
so in that case, you'll need to reduplicate multiple times.
Make sure you actually come out on the correct side afterwards,
though.
As an extra complication, the code is deduplicated not on the C statement level, but on
RTL instructions, so if you're calling functions with five parameters
of more (which requires pushing parameters onto the stack), m2c can
get really confused and start throwing
M2C_ERROR()
at you on the
receiving side because it's not clear at all where the parameters
would be coming from.
Playful, Princely, Likely Molting: There's a New Hot Duck in Town
hellgate
hellgatenyc.com
2026-10-19 15:45:10
New York City has been blessed with another mandarin duck, after becoming captivated by the dazzling bird in 2018....
Eight years after the famous mandarin duck—or "Hot Duck"—captured
the hearts
and
headlines
of New York City in 2018, a new member of the world's most dazzling duck family has waddled onto the scene.
Since early October, a new, brightly plumed male mandarin duck has been spotted hanging out on the pond at Bowne Park in Flushing, Queens. "He's one of the most colorful, vibrant ducks I've ever seen, and just so cute," gushed
Sarah Gonzalez
, a Queens
birder
who blew off her chores on Sunday to see the duck.
Hackers hijack AOMEI update servers to secretly spread malware
Bleeping Computer
www.bleepingcomputer.com
2026-10-19 15:40:58
Hackers reportedly compromised AOMEI's servers to distribute malware through a built-in promotional feature in its backup software, briefly tampering with configuration files before restoring them to their original state to hide the attacks.a [...]...
Hackers reportedly compromised AOMEI's servers to distribute malware through a built-in promotional feature in its backup software, briefly tampering with configuration files before restoring them to their original state to hide the attacks.
The supply chain attacks took place between April and July 2026 and targeted the update and notification systems used by AOMEI Backupper, a Windows application for backing up data, cloning disks, and restoring systems.
Researchers at ManageEngine's Threat Analysis Lab (METAL), working with Google's Threat Intelligence Group (GTIG) and Mandiant, uncovered the campaign and investigated the attacks.
In reports published by
Google
and
ManageEngine
, the activity is attributed to a threat actor tracked as UNC7017, who used the compromised infrastructure to distribute a previously unknown malware downloader called CROSSROAD and a backdoor named SHINYROAD.
The researchers identified affected organizations in multiple countries, including the United States, Australia, India, Singapore, Spain, and Switzerland, across sectors such as IT services, telecommunications, and higher education.
However, Google warned that the attacks were opportunistic and could have affected additional organizations that checked for software updates during the brief periods when malicious files were being distributed.
Software
The attacks were first detected on May 28, when ManageEngine said its endpoint security software spotted AOMEI Backupper suddenly installing the legitimate remote administration tool Radmin on computers at two unrelated companies in different countries.
The Radmin installation was suspicious because AOMEI's built-in promotion processes launched it, which normally handle downloading and displaying promotional content and notifications.
However, when researchers attempted to reproduce the behavior on their own test systems, they found nothing malicious. Instead, the software contacted AOMEI's servers and downloaded the legitimate configuration file.
Further testing showed that instead of permanently replacing files on AOMEI's servers, the attackers briefly modified two configuration files used by the promotion and notification systems:
The first file, down_html.ini, tells AOMEI Backupper where to download update packages. The second, Notifycfg.ini, controls notifications and can trigger content to run on the computer.
By modifying these files, the attackers redirected the software to download a malicious ZIP archive and then used the notification mechanism to execute the malware without requiring user interaction.
Researchers at Google later confirmed this execution flow in their own tests.
AOMEI supply chain attack execution flow
Source: Google
After failing to reproduce the original attack, ManageEngine began continuously monitoring AOMEI's servers.
On July 16, that monitoring finally captured the malicious modifications as they happened, confirming that AOMEI's systems were serving the malicious content.
The researchers also found that the attackers had modified the expected checksum in the update configuration, allowing the malicious archive to pass the software's file verification checks.
Google and ManageEngine say they identified three windows where the malicious configuration file was being sent by Aomei's servers:
May 28: 10-minute exposure window (05:40 – 05:50 UTC)
July 16: 6-minute exposure window (08:33 – 08:39 UTC)
July 20: 5-minute exposure window (10:35 – 10:40 UTC)
The attackers restored the configuration files back to its original form within minutes, making the compromise difficult to detect.
During these windows, the malicious configuration file was used to install the CROSSROAD and SHINYROAD malware.
When launched, the CROSSROAD downloader checked the performed reconnasaince on the infected computer, downloaded additional components, and established persistence through a scheduled task.
SHINYROAD is a backdoor that used legitimate Radmin components to load malicious code and establish an outbound connection to an attacker-controlled command-and-control server.
This allowed the attackers to potentially execute additional commands and payloads on compromised computers.
During the July 20 attack, Google also observed a second technique that attempted to steal Windows authentication hashes by forcing the software's notification system to access an attacker-controlled WebDAV resource through an invisible popup.
This technique could expose NTLM hashes that can be collected by the attacker-controlled server and later cracked using various tools.
The researchers also identified several IP addresses and hostnames used during the attacks, including
8.210.84[.]56
,
serv.oss-cn-hongkong[.]aliyuncs.com
, hostnames under
storage-data[.]com
, and
storage.googleapis.com
, a legitimate Google Cloud Storage endpoint.
AOMEI says CTO is investigating
ManageEngine told BleepingComputer that it first notified AOMEI about the suspicious activity on June 7, more than a month before researchers directly captured the malicious configuration files being served from its servers.
At the time, AOMEI initially suggested that the content may have been intercepted and modified while in transit, an explanation the researchers disagreed with.
"The evidence did not support AOMEI’s explanation of interception in transit," reads ManageEngine's report.
"Both endpoints had retrieved the content over HTTPS from AOMEI-owned hostnames, across different countries and unrelated network paths, and the executable had arrived through the application’s own extraction sequence rather than being written directly to disk by an external process. The content had been altered before it reached either endpoint, within the vendor-hosted delivery path."
When ManageEngine captured another attack on July 16, it immediately provided AOMEI with the original and modified file hashes, file differences, and altered files.
"AOMEI engaged, conducted its own review, and told us its initial examination had not found evidence of a breach," ManageEngine told BleepingComputer.
The researchers said AOMEI indicated that it planned to move the affected configuration files to new infrastructure with more detailed logging.
ManageEngine told BleepingComputer it advised AOMEI to preserve existing evidence before making those changes and to bring in incident-response specialists, connecting the company with Mandiant to assist with the investigation.
AOMEI later informed the researchers that its technical team had upgraded its servers, patched potential vulnerabilities, and verified that the files hosted on its infrastructure were correct.
Google also confirmed in its report that Mandiant notified AOMEI about the configuration file tampering on July 17 and that the company responded on July 29th, stating it took corrective action.
When contacted by BleepingComputer about the findings, AOMEI said it was treating the matter as a high priority and that its chief technology officer was leading an internal investigation.
"We have also internally detected this report and have classified it as a high-priority matter. Our CTO is currently leading a dedicated investigation to ensure accurate issue identification," AOMEI told BleepingComputer.
The company said its CTO would provide a more detailed response about the incident and the investigation's progress, and BleepingComputer will update this article if we receive new information.
AOMEI did not immediately confirm how attackers gained access to its update infrastructure or whether the reported compromise had been fully resolved.
While AOMEI says it has secured its servers, ManageEngine warns that these changes would not remove malware previously installed on customers' computers.
"A server-side fix stops new infections; it does not remove the backdoor from machines that received it during an earlier window," ManageEngine told BleepingComputer.
Organizations using AOMEI Backupper are advised to review the indicators of compromise published by Google and ManageEngine, including suspicious scheduled tasks, unexpected executable files in AOMEI installation directories, and connections to attacker-controlled infrastructure.
It's been more than a week since we
last checked in
on the Brooklyn Democrats. Things have surely sorted themselves out over there, right?
Funny you should ask. The Democrats were back in court Monday morning, attempting to resolve whether the people who held a
late-night meeting
October 4 purporting to elect a new executive committee for the Brooklyn Democrats under rules multiple courts had already invalidated, after being explicitly barred from holding such a meeting by a court's restraining order, should face any consequences for doing so.
Members of the party's reform bloc, who had won the
restraining order
barring the party from relying on the invalidated rules changes or convening a meeting to elect a new executive committee, immediately filed a motion to hold outgoing party chair Rodneyse Bichotte Hermelyn, her lawyers at Abrams Fensterman, and everyone who took part in the meeting, in contempt of court.
Rapper French Montana performs at the 2015 Hot 97 Summer Jam at MetLife Stadium on Sunday, June 7, 2015, in East Rutherford, New Jersey. (Photo by Scott Roth/Invision/AP)
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.
Linux Plumbers Conference videos now available
Linux Weekly News
lwn.net
2026-10-19 15:04:55
Mike Rapoport has announced
the release of the video recordings from the 2026 Linux Plumbers Conference (LPC),
which was held in Prague from October 5 through October 7. Find the
complete set via the YouTube playlist
or look for the video links in the schedule. See also LWN's
coverage
of t...
Staffing software company Bullhorn has disabled access to its platform to contain a cyberattack that caused a system-wide outage.
The company says it has isolated the issue and eradicated the immediate threat. Currently, its team is working to restore services following thorough security reviews conducted with help from CrowdStrike specialists.
Bullhorn is an American software company specializing in cloud-based staffing and recruitment solutions. Its platform helps staffing firms manage the recruitment lifecycle, including candidate tracking, onboarding, and payroll.
According to a status page on the incident, customers started to experience issues with job posting in the Bullhorn application on Friday.
The next day, the company said it was "experiencing a system-wide outage affecting the Bullhorn platform," and later confirmed that the issues were caused by a cyberattack.
"We have detected a cyber incident on the Bullhorn Platform. We have temporarily disabled access to our systems in order to contain the activity while we investigate further," the
company said
in an update.
In a FAQ page, Bullhorn says that a forensic investigation has been started and "not yet determined whether customer data was exfiltrated." Bullhorn promised to notify affected individuals directly if a data breach is confirmed.
According to the firm’s
status page
, most of the services are under maintainance or have degraded performance, except for Adapt, eEmpACT, and StaffSuite, which remain operational.
Major outages affect ATS/CRM, Automation, Back Office, Talent Platform, and sandbox environments.
At the time of writing, degraded performance was reported for Bullhorn for Salesforce and associated products, Onboarding365, and additional solutions including Amplify, Analytics, Messaging, SourceBreaker, VMS Sync, Data Hub, Erecruit, SalesDuel, and VMS Access.
Bullhorn has not provided any timelines for when those services will be restored. Customers should check the company’s service status page for the latest updates.
Also, the latest update mentions that all non-SSO users will be required to reset their passwords on their next login.
Also, as per the
FAQ page
, API passwords require rotation to protect integrations, while client-secret changes will follow later. For Bullhorn-hosted instances, this will take place automatically.
Customers can request data exports through the firm’s support to minimize business disruption.
Unposted time records will be reprocessed after restoration, and service credits will be reviewed against applicable SLAs once the incident is resolved.
BleepingComputer has contacted Bullhorn to request more information about the attack, and we will update this post with their response when received.
Beacon’s ultimate goal is to diffuse AI into the Real Economy. One concrete measurement of our success towards this broader endeavor is when we prove that we can actively manage and grow, alongside the owner-operator, our broad portfolio of essential businesses.
There are two main ways in which we can achieve this goal:
Digital Employees.
Equipping our portfolio companies with digital-employees-upon-request that can be dispatched to pursue concrete, well-defined tasks within the business. For example, spinning up an AI BDR to hunt for leads sourced from the networks of existing customers, or an AI Support Engineer that squashes customer tickets, or an AI accountant to take care of your books. There is obvious value to this; and there is also no shortage of supply of agent companies in service of these ends.
Company World Models.
Beyond enabling our portfolio companies to be more efficient and effective in their existing work, we can also grow them through better
strategic decision making
. While dispatching infinitely many Digital Employees is clearly beneficial, an even broader, more fundamental, more audacious, and more exciting technical challenge to pursue is to decide what the Digital Employees, and more generally the business, should be doing in the first place. We refer to models that are capable of this company-level strategic decision making as
Company World Models.
There is obvious value to this category of intelligence as well; however, there is significantly fewer teams tackling this problem.
Today, I’d like to share more of our vision what Company World Models can do, the challenges they pose from a capabilities and alignment perspective, the merit in pursuing their development, and how Beacon’s company structure enables the fastest path for research towards Company World Models.
Company World Models as a Co-Founder
In the literal sense, Company World Models (CWM) are models that can
Implement
the proposed hypothesis by dispatching Digital Employees and coordinating the verification of intermediate work output with human employees; and
Measure
the ultimate efficacy of the hypothesis and implementation vis-a-vis the originally stated goal, as well as the overall health of the business. If the outcome is subpar, the CWM should be able to diagnose the source of the issue, whether it be in the hypothesis or implementation stage.
By a slight (or severe) abuse of terminology, we use
World Model
to describe this form of intelligence. Like classical world models, Company World Models ingest a company’s current state and a proposed intervention, then estimate the resulting state. Hypothesizing the best potential improvement is accordingly a simple matter of searching over possible interventions for the one expected to produce the greatest risk-adjusted increase in company value.
In a more colloquial sense, we imagine CWMs to be the ideal co-founder; one that, in concert and debate with you, can spur new ideas for your business, sharpen your decision-making, and act as a long-term aligned thought partner for growth.
As we think about what work will look like in an increasingly AI-abundant world, it is not at all crazy to imagine CWMs as an enabler of the economy of the future—namely an economy powered by lean teams of entrepreneurs (perhaps, solo-preneurs) bringing passion projects to life, made commercially sustainable by the CWM. That, however, is a topic for another blog post.
A New Dimension of Data and Capabilities
Despite impressive general capabilities, current models are astonishingly bad at running businesses. For example, in its first two months running Andon Labs’ café, Gemini 3.1 Pro spent $38,000 against just $9,000 in sales. Even excluding rent, wages, and other fixed costs, sales fell approximately $5,600 short of supplier spending. It purchased 1,331 fresh bakery items and sold only 326. Newer models improved some behaviors, but the gap between completing business tasks and exercising sound business judgment remained.
Closing this gap requires a particular kind of data: 1) the full internal context and state of a business in digital form, ideally enabled by an
ontological data platform
with time travel capabilities; and 2) feedback from proposed and executed interventions.
Note that the latter need not always require rolling out an expensive real world trajectory. The owner-operators of Beacon businesses can supply judgement that is cheap, high-signal proxy for the much slower feedback of actual business outcomes. The ability to acquire this rich expert signal for CWM training is one of the many reasons Beacon works to keep the owner-operator in the driver’s seat of our portfolio companies.
Continuity Through the Silver Tsunami
The “
Silver Tsunami
”—i.e. the wave of business owners approaching retirement age—renders our work particularly timely from a public benefit perspective. For an owner without a clear successor, the challenge extends beyond finding a buyer. Who will inherit the intuition, relationships, and unwritten
metis
accumulated over decades of operating the business?
Our intention is to help preserve these businesses and the livelihoods they support. While owners remain actively involved, Company World Models can learn from their decisions and corrections, making their understanding available to the employees and successors who will carry the business forward. This requires working alongside operators while their knowledge can still be elicited, tested, and clarified.
Might these systems eventually assume many of an owner’s responsibilities? Certainly. But we need not resolve the limits of autonomous AI to see the immediate opportunity: helping a business continue to thrive after its owner chooses to retire.
Nor should we expect alignment to be finished at retirement. Customers change, new obligations emerge, and yesterday’s sensible decision may become tomorrow’s mistake. Successors must be able to revise the model and determine which inherited practices to preserve. Even as machines become more capable of decision-making, the people responsible for the business should retain authority over its objectives and tradeoffs.
The opportunity is to make an owner’s accumulated expertise useful beyond their tenure, while giving the next generation the room and tools to build upon it.
Company World Models as Alignment Mesocosms
Thoughtfully transitioning the real economy through the AI revolution is itself a worthy responsible AI problem of our time. The livelihoods of business owners, employees, and customers are at stake; and ensuring that these people benefit from AI should be central to what we mean by responsible AI.
These Real Economy businesses in Beacon’s portfolio and the customers we serve possess the knowledge, needs, and values that the frontier labs’ alignment recipes do not currently or adequately capture. Company World Models must account for these localized preferences to competently serve the businesses they operate. Doing so naturally brings this broad, underserved sector of the economy directly into the alignment process, whose preferences might otherwise never reach model development.
“Making money”, e.g. for a business, is clearly an objective people will instruct their AIs to pursue. But it exhibits
incomplete contract
characteristics
: the stated goal leaves the many conditions under which its pursuit is un/acceptable unspecified. An AI might deceive the board, exploit customers or indiscriminately cut staff to improve the numbers in pursuit of its ultimate objective.
Fortunately for us, Beacon’s owner-operators remain in the driver’s seat. They have the knowledge to recognize failures, strong incentives to intervene, and authority to inspect and reject consequential proposals before execution. Their corrections make the otherwise implicit conditions and exceptions of “making money” explicit for machines to learn.
Here,
is the Company World Model,
its inferred business state, and
the operator’s feedback. The business supplies the consequences; the operator supplies the judgment; and the model learns from both.
This is precisely the kind of
alignment mesocosm
I have previously argued for
: an environment where the AI’s objectives incomplete, where humans are incentivized to correct AI’s misbehavior, and the scope of the AI’s actions is bounded.
This enables us to study alignment under practical, grounded reality while simultaneously advancing model capabilities along a new, useful, and commercially incentivized dimension. The people whose businesses we seek to sustain become active participants in shaping a safe intelligence that will best serve them and best preserve their legacy.
A New Institution for a New Type of Model
At
Haize
, we had made substantial progress on one necessary component of Company World Models: translating human judgment into signals that guide machine improvement. We built technology that enabled nontechnical experts to express and translate what good behavior looks like into quantitative metrics, reward models, and judges. But as an outside vendor, we lacked the full internal context of the business and the organizational alignment needed to continuously learn from the people who understood it best.
Beacon is a researcher’s paradise in the sense that it enables us to approach this problem from the
inside out
. Long-term ownership lets us work within a business, understand its particulars, and align AI directly to the needs and values of its operators. A shared stake in the business’s continued success creates incentives to surface knowledge, correct mistakes, and measure whether the technology actually helps. It also gives us the responsibility to act on what we learn.
The resulting data is inseparable from these relationships. Producing it requires sustained access to real businesses, permission to intervene, and humans with both the expertise and incentive to correct the machines. Building Company World Models is therefore as much a project of institutional innovation as technological innovation. Beacon brings the two together.
The people who built the real economy should, and will, have a hand in building the intelligence that shapes its future.
Many readers will be aware that an unusually high number of features
have been reverted from the PostgreSQL 19 branch after the beta period
began. Having some reverts is not unusual, maybe one per cycle could
be expected. But this time around, about 8 to 10 significant
features, depending on how you count, have been reverted, and some of
them quite late in the beta period. I have been on the receiving end
of some of that, as the developer or committer of some of those
features, and have gotten some questions about it, and so I want to
take a moment to reflect on this. I’ll try to extrapolate a little
bit to similarly affected work that I was not actively involved in,
but these are just my opinions at this point.
So what happened?
I don’t think we, meaning all the developers affected, have had enough
time to fully reflect on all this. But here are some thoughts. It’s
probably a combination of these, and a different combination in the
case of each reverted feature.
Maybe we just didn’t do a good enough job. Maybe the code was just
not good enough. We’ll learn and improve. It’s probably some of
that, and I’m mentioning it here to not give the impression that it
was only the other factors that I’m going to mention.
It could also be a coincidence. Maybe we had been on such a good
roll that we attempted to tackle several features that turned out to
be too hard, or at least too hard to finish in time.
Some of the reverted features had significant architectural defects
that would have been hard to fix quickly and during beta. But there
was also a long tail of relatively harmless issues involving various
edge cases. In past times, many of these would not have surfaced
until much later and we would have fixed them bit by bit over the
subsequent five years. But with LLM-assisted code review, these
kinds of things can get found much faster, and then you’re staring
at a list of like forty defect reports. And even if each of them
requires only a three-line fix on average, there is a fixed overhead
to dealing with each of these, and then you run out of time. Most
if not all of the affected reverted features were written a long
time ago when LLM-assisted code review was not as useful as it is
now, meaning that the effective quality bar has been raised after
the time the feature was written and committed. Unless the
capabilities of LLM-assisted code review keep improving at the
current rate, this situation should sort itself out for future
development cycles.
A corollary of that is that, at least for the most part, as far as I
can tell, this situation is
not
due to “vibe coding”. This code
was written well before that was a possibility.
Because of the Vulnpocalypse, many senior developers were busy
between, say, April (the start of feature freeze for PostgreSQL 19,
and also the start of the Vulnpocalypse) and August (the most recent
PostgreSQL security release) with working on fixes for security
issues. Because of that, the usual additional review and testing
that happens during the beta period was reduced, and then picked up
again in August. That’s possibly why a lot of new issues were
discovered quite late in the beta period and why so many reverts
happened so late, which is what made all of this so notable. Again,
some issues were more fundamental but there was also a long tail of
smaller issues, and I feel with more time, say, two months, these
could have been addressed (given adequate focus, but note that the
Vulnpocalypse is ongoing). But the community preferred trying to
stick to the release schedule rather than delaying to get more fixes
in. (And you never know how long a long tail really is.)
The complexity of the system has made some kinds of features
extremely complex to get right, and there is not enough scaffolding
in the code to support that. Consider, as an abstracted example,
some SQL-level query language feature. Does it work with domains?
How about with domains over a composite type? Where one of the
fields is also a domain? And the domain has a not null constraint?
And one of the columns was dropped and re-added? And this is part
of a table partition that has been detached and reattached with a
different column order? And this is part of a view that is called
from a security-definer function from a trigger? And so on. No one
can manually test this or even enumerate these test cases. But
LLM-assisted fuzzing can find problems with this really quickly. So
this probably needs to be part of feature development in the future.
But we should also think about making the internal interfaces more
robust so that each different combination of contexts doesn’t open
up so many new possibilities of interactions.
I like to say, in PostgreSQL, “everything works with everything”.
This is part of the appeal, that you
can
construct cases like this
and expect them to work. I don’t want to give up on that at all.
But it does impose a significant penalty on feature development that
everyone needs to be aware of.
As a final point, the PostgreSQL development community has been
contemplating for some time the possibility of committing features
with some kind of “experimental” status and then maturing them in
the main tree. This would also be one possibility to address the
previous point. This would have been a helpful tool for at least
some of the reverted features, but we haven’t yet figured out a way
to do this, and some of the work suffered from misunderstandings
related to this. This is a concrete point to work on.
So what’s next?
First of all, from my personal perspective, thank you to everyone who
has reached out in person or online to express support and
encouragement. That’s the most important thing. I’m confident that
many of the reverted features will come back before too long.
PostgreSQL 19 will still be a great release. REPACK CONCURRENTLY,
logical replication of sequences (itself a previously reverted
feature), and planner hinting with pg_plan_advice, just to pick a few
headline items, will make this release very attractive. And it will
be very robust, after all the additional scrutiny.
It’s difficult to predict things now. A few months ago I said,
PostgreSQL 20 might have no new features, just bug fixes. It turned
out that things moved even faster, and PostgreSQL 19 now, kind of, has
half as many major features as then expected, but now we also already
have a few nice 80%-ready features queued up for PostgreSQL 20 that
just need those remaining 80% to get done!
Fred Potter, on LinkedIn:
So if you ever meet someone who tells you, “At Apple, I’m the one
who did this,” take it with a grain of salt. They were probably
part of the team that made it happen, and that’s already something
to be proud of.
Sometimes, when the final product finally comes out, you...
Tonight, I’m looking back through the photo album from my three years at Apple in Cupertino.
Here with Olivier Blum. One of the things that struck me most during that time was how much of the work was truly collective. Everyone contributes to the bigger picture, whether by shaping ideas, building things or convincing others.
So if you ever meet someone who tells you, “At Apple, I’m the one who did this,” take it with a grain of salt. They were probably part of the team that made it happen, and that’s already something to be proud of.
Sometimes, when the final product finally comes out, you can recognize a few of the personal touches you contributed along the way. And that, in itself, is immensely rewarding.
Wishing HomeView every success!
Exciting news for Safari users: Privacy Badger is now available on Safari for macOS! You’ll need Safari version 26.5 or higher to use it.
Whether you want to protect yourself from data brokers or just don’t want Big Tech profiting off your browsing data, Privacy Badger is here to help. More than 4 m...
Exciting news for Safari users: Privacy Badger is now available on Safari for macOS! You’ll need Safari version 26.5 or higher to use it.
Whether you want to protect yourself from data brokers or just don’t want Big Tech profiting off your browsing data, Privacy Badger is here to help. More than 4 million people already use EFF’s free tracker-blocking extension to take a stand against online surveillance. Safari users can now join them and EFF in the fight for a better web.
Safari support has been one of Privacy Badger’s most
requested
features for years. Thanks to recent improvements in Safari's extension support, we’ve finally made it happen for Safari version 26.5 and higher. Privacy Badger is now available on all major desktop browsers. And before you ask, yes, we will look into supporting
Safari for iOS
once we've ironed out any issues on macOS.
Why Install Privacy Badger on Safari?
Most websites
contain invisible tracking code that lets companies collect, share, and profit from your personal data. Some of those companies are data brokers that sell your information to anyone willing to pay. Creepy ads are just the tip of the iceberg when it comes to the harms of online tracking: Once your information enters the data broker ecosystem, it’s nearly impossible to know
who buys it
or what they’re doing with it. Privacy Badger blocks online trackers to prevent your browsing data from being used against you.
Privacy Badger goes beyond Safari’s
built-in privacy features
to provide additional protection against online tracking. In its default browsing mode, Safari limits the information that trackers can access but still allows them to load. Privacy Badger blocks trackers from loading in the first place, preventing them from tracking you using
techniques
that bypass Safari’s protections.
For example, Privacy Badger blocks
tracking from widgets
like embedded tweets, comments sections, and video players. These widgets can share your data even if you never click on them. Privacy Badger prevents these trackers from loading and replaces them with
click-to-activate placeholders
.
Beyond tracker blocking, Privacy Badger automatically sends the
Global Privacy Control (GPC) signal
to tell websites not to sell or share your personal information. The GPC signal is already legally binding in
a growing number of states
, including California, Colorado, New Jersey, and Connecticut.
All these features (
and more
) work together to help keep your browsing activity private on Safari.
Try It Out and Spread the Word
If you use Safari on macOS, give Privacy Badger a try. You’ll install Privacy Badger through the App Store on your macOS device. Installing extensions is a little more complicated on Safari than other browsers, so follow Apple’s
directions here
if you’re having trouble.
This is our first release of Privacy Badger for Safari, and we will keep improving it based on your feedback. If you run into any problems, let us know by emailing
extension-devs@eff.org
, or by opening an issue on
GitHub
. And if blocking harmful trackers causes issues on a website you visit, you can
disable Privacy Badger for that specific site
while keeping it enabled and protecting you everywhere else. You can also let us know about broken sites by using the “Report broken site” button found next to the “Disable for this site” button in Privacy Badger’s popup window.
When you use Privacy Badger, you join EFF and millions of other users in the fight for a better web. Help spread the word by telling your friends and family who use Safari that they can use Privacy Badger too!
A reading app for kids who have just learned their phonics sounds and need something real to read. Every word in a story can be
sounded out with the sounds they already know. When they get stuck, they tap the word and its sound buttons appear right there.
I made it for my daughter Yara. She's six and loves glitter, magic and dragons. She'd finished Teach Your Monster to Read and I
couldn't find anything for her to read next that was both a good story and made only of words she could sound out. Her big brother
Tom wrote the first story, and the app is built so there can be many more.
What's different
The help lives on the word.
Tap any word: a dot under single letters, a bar under pairs like "sh" and "ee", an arc joining
split vowels like a_e. One speaker button lights each sound in turn, then says the word. It never reads whole pages for them.
The checker is the point.
Stories are checked word by word against the sounds the child knows, by pronunciation and not
just spelling ("cake" fails if the child hasn't learned the split a).
npm run check
fails a story with a word they can't read.
Bring your own books.
Connect your own agent (Claude, ChatGPT, anything that speaks MCP) and it writes stories inside your
child's sounds, or types in books you own. It checks its own words, adds pictures, and shows you the result. Only your account sees them.
You set what your child knows.
Switch sounds and tricky words on or off. Words with a sound they haven't learned get a dotted
underline and the new sound shows in purple.
Run your own
It's a Cloudflare Worker with static assets, D1 for data and R2 for pictures. No build step. If you're a tech dad (or mum) with a
kid who's learning to read, I'd love you to take this and make it yours.
git clone https://github.com/finereli/yarareads &&cd yarareads
npm install
npx wrangler d1 create yara-reads # put the database_id in wrangler.jsonc, with your account_id
npx wrangler r2 bucket create yara-reads-pictures
npx wrangler d1 migrations apply yara-reads --local
node tools/lexicon-asset.mjs # the word dictionary the worker uses
node tools/push.mjs --local --inventory --images --owner dev # load the stories (--owner: books from home, if you have any)
npx wrangler dev
Then
npm run deploy
when you're happy (edit the
routes
in
wrangler.jsonc
for your domain; deploy needs the dictionary step,
which the script runs for you).
Things to know:
It works signed out.
That's the whole app, with the sounds and progress kept in the browser. Accounts (and so agents) use
login.finereli.com
, which only serves my own apps. To run accounts yourself, swap in your own sign-in:
public/login.js
and
src/verify-login.js
are the only files that know about it.
The sounds are my voice
, recorded for the tiles, and they aren't in this repository. Without them the tiles still light up
but stay quiet. Record your own with
tools/sounds-record.mjs
(see the comment at the top). Words are spoken by Cloudflare
Workers AI, so deploying needs an account with that enabled.
Write a story
: copy
content/stories/toby-1.json
, edit the pages, run
npm run check
. It tells you every word your child can't
read yet. Never loosen the sounds to make a story pass: rewrite the story.
docs/vocabulary.md
has the queue of what to teach next.
Pictures
:
docs/illustration.md
and
tools/illustrate.mjs
describe how the illustrations were made.
CLAUDE.md
explains how everything fits together, for you or your agent.
Usage numbers:
node tools/stats.mjs
.
Licenses
Code: MIT (
LICENSE
). Stories and pictures: Creative Commons Attribution 4.0 (
content/LICENSE.md
), so remix away and credit
Yara Reads and the authors. Third-party material:
NOTICE.md
.
You might have already noticed that 2026 seems to be a bit special year for Rust compiler. It seems like there's just a lot of stuff going on. Some things were already announced since I started writing this, but there's still a bunch more that's not as visible. I'll share some things that I personally find interesting.
To explain a bit of context, what happened this year is that multiple different initiatives are reaching final steps at the same time. In other words, 2026 is not that special with the amount of work being done, but it's a year when we see several long-term investments starting to pay dividends.
Probably the biggest thing is the
next generation trait solver
. This is a reimplementation of a big part of the type system, and it has been in the works for a very long time - Almost 10 years in various forms.
It fixes a bunch of soundness bugs and unblocks a lot of features and fixes for long-standing issues.
It's easy to understate how big of a deal this is for the compiler. This work resolves a major piece of technical debt that a lot of compiler developers dreamed about for years. It also frees up a bunch of people with a fresh and deep understanding of the type system to work on new things. The queue of things that get unblocked includes many common pain points of the language, even things that might seem benign or unrelated. It contains solutions to big problems in
async
Rust, or various limitations of
impl Trait
.
Another big thing is
Polonius, a new borrow checker implementation
, long time in the making as well. It enables more code to compile and unblocks several related features - including (hopefully one day) internal references. The compiler impact of this is not as big as with the new solver, but it's still a pretty big deal.
My main area of interest is compiler performance, and here we have quite a few things going on. After 1-2 years of a sort of stagnation (at least in terms of results), we suddenly have a lot of things going on at once. So much so that I have a hard time remembering everything, but from the top of my head:
Very old initiative that was put a few years on hiatus with many unclear blockers. The development restarted again a few years ago with a new contributor
@SparrowLi
, and over time a number of other people contributed to the effort.
Over the years, this turned out to be a massive can of worms. I get the feeling that almost nobody is really happy with the design. However, there doesn't seem to be a better alternative for the foreseeable future, and parallel frontend is highly desirable, so the solution ended up being just grinding through a number of annoying and hairy problems until there's nothing left.
The
current project goal
is driven by
@petrochenkov
and is getting close to stabilization.
LLVM 23 was unambiguous and unexpectedly large positive change in performance. For a long time, LLVM upgrades were not particularly great for rustc performance. This changed after LLVM 10 upgrade, which introduced a massive 10% regression, and
@nikic
, current lead developer of LLVM, called it out in his blog post,
Make LLVM fast again
. In the post he also introduced a system for tracking LLVM performance over time, inspired by
the one we use for rustc
.
Since then, LLVM started catching performance regressions earlier, and results for upgrades in rustc went from "less bad", to "somewhat mixed", to "mostly positive with caveats." The last one of those was LLVM 22, which was green on
icount
benchmarks, but almost universally red on wall time.
LLVM 23 is pretty much entirely positive. I don't follow LLVM development that much, but my understanding is that this is because there's now more work on actually optimizing it, as opposed to working on features without trying to regress performance. These days the improvements come both from new optimizations (those help optimize the compiler during bootstrap) and from LLVM itself getting faster.
Lot perf improvements landing (micro-optimizations)
🔗
Compiler performance has been on a steady streak of improvements in the past few months. There's probably no single explanation for it, just a combination of new contributors coming in, old contributors getting to do more perf work, and tooling improvements combined with architectural cleanups unlocking new opportunities.
With more people working in this area, I've noticed a lot of cross-pollination,
where a certain idea would circle around a few people's minds, as people get inspired by each other's PRs and try related things.
I also feel like we got a lot better at managing regressions - triaging and addressing them.
This is partially a tooling investment, but also a lot about processes and social structures.
A major development here is the connection between tree ops and perf triage, represented notably by
@JonathanBrouwer
.
This means that people who manage merges often directly triage their performance impact. This is important because it shrinks the response time, but the connection is useful for other reasons as well. The perf impact informs how you group PRs into
rollups
, for example. Turns out that
Conway's law
is still a law.
I also greatly enjoy helping people interpreting the measurement results and diagnose regressions.
I often find that even just a few sentences from somebody who's been looking at the results every day for many years
go a long way towards getting the regression addressed.
All in all, I feel like the compile time concerns are integrated into the development better than they have ever been.
This seemingly came out of nowhere earlier this year, and it's quite interesting.
@Amanieu
proposed
a MIR optimization pass
that allows the compiler to eliminate copies that LLVM has trouble optimizing. It speeds up both compile time and runtime.
This is one of those passes that makes sense to implement in MIR instead of LLVM, because the Rust part of the compiler
has better information about whether it's valid to apply specifically for Rust. Even more so because it actually requires changing the MIR semantics a bit.
It matters for Rust in particular because Rust typically generates more moves than C(++), which is the primary LLVM target.
This one is particularly close to my heart because I've been following the efforts for a very long time. Polymorphization is one of the most impactful compiler performance optimizations we could ever do, but it's unfortunately really tricky to implement.
This would be the third experiment I'm aware of. This time it's slightly different from the previous ones, and it's inspired by a similar mechanism in Swift.
The difference is that the original polymorphization intends to only avoid duplicate or redundant monomorphizations, so it's purely a compile time optimization with no runtime impact, while the Swift-style one intends to polymorphize everything and pass around layouts of generic parameters as arguments. This will have a runtime cost, so it'll be something you can tweak with compiler flags.
If my understanding is still up to date, next-solver will also enable polymorphization in the previously intended way. Either way, both options run into the same problems, so the work is useful for both. It's also possible that both options come out of this same effort. Either way, this is still just an experiment with a bunch of problems to solve, so we'll have to wait to see how it turns out.
The project goal
has been proposed and driven by
@camelid
.
@blyxyas
is working on a
project goal
,
which will enable cargo to share artifacts between
cargo check
and
cargo build
.
The goal is actually more general, but this is probably its most recognizable outcome.
This is something we wanted for ages, so it's really cool to see progress on this front.
Already announced as well
,
this is another project that has been in the works for quite some time.
As with the other things above, this is major internal restructuring that unlocks other things - namely granular locking of the target directory and cross-workspace caching.
@bjorn3
has been working on fixing support for these two flags, which enable pipelining of build scripts and proc macros. As you can see in the
proposal
, this is yet another line of work that boils down to fixing a laundry list of internal issues and architectural problems until suddenly a big thing is unlocked.
There have been a number of initiatives in the compiler architecture. I'll mention a few, just to (once again)
underscore the point that big things don't happen in big-bang projects coming out of nowhere, but rather as consequences of
sustained long-term investments into a healthy system.
Two years ago,
@jdonszelmann
started the effort
to unify and cleanup how attributes are represented and checked in the compiler.
Just a few days ago, the last remaining attribute was ported to the new system. This significantly improves how attributes are checked and unblocks improvements to diagnostics and other things.
Earlier this year,
@Zalathar
and
@nnethercote
cleaned up the implementation of rustc's query system. This improved performance but more importantly, made the system easier to understand, which was often a blocker for making improvements to it. The system is still a pretty scary part of the codebase, but this is a big step forward.
There's actually more architectural work in this area,
@oli-obk
has been working on
architectural groundwork for expansion-time evaluation
,
and there's been a lot of work by
@cjgilot
,
@petrochenkov
and other people I'm forgetting (sorry) on queries and incremental in general.
Similarly, a lot of work happened to enable const generics to progress further. A common theme of these efforts is that
they enable the compiler to use its capabilities in more contexts where it was previously limited,
often because of strict ordering of some compilation phases.
There's quite a bit of meta stuff as well. Rust project has been experimenting with a new organizational framework called "project goals."
It went through multiple iterations with various changes and experiments, but it seems that the system has finally reached some optimal steady state, and we see the benefits play out.
I think you can clearly see that from the list above.
We now have
a Fast Builds
roadmap and multiple perf related project goals. That's pretty exciting.
There are also multiple new developments in funding. One is explicitly attached to project goals, we also have a new
"Maintainers in Residence"
program,
and a new funding team was established as well.
One also can't help but notice how many results came out of
Hexcat
employing a bunch of people in the past year.
And lastly, 2026 is also an exciting year for me. After a few years of watching from the sidelines and eventually joining the perf triage, I decided to start working on the Rust project more seriously.
Earlier this year, it became clear that I need to decide what to work on next. My current work is slowly winding down and turning into maintenance, and I also started to feel a bit burnt out on web-based work. For quite some time, I've been feeling the desire to return to something more technical and challenging.
I was considering a few options, but somewhat unable to decide between them. To use the term from Marie Kondo, nothing really felt like it "sparks joy." After some exhausting events and feeling a bit down from all of this on one evening, I received an invitation to Rust All Hands. This was a pleasant surprise. I signed up for it earlier that year, but I didn't really expect much because I didn't know the likelihood of being invited. I took this as a sort of sign from the universe or something and booked the trip.
The experience was overwhelmingly positive. I have to say that this was one of the most exciting events I attended in a long time. It reminded me that there's this big part of my life that I don't get to share with anybody almost ever, especially in real life. It seems so easy to forget that until you actually experience it again.
Yes, sure, I can talk about some curious aspects of the Rust compiler with my friends, but it's a whole another level to talk about it with people who actually work on it and understand what you talk about on a deep level. It was really nice to meet people I know from their work and join the discussions about the development of the language.
Long story short, it became clear that this is it, this is what I want to do. I was thinking about it before, but I guess I needed some strong "spark of joy" moment to stop doubting my feelings and force me to make a decision.
Now, of course, the question is how to actually do it. As you may know (and I somewhat hinted above), it's not exactly straightforward to find a job on the project.
There's no "Rust inc." company you can send a CV to.
There's a fractured and diverse space of possibilities where everybody finds their own way somehow.
It's getting more approachable with those new programs, but I still expect this to take some time. Part of it depends on connections and trust, and those are built over time.
I don't have to rush this, so I'll keep working until I figure something out.
I've agreed to work on the
target directory size reduction project goal
if there is enough funding for that. I've also applied for
MiR
program, but I don't think that'll be available soon because the funds are limited and there are more important areas that need this specific funding.
btw. I also opened
GitHub sponsors
, so feel free to join if you want to support some compiler performance work ;)
There's so much happening in the project that I feel like it's really challenging to do it justice.
I already feel like I left out a ton of interesting work, but I have to stop somewhere. I hope that even this incomplete overview has been interesting.
I think I should also say that not everything has been positive. The beginning of the year was overshadowed by a bunch of people losing funding and heated discussions around AI policy. Just a few days before All Hands, somebody posted the policy draft to social media, and our small moderation team and other people spent a stressful weekend trying to limit the damage.
In light of that, I have a feeling that All Hands was a turning point where everybody could recharge, refocus, and take the positive energy back to the project. I certainly feel that, and I hope I'm not alone.
Europe EV sales rose 70.3% in September, 32.6% of market share
OpenCode hack exposes API keys amid AI distillation attacks
Bleeping Computer
www.bleepingcomputer.com
2026-10-19 13:27:15
The open-source AI coding project OpenCode has notified a small number of users that API keys they used with external providers were exposed in a security breach. [...]...
The open-source AI coding project OpenCode has notified some users that stored API keys they used with external providers were exposed in a security breach.
Multiple users reported that the incident led to unauthorized API charges and suspended projects in Google Cloud.
According to the project maintainer, the breach affected 1.4% of OpenCode Console users, with some reporting more than $1,700 in unauthorized charges overnight.
OpenCode is a model-agnostic AI coding agent that helps users understand code, write features, and fix bugs using natural-language instructions, through a terminal, desktop app, or code editor.
Users can connect AI models from multiple AI providers to the OpenCode console to streamline and automate the development process.
Distillation attack
On Saturday, OpenCode announced that it suffered a large distillation attack that impacted only developers who linked external providers, including Anthropic, OpenAI, and Google.
“We had a security breach last night related to a large-scale distillation attack that impacted 1.4% of OpenCode Console users,” the
project maintainer said
.
“We have notified them all this morning via email. If you did not get an email, you were not impacted, it was a subset of users who had external providers linked.”
Distillation is a legitimate machine-learning technique that
trains smaller AI models
using responses generated by more powerful models. The goal is to create cheaper, faster models that retain many of the capabilities of their larger counterparts.
However, the technique becomes an attack when it involves large-scale training through unauthorized queries.
He also said OpenCode's investigation of the attackers were blocked when the AI models it was using began refusing requests due to built-in security safeguards.
Distillation attack on OpenCode ran for 48 hours
source:
Dax Raad
Raad said the situation stabilized after OpenCode began using OpenAI’s Daybreak AI cybersecurity model for defensive work, which it was approved to use on Saturday.
The email sent to impacted users notes that the earliest possible exposure of the users’ keys was on October 17, 2026, 00:30 UTC, and that no data appears to have been exposed.
OpenCode also said it was working with Google, OpenAI, and Anthropic to address the incident but could not share further details at this time.
User reports claim rogue charges following the private key leaks, ranging from
several hundred USD
to
up to $1,700
. OpenCode’s message to impacted users mentions the possibility of reimbursement for those impacted.
Getting my TOTP data out of Twilio's Authy app thanks to the GDPR
blogccasion
blog.tomayac.com
2026-10-17 13:21:12
As every responsible Internet user, I use two-factor authentication (2FA) for my important accounts. For a long time, I depended on Google's Authenticator app, but because early versions of the app weren't backed up to the cloud (not a problem anymore) and because as a Google Android dogfooder I sw...
As every responsible Internet user, I use
two-factor authentication
(2FA) for my important accounts. For a long time, I depended on Google's
Authenticator
app, but because early versions of the app weren't backed up to the cloud (not a problem anymore) and because as a Google Android dogfooder I switch devices frequently, I turned to Twilio's
Authy
, which at the time already supported cloud backup and cross device synchronization. Authy has both iOS and Android apps, and also offered a desktop app, but for whatever reason they shut down the desktop app three years ago.
Now every time I needed a token, I had to get one of my phones out. Annoying, but not annoying enough for me to actually switch away from Authy. I have 33 accounts in there, and unfortunately Authy offers no export option. For a while, you could hack your way to your data by installing an old version of their desktop app and sniffing the network traffic, but they eventually patched that loophole. Modern Android and iOS versions (for good reason) also make it incredibly hard to sniff mobile traffic, plus I have corporate devices that prevent me from installing the required apps and certificates.
So my data was locked into Authy, with my choices being to just be lazy and stick with it, or bite the bullet and set up 2FA again for each account. Guess what I did! Correct, I entered each account one by one, turned off 2FA, set it up agai… Haha, LOL, of course I did not. I stuck with Authy and walked to one of my phones like a Neanderthal every time I needed a token.
Until I remembered that under the European Union's 🇪🇺
General Data Protection Regulation
(GDPR), I have the right to request my personal data from any service provider, including Authy. If you live in the EU, you have, too. Here's the request I sent to Twilio (
privacy@twilio.com
) to get my TOTP data out of Authy:
Dear Twilio Privacy Team,
I am a resident of [Your EU country] and a user of the Authy application. Under the EU General Data Protection Regulation, I am exercising my right of access (Article 15) and my right to data portability (Article 20) with respect to the personal data you process about me.
Please provide a complete copy of all personal data associated with my Authy account, identified by:
I specifically request that your response include the stored authenticator data for my account, namely the encrypted TOTP token seed values together with any associated salts, initialization parameters, and key-derivation parameters required to decrypt them, and, for each token, the issuer or account name, the number of digits, the period, and the algorithm. Please also specify the encryption scheme used to protect the token seeds, including the cipher and mode, the key-derivation function, its iteration count, and the hash function. The token seeds are stored encrypted under a password known only to me, and I am asking for that encrypted data as you hold it, so that I can decrypt it myself.
Under Article 20, please provide the token data in a structured, commonly used, and machine-readable format, for example JSON.
Please confirm receipt of this request and respond within one month, as required by Article 12(3). If you consider any part of this request unfounded or excessive, please explain your reasoning for each element rather than declining as a whole.
Thank you.
Kind regards,
[Your name]
They came back quickly, asking for the following verification details:
All current and past email addresses associated with the Authy account.
All current and past phone numbers associated with the Authy account.
A confirmation code sent through text message to the number linked to the account, which should be sent back with the reply.
I responded with the requested information, and a few weeks later they sent me a link to a secure file transfer on
twilio.sendsafely.com
and let me download two CSV files with the data. One was an
Authy Personal Information Request - Exported Tokens (1).csv
file with the columns
name
,
encrypted_seed
,
salt
, and
iv
. The
name
is just the name of the token I had chosen. The others are explained below.
encrypted_seed
: The actual TOTP secret (the seed used to generate 2FA codes), encrypted so it's unreadable in plain text.
salt
: Random data mixed in when deriving the encryption key from the encryption password (prevents precomputed "rainbow table" attacks and ensures the same password doesn't always produce the same key).
iv
: The random value (initialization vector) fed into the cipher itself, ensuring that encrypting the same seed twice (even with the same key) produces different ciphertext each time.
The other file,
Authy Personal Information Request - Authy Personal Information (2).csv
, was a text file (despite the
.csv
extension) with CSV-ish metadata about my account and its associated tokens.
,,,,,
User Information,,,,,
Phone number(s),"(+49) [REDACTED]
",,,,
E-mail (primary and secondary),"[REDACTED], [REDACTED]",,,,
"Last Sync (The last time one of your devices communicated to Authy)
-Time is in UTC","Oct 10, 2026 - 06:37
",,,,
"Used at (The last time you verified an Authy TOTP token)
-Time is in UTC","Jun 01, 2018 - 10:27
",,,,
"Created (When the Authy user was created)
-Time is in UTC","Jul 06, 2017",,,,
,,,,,
Devices linked to the Authy user,,,,,
Name,Created,Device Creation IP,User agent,Device ID,Last sync
Android,"Sep 30, 2019",[REDACTED],Dalvik/2.1.0 (Linux; U; Android 10; Pixel 3a Build/QQ1A.190919.002) Mobile,[REDACTED],"Sep 18, 2021"
[SNIP]
Android,"Jun 23, 2026",[REDACTED],Dalvik/2.1.0 (Linux; U; Android 17; Pixel 11 Pro Fold Build/CD1A.260612.002) Mobile,[REDACTED],"Oct 10, 2026"
,,,,,
Authy native tokens,,,,,
ID,Name,Email,Cellphone,Member/Owner,
[REDACTED],Twilio,[REDACTED],[REDACTED],Member,
,,,,,
Authenticator tokens,,,,,
Name,Logo,Created at,Updated at,,
GitHub:tomayac,GitHub,"Jul 17, 2025","Jul 17, 2025",,
[SNIP]
I threw both files at Claude and asked it to create me a
TOTP Vault PWA
that going forward I can use on all of my devices, desktop or mobile, with the TOTP data backed up to a private GitHub repo. After a few iterations back and forth with the LLM, I can now scan QR codes and add new TOTP tokens seamlessly using the
Barcode Detector API
. The app is fully offline capable thanks to
Service Workers
. It looks almost like a native app because I use
Window Controls Overlay
. Each TOTP line has a guessed (but overrideable) icon provided by
Icon Horse
. And it is
my
PWA with features tailored to my needs, like always sorting entries by most recently used, a search input that clears after copying the token, plus, of course, token import and export functionality for all possible providers and standards:
Bitwarden / Vaultwarden:
Unencrypted JSON for importing data in
Bitwarden
/
Vaultwarden
. I use Vaultwarden as a backup on my devices.
otpauth links:
An unencrypted text file with one
otpauth://
link per line, for apps like
Ente Auth
.
Encrypted vault
(not really a standard, but what I use for my backups): A CXF document inside a
JSON Web Encryption
envelope, locked with my password. Yes, the below screenshot is redacted to not show any sensitive TOTP data like the actual account names or the token values (though the latter is really just me being a
tin foil hat
, it's totally unnecessary).
It's kind of sad that I had to use the
GDPR
sledgehammer to get my own TOTP data out of Twilio's Authy, but at least now I have full control over it, and I'm, once more, thankful that the GDPR exists. I would also like to credit Authy for dealing very professionally and promptly with my data request.
Making all divisions slower to fix a bug in 0.000000000000000000542% of cases
Almost all modern machines use
two’s
complement
to
represent integers. This representation is asymmetric, in the sense that the
most negative number has no corresponding positive number. For example, with
signed 8-bit numbers, the most negative number is
-128
, whilst the most
positive number is
127
. This quirk shows up in various cases, but for the
purpose of this post, I am concerned with signed integer division, where
x/-1
mathematically should produce
-x
, but in the case where
x
is the most
negative number, that is not possible. For 32-bit integers, which I arbitrarily
decide are the most common, this means that one out of every 2⁶⁴ possible inputs
is impossible to represent correctly - leading to the somewhat clickbaity title
of this post, and some recently fixed troubles in the Futhark compiler. In this
post I will explain what the actual problem is for a language implementation,
how we fix it, and what the performance cost looks like. The main audience of
this post is other language implementers, but I think the concepts involved are
simple enough that anyone curious about low level issues can follow along.
The Futhark compiler has multiple backends, but the most important ones work by
generating C code. This has many practical advantages:
It is easy to debug the generated code because it is easy to read and modify
by hand.
Most systems have a C compiler (or easy access to one), meaning Futhark has
fewer dependencies, is portable, and doesn’t need to bundle native code
generators.
Some code patterns are hard to express (or express efficiently) in C. This is
mainly the case for advanced language features such as coroutines, tail
calls, or garbage collection. Fortunately Futhark is
pretty boring from a
semantic perspective
, so this
does not affect us too much.
It is very easy to accidentally generate C code that is subtly wrong. This
does unfortunately keep pestering us.
C is of course renowned as a very safe and easy-to-use language, because C
programmers never make coding mistakes. The few times they do make mistakes, it
is often due to mishandling of pointers or array sizes, leading to buffer
overflows, heap smashing, etc. These are actually not the main problem with
generating C from Futhark, as Futhark itself is memory-safe, and systematically
inserting in bounds checks in generated code is easy (
although a little more
interesting in GPU code
).
No, the main problem we’ve had is actually undefined behaviour. As is by now
well-known, C specifies various events as explicitly undefined, meaning not only
that a C compiler can assume it will never occur, but also that no particular
result is guaranteed should a program perform one of the undefined operations.
Some causes of undefined behaviour are obvious and easy to avoid: reading arrays
out-of-bounds, using freed memory, etc. But C has a long list of more obscure
cases. My favourite example is that in C99, it is undefined behaviour if a
source code file does not end with a final newline character. Yet we have
honestly not spent that much time dealing with that particular issue in Futhark.
No, the main problem, and now we are finally returning to the premise in the
post, is that
signed
integer overflow is undefined behaviour in C. This is
particularly insidious since most programmers have a mental model of fixed-size
integer arithmetic where overflow is a natural event, and so does the actual
machines we use, but a C compiler may assume it never happens. The reason behind
this specification is so the C compiler can optimise based on useful properties
such as
x+1>x
, which are not true in the presence of overflow, but the
motivation does not actually matter to us. In a language like Futhark, where
integer overflow
is
defined behaviour (it wraps around), this creates a very
unfortunate mismatch between what we want to do, and what we can express in our
target language.
Fortunately, C is merciful enough to specify that for
unsigned
numbers,
overflow is well-defined, and behaves just as you would expect (on a
two’s-complement machine, anyway). For this reason, Futhark’s C code generation
actually represents all integer types using unsigned C types, (so
i64
becomes
uint64_t
), and then performs the arithmetic on unsigned types. This works due
to the nice property of two’s complement representation that most arithmetic
operations are done exactly the same, at the bit level, as for unsigned
integers. One exception is comparison operators, in which we cast to the signed
type (e.g.
int64_t
) before performing the comparison. Such conversions are
free, since they do not need to change the bit representation of the number, but
only affect what instructions the C compiler emits for e.g. a
<=
operation.
Another operator where sign matters is division. If we do
x/-1
, then it is
quite important whether we are dividing with a small negative number, or with
the number that arises if we interpret the two’s complement bit pattern for
-1
as an unsigned integer. This means that for signed integer division, Futhark
generates a signed C division. This means that if we do
x/-1
where
x
is the
most negative number, we are stuck with the issue described in the post opener -
the correct result (
-x
) cannot be represented as a signed integer, so this is
a signed integer overflow, and that is undefined behaviour in C.
Futhark is a principled language, and therefore producing undefined behaviour is
unacceptable. (I realise the hypocrisy of this puritan declaration whilst
leaving in the bug for ten years.) Further, on x86 this kind of division will
actually signal a CPU exception, crashing the program, so this is not merely a
violation of the sanctity of the C specification. Fixing it in principle is
easy. This is the definition of 32-bit signed division in the Futhark runtime
system:
int32_t squot32(int32_t x,int32_t y){return x / y;}
And this is the version that avoids the 0.000000000000000000542% undefined cases:
int32_t squot32(int32_t x,int32_t y){return y ==-1?(int32_t)(0-(uint32_t)x): x / y;}
This function simply checks whether the divisor is
-1
, and if so does the
negation with unsigned (well-defined) arithmetic. The cost is a branch on every
single division. The behaviour is still
implementation-defined
, but produces
the right results on the machines we care about.
(Why
quot
instead of
div
? Futhark actually has
two
division operators -
one that rounds sensibly towards negative infinity, and one that rounds towards
zero like C. The function above is the one that follows C’s behaviour because it
is less code, but the issue is the same either way.)
Correctness is not really a thing we can compromise on, but in principle it is
frustrating that
every
integer division needs an additional branch just to
handle a
single
special case that may never actually happen, as it is highly
unlikely that a program’s correctness
depends
on wraparound for signed integer
division at the ends of the numeric scale. But apart from the principal
frustration, what is the actual overhead?
Measured on the
Futhark benchmark
suite
on GPU, I was unable to
measure an impact. This is likely because signed integer divisions are
relatively rare, and even when they do occur, they likely occur due to index
arithmetic, where the resulting memory loads have so much latency that they
easily
hide
the cost of
doing the divisions.
But what if we try to construct a contrived program where the bottleneck is
signed division throughput? That would demonstrate something close to worst-case
overhead of adding the branch. Behold,
divisions.fut
:
-- ==-- random input { 1000000 [1000]i32 [1000]i32 }entry main [n] (k: i32) (xs: [n]i32) (ys: [n]i32) : [n]i32 = map2 (\x y ->loop z = xfor _i < k do #[unsafe] z // y) xs ys
The program accepts a number
k
and two arrays of integers. For each
corresponding pair
x
and
y
, it
k
times divides
x
by
y
, using
//
to
target the
squot32
function, and using
#[unsafe]
to remove division-by-zero
checks.
For most values of
k
, repeated division quickly produces zero, but the
compiler cannot assume this, so it will have to actually perform the divisions.
You may reasonably argue that the program is not
purely
division bound, as the
bookkeeping around the loop also involves costly things such as adding and
comparing integers, but a program that contains a very long
unrolled
sequence
of divisions stretches my credulity too far.
Using the handy
futhark
bench
tool, we can then
measure the impact using the compiler with a fixed implementation of
squot32
(
part of this pull request
).
First on sequential code, using the
c
backend:
There is no measurable difference, which is not a surprise on a modern
speculatively executing CPU for a program with an easily predicted branch.
But what about GPUs? After all, “GPUs are bad at branching” is a common motto by
those of my students who like to replace an
if
with ten lines of dense
branchfree code. Let’s try the experiment again with Futhark’s
cuda
backend:
Well then! This really is a major difference. Much more than I expected when I
began this work, actually. Reading the generated PTX (CUDA machine code), the
old version is partially unrolled into four consecutive
div.s32
instructions
in a single basic block, whilst the fixed compiler still triggers unrolling, but
with many branches between the divisions.
I observed a similar result on an AMD GPU with the
hip
backend, although the
impact was slightly less there.
The cost of fixing those 0.000000000000000000542% of divisions is real and
unfortunate, and I would certainly like to have a cheaper fix. Having undefined
behaviour in the generated code is of course not acceptable, so we will have to
live with this for now. On non-contrived benchmarks, it seems there is
essentially no impact. For programmers unwilling to pay this cost, you can
always stick to
unsigned
divisions, if you know that you will never have
negative numbers.
This is the last instance of undefined behaviour in Futhark’s generated C code
that I remember. There is however at least one instance of
implementation-defined
behaviour, namely in the code generation for
bit-shifting integers by more bits than their size, but I have yet to gather the
courage to fix it.
Today we’re introducing Mercury 3, the most capable diffusion-based LLM released to date. Across a range of benchmarks, Mercury 3 outperforms GPT-6 Luna and Claude Haiku 5.5, while running 4–8x faster at 1,000+ tokens per second.
Mercury 3 demonstrates that text diffusion scales. It’s more than 40x larger than Mercury 1 and is vastly more intelligent, but just as fast.
Early-access partners already use Mercury 3 for voice and chat support, real-time tutoring, data engineering, and web navigation:
Mercury 3 at a glance
Quality:
On par or better than frontier speed-optimized models like GPT-6 Luna and Claude Haiku 5.5.
Speed:
1,068 tokens per second on NVIDIA GPUs.
Context:
1M tokens, up from 260K for Mercury 2.5
Price:
$0.20 per million input and $0.70 per million output tokens.
At launch, Mercury 3 is 50% off at $0.10 per 1M input and $0.35 per 1M output. Cached tokens are 90% off the input price.
Diffusion at scale
When we launched Mercury 1, it was the first proof point that diffusion LLMs could be built for commercial applications. The open question in the AI community was whether diffusion LLMs could scale to compete with autoregressive models on complex use cases.
Mercury 3 answers that question: they can. We’ve scaled Mercury more than 40x in total parameters, and intelligence across a range of standard benchmarks has risen 3x from Mercury 1 (mini) to Mercury 3. The scaling laws that drove progress in autoregressive models hold for diffusion too.
Mercury 3 in production
Early-access partners are already running Mercury 3 to power latency-sensitive applications such as browser use agents, interactive education, real-time search agents, and customer support.
Browser Use Agents
Agents wait on the model at every step, so small delays compound quickly. Mercury keeps each pass fast, whether the agent is navigating websites, researching across sources, or analyzing logs and tracing incidents. Agents finish sooner and have time to try more approaches before answering.
We ran Mercury 3 inside our production web-agent harness against frontier models, on 50 live Mind2Web navigation tasks. Mercury 3 completed 50% of them, significantly more than GPT-6.1-Sol. It did so using the same token volume and the same number of agent steps as a frontier model, at a fraction of the per-token cost.
Shuhao Zhang, Cofounder, TinyFish AI
Interactive Education
Learning runs on fast feedback loops, and any delay pulls a student out of the material. Mercury reasons through each request and responds in near real time, whether it’s a voice tutor carrying a conversation, an assistant grading work, or an app adapting the next question to what the student just got wrong.
Mercury 3 allowed us to give every student instant feedback without giving up reasoning. Hints, marked answers and definitions now come back in about a second, with quality as good as or better than the models we ran before. When a student is stuck on a question, that speed keeps them working instead of waiting, and it was a drop-in swap for our existing stack.
Michael Tong, Co-founder/CTO, General Learning aka RevisionDojo
Real-time search agents
Search applications start to feel unresponsive after just a few seconds delay. Mercury 3 runs fast enough to process dozens of documents and still answer while the user is engaged.
On smart glasses, an answer that takes five seconds feels broken. In our Sense API tests, Octen search took about 80ms; model generation was the bottleneck. Mercury 3 delivered the best balance of speed and quality among the fast models we tested, with a median generation time of 0.9 seconds and a median end-to-end response time of 2.2 seconds.
Kuan Zou, Founder & CEO, Octen AI
Customer support
Support agents have to answer quickly, often for regulated businesses where a wrong answer is costly. Mercury keeps responses conversational without sacrificing accuracy.
At Lorikeet, we help complex and regulated businesses build a concierge for their customers that works across voice, chat and email. In chat and voice, customers need fast responses, but we can't compromise on accuracy or getting the job done correctly. In early testing, Mercury 3 beat other models on latency while also performing higher on evals and in production.
Michael Gribben, Member of Technical Staff, Lorikeet
A real-time product portfolio
Mercury 3 is the flagship model in a widening portfolio of products that enable real-time AI.
Mercury Voice:
Mercury Voice is customized for the extreme low-latency requirements of voice applications and for minimizing time to first answer token (TTFAT), not just end-to-end latency. It’s already powering agents at Audivi AI, Altur, and OpenCall.
Mercury Decide:
Mercury Decide is a decision model built for high-volume classification. It outperforms Jev on benchmarks including JevBench and LegalBench.
Get started
Mercury 3 is available today on the Inception API Platform and through OpenRouter, Baseten, and Vercel. It is OpenAI API compatible, so it drops into your existing stack with no rewrites. Enterprise deployments support dedicated capacity, autoscaling, compliance controls, and configurable data retention.
You don't have permission to access "http://www.dailymail.com/news/article-16220441/Ukraine-carries-aerial-drone-evacuation-wounded-soldier-frontline.html" on this server.
Evidence is building the new standard for business intelligence, designed for a world
where humans and AI agents work together on analytics.
Today, Evidence is used by thousands of teams, from startups to Fortune 100 companies and
governments, often replacing tools like Tableau and Power BI. Our open source project has
7,000 GitHub stars and a large community of data professionals.
We’re backed by Y Combinator, SV Angel, A Capital, and founders of companies like dbt and
PagerDuty, with growing revenue and years of runway.
We’ve gotten here with a deliberately small team and an extremely high bar for the people
we hire. We believe exceptional engineers, amplified by increasingly capable AI agents,
can accomplish far more than was possible even a few years ago. We’re keeping that
philosophy as we grow, so the people who join now will have enormous influence over what
Evidence becomes.
How we work
We’re currently rethinking how we build software, moving toward a development process where
agents take on most of the software lifecycle. We believe it’s possible to automate almost
all of this work, freeing us to focus on the parts that require the most judgement,
creativity, and product thinking.
Our development process will change as AI improves, but our core principles remain the same:
We take care of our customers.
We’re exceptionally responsive and stay close to customers until their problems are solved. We probably take this further than is reasonable, and we like it that way.
We’re obsessed with product quality.
We care about the details and put a huge amount of effort into making our work look beautiful and feel smooth to use.
We move fast and finish things.
We bias toward action and care about getting useful things into users’ hands as soon as we can.
We avoid meetings.
The best work gets done when you have time and space to focus, so we try to make that our default work environment. We have one team meeting per week, and that’s it.
We’re data-driven.
We instrument almost everything, track the metrics that matter, and use data to understand what’s working.
We keep raising the bar.
We’re constantly looking for ways to improve our software development process, and expect everyone on the team to suggest and make improvements when they see them.
Alpha.
Mac.apk is early software under active development. Some apps run
beautifully, some run partially, and some do not run yet. It is stable enough to use
and interesting enough to explore, and it improves with every build.
What it is
Mac.apk runs Android apps directly on Apple Silicon. Apps launch as ordinary macOS
processes, draw through the Mac's GPU, and execute on the CPU at native speed. They
appear in your Dock, get their own windows with a back button next to the traffic
lights, resize and rotate like any Mac window, and switch between light and dark
along with your Mac.
There is no emulator here, and no virtual machine. Nothing boots Android in the
background, there is no Linux kernel running underneath, and nothing is interpreted
instruction-by-instruction. Mac.apk implements the Android application environment
on top of macOS directly.
How it works →
Any Apple Silicon Mac, including MacBook Neo. Intel Macs are not supported
Disk
~280 MB for Mac.apk. Each installed app takes roughly 1.5 to 3 times its APK size
Quick start
Download the disk image from the
Releases page
and drag
Mac.apk
into
Applications
. It is signed and notarized by Apple, so it opens
normally.
Open Mac.apk and click
Install
next to
Runtime:
in the top left.
Open
Settings
(the gear), find
File types
, click
Make Default
, and
approve the macOS prompt.
Double-click any
.apk
(or
.apkm
,
.xapk
,
.apks
,
.apkx
), or drag it onto
the Mac.apk window.
The first launch of any app is slow
(up to a minute for a large one) while
Mac.apk prepares it. Later launches are fast. Full details, updating, and the app
stores are in the
Installation
and
App stores
pages.
Warning
An Android app's saved data lives inside its own
.app
. Dragging the app to the
Trash deletes its saves; uninstall from the Mac.apk control panel instead.
More →
Send the Mac.apk version, your macOS version, the app and where you got it, what
happened, and the app's log from
~/Library/Logs/macapk/
to
Kaleb@voltare.us
or
open an issue
. Look the log over before posting it publicly.
What to include →
Source code
Everything that makes Mac.apk work is in this repository: the Android framework
reimplementation, the native runtime, the arm64 loader and Bionic shim, the ARM32
recompiler and the macOS app.
BUILDING.md
explains how to build it, and
CONTRIBUTING.md
how to send a fix. App reports are just as useful
as code.
Developers and publishers
Mac.apk serves no ads and supports no in-app purchases, by design. If you publish an
app that runs on Mac.apk and want to talk about a partnership, or would rather it
not run here, email
Kaleb@voltare.us
.
Details →
License
Mac.apk is
open source under the
GNU AGPL v3.0
, and a
commercial
license
is available for companies that want to ship or offer it without the AGPL's
terms. Using the official app is free. Details:
COMMERCIAL.md
. The
Mac.apk name and logo are covered separately in
TRADEMARKS.md
.
Disclaimer
Mac.apk is provided "as is", with no warranty of any kind. You are responsible for the
Android apps you choose to load, and Voltare cannot test, audit, or vouch for any
third-party APK. Voltare is not liable for damages, data loss, malware, security
incidents, copyright disputes, or any other consequence of code that runs through
Mac.apk.
Only install APKs you trust.
An Android app running under Mac.apk runs as ordinary
native code with your macOS user account's permissions. There is no phone-style app
sandbox around it: it can read and write your files the same way any Mac app you run
can. Treat an APK exactly as you would any program you download and run yourself, and
get it from a source you trust.
Third-party software
Mac.apk bundles several open-source components (ANGLE, MoltenVK and the Vulkan loader,
Capstone, libpng, libvpx, stb_vorbis, Bouncy Castle, a JRE built from OpenJDK together
with the libraries its font and image code uses, such as FreeType, HarfBuzz and GLib,
and the Android platform resources built from AOSP source). Each is used under its own
licence; the full notices are in
THIRD_PARTY_NOTICES.txt
,
and a copy ships inside the app at
Contents/Resources/THIRD_PARTY_NOTICES.txt
.
Two of them, GLib and GNU gettext's libintl, are licensed under the LGPL. Their
complete source for the exact versions in each release (upstream source, patches and
build recipe) is attached to that release on the
Releases page
, with
LGPL-SOURCE-README.txt
explaining how to use a modified build.
Today, we officially roll out
MiniMax M3.1 Flash
.
Space Bunny 🐰, which processed more than 200 trillion tokens while operating anonymously, was an early version of MiniMax M3.1 Flash.
As a next-generation Flash model, M3.1 Flash delivers a generational leap in agentic tasks, coding, Computer Use and cybersecurity, while making online inference nearly three times faster and reducing usage costs by 70%.
Stronger Capabilities Across the Board
M3.1 Flash improves across a broad range of benchmarks, reaching the level of leading models in complex agentic tasks (cowork), computer use, software development (coding), and cybersecurity.
Complex Tasks and Automation:
M3.1 Flash ranks among the top performers on AutomationBench-AA. It can complete real enterprise workflows across SaaS systems, solving practical problems in sales, marketing, operations, customer service, finance, and HR from end to end.
Scoring 76.2 on BankerToolBench, it excels at complex real-world challenges such as multi-step planning, maintaining consistency across documents and files, financial compliance, and chained tool calls.
Coding and Software Engineering:
It achieves 73.7% on DeepSWE v1.1, placing it alongside top models. DeepSWE focuses on complex software tasks that require models to independently understand code, develop features, fix issues, and validate their work through testing. M3.1 Flash demonstrates strong execution across long sequences of steps, supporting complex software development workflows at a lower cost.
Computer Use:
It scores 61.7 points on OSWorld V2, which measures AI computer operation and cross-application task execution, and 29.6 points on Agents’ Last Exam (ALE), which evaluates performance on real professional work and complex tasks. It ranks first among Chinese models on both benchmarks.
M3.1 Flash demonstrates strong capabilities in interacting with real environments, using tools, and executing long sequences of tasks—moving beyond understanding a task to taking action and delivering results.
Cybersecurity:
It achieves a strong score of 82% on CyberGym, demonstrating leading capabilities in vulnerability discovery and validation.
In in-depth evaluations by our internal security experts, the model performed strongly in code auditing, vulnerability patching, penetration testing, malware analysis, and reverse engineering, enabling efficient, low-cost support for building complex security systems.
We have further optimized M3.1 Flash’s inference efficiency through more aggressive sparsity. In everyday use, output speeds can reach 200+ TPS (tokens per second), with median (P50) speeds consistently reaching 170+ TPS.
Pricing: Most Cost-Effective
For agentic tasks, the model’s overall usage cost is 70% lower than its predecessor.
Across three benchmarks—Automation-Bench for complex agentic task execution, DeepSWE for real-world coding, and Agents’ Last Exam (ALE) for computer use in real-world tasks with economic value—M3.1 Flash delivers performance on par with top models at a very low task cost, setting a highly competitive new standard for performance and cost.
M3.1 Flash is now available through the MiniMax API, M Plan, and MiniMax Code. Model weights will be released later.
Flash represents our ongoing exploration of the balance between efficiency and capability. Pro, which pushes the boundaries of intelligence, will also arrive later.
Intelligence with Everyone.
I no longer care to work on any Ruby gems so I've archived all my repositories
I’ve decided to archive the source code of my Ruby gems to make it clear
that I’m no longer working on them; I’ve written this post to link from them in
order to explain why.
For me, the purpose of life is, at least partly, to have joy. Programmers
often feel joy when they can concentrate on the creative side of programming,
so Ruby is designed to make programmers happy.
It was during that era, when Ruby was ostensibly for joy, for creativity, for
humans, that I developed this code. But that age, of doing things for humans,
has passed, and with it my enthusiasm for working on Ruby gems. I won’t say it
was always great, but at least we were working with and for people.
The pre-eminent application of Ruby has been making web applications
using Rails. Rails is open source software but it’s owned and controlled by
a
man whose views I find abhorrent
, although there is an
ongoing
effort
to fork it.
To judge by his
keynote
at Rails World this year – the conference that he
himself set up in pique after he wasn’t invited to RailsConf a couple of years
ago – he is no longer particularly interested in Ruby, Rails, or even
programming itself.
(He’s now using LLM agents to churn out apps in Rust, a language which he
compares to “pouring acid into [his] eyes”, but that’s apparently fine because
he doesn’t even look at what they generate.)
But even beyond Rails, the Ruby language itself is now
substantially
developed using LLM agents
. Matz is giving talks repositioning Ruby
as a
“Programming Language for AI age”
, to be emitted by LLM agents,
and stating that to be able to do that LLMs need to consume more good
human-written Ruby code. You might already have seen the problem here.
In that context, I no longer feel inspired to contribute to a commons that’s
being strip-mined by massive corporations to feed the very machines whose
unthinking output pollutes it.
When people claim that it’s no longer sustainable to write code by hand,
they’re not
entirely
wrong, but only in the same way that it’s no longer
sustainable to sleep in a bed once someone has taken a shit in it.
You want changes? Go ask your agent or something. I’m told that’s what you’re
supposed to do now. I’m out.
Netflix Lays Off 6 Percent of Staff
Daring Fireball
www.wsj.com
2026-10-19 12:32:06
Joe Flint and Jessica Toonkel, reporting for The Wall Street Journal last week:
Netflix is cutting 6% of its staff, or roughly 1,000 positions
globally, its biggest round of layoffs since 2022, as it struggles
with slowing growth and customer engagement. Co-Chief Executives
Greg Peters and Ted S...
Like many others in the free software community, I've been been growing
apathetic with the whole thing, lately. One project after the other - and one
Linux distro after the other - embrace the proprietary world destroying
plagiarism machine. I've been questioning the point of it all. Why make the
effort of writing software, and publishing it, only for huge corporations to
gobble it up, while blatantly ignoring the license?
I felt Debian's embrace of it the worst. To me it has been a community-focused
constant. Until it wasn't. That isn't to say I feel Debian owes me anything.
They don't. But it still made me sad.
But I still like computers. Coding and tinkering is fun. Unix-like systems are
where I feel comfortable. But, if possible, I'd like to use something that
aligns more with my values than my previous go-to, Debian, does.
It's not just their firm focus on community that makes Chimera interesting,
though. They've also got a tech stack that deviates from mainstream Linux.
Chimera uses
musl
, not glibc, it uses a
FreeBSD-derived userspace, not GNU coreutils, and it uses
dinit
, not systemd.
The latter, not using systemd, required a bit of research. Not because it's a
bad choice, but because some of the discourse among non-systemd-users is
frankly bizarre. But Chimera has my back here too. Chimera «is explicitly
not a part of this community».
I was sold, and quickly installed Chimera. Suddenly I was back to when I
discovered Linux in the early 2000's, poking around something new and fresh.
This time I knew my way around, but a new init and service manager, the
FreeBSD-based userspace and new-to-me apk-package manager meant I had to learn
some new tricks. It's loads of fun.
Making it easy to contribute
One thing that stood out
in the blog post I
was
«[…]Every user can be a maintainer. It shouldn't be unnecessarily intimidating.
We don't gatekeep here when possible. You should also be having fun using the
system and being here.».
The barrier to entry for contributing to many Linux distributions these days is
pretty high. Chimera makes it an explicit goal to make contributing easy - and
I'd say they've succeeded. The packaging tools, and the format you write
packages in, are both easy to learn and easy to use. As of writing, I've got
one new package and one update accepted into «cports», Chimera's package
repository.
More importantly, I made mistakes when contributing, and I was met with advice
and suggestions on how to improve, not with hostility or rejection. What I
first tried to submit wasn't good enough, but I was given a chance to improve -
and I did.
This welcoming, friendly atmosphere, in my experience, extends to the rest of
the community. I've been talking and asking questions in the
#chimera-linux
IRC channel on OFTC
. People
were more than happy to lend me a hand, give me hints and even just chat.
But, Eskild, you're still running LLM-generated code
I am. There's LLM code in projects upstream from Chimera, perhaps most notably
the Linux kernel. It's impossible to avoid it at this point, and still be left
with a usable system. I still think there's value in a project taking a stand,
as much as it can, and I think there's also value in non-LLM forks like
vim-classic
and
opentmux
. I'm happy to be in a
community of builders that take a stand.
There are others
If you think this sounds interesting, I urge you to try out
Chimera
Linux
. That said, it's not alone, even though many
of the largest Linux distributions, and *BSDs, are embracing LLMs.
Elementary
OS
,
Gentoo Linux
,
Asahi
Linux
and
Nura
on the Linux
side, and
NetBSD
on the BSD side, are also options.
Time Magazine Profiles John Ternus
Daring Fireball
time.com
2026-10-19 12:17:14
Andrew Chow, writing for Time:
Just below the broad smile he’s been wearing all morning, John
Ternus’ hands are shaking.
On this September day in Silicon Valley, Apple’s new CEO is
surrounded by celebrities, tech enthusiasts, and reporters who
have flocked to Apple Park from around the world to...
Just below the broad smile he’s been wearing all morning, John Ternus’ hands are shaking.
On this September day in Silicon Valley, Apple’s new CEO is surrounded by celebrities, tech enthusiasts, and reporters who have flocked to Apple Park from around the world to catch a glimpse of the company’s new and long-awaited foldable phone, the Duo. After Ternus takes a few photos with the device, an Apple PR rep pulls the influencer known as
IShowSpeed
out of the crowd to meet him. Winning over the 21-year-old isn’t exactly the toughest assignment Ternus has faced in his 25-year Apple career: Speed barks when he
sees the phone
and then gleefully springs into a backflip.
But IShowSpeed also happens to be livestreaming the encounter to his 61 million subscribers on YouTube. And as Ternus thumbs through the $1,999-and-up phone, attempting to drag a photo into a text-message box, eagle-eyed viewers notice his hands quivering. Ternus later explains that he didn’t sleep much the night before. “I was on such a moment of adrenaline and caffeine and excitement for the day,” he tells TIME.
Ternus, who took over as CEO on Sept. 1, was chosen to run Apple because he has ably applied his engineering and design expertise to shape products that redefined entire categories of technology, from the Mac to iPad to AirPods and the iPhone. But becoming the face and front man for the second biggest company in the world by market cap is another proposition entirely. Ternus’ hard technical skills may not translate easily to a position that involves toggling from Hollywood to stockholders, to politicians shaping policy, to rival CEOs in the constellation of tech companies whose power challenges nation-states.
The recently unveiled iPhone Duo.
APPLE
His predecessor, Tim Cook, gained stature on the world stage as a power broker deftly navigating global politics, markets, and supply chains. Cook’s predecessor, Steve Jobs, was a rock-star visionary who sold the world on the deeply personal and even spiritual nature of tech creations. Ternus is different from both: a private, detail-oriented engineer, little known outside the company until he became a senior hardware executive in 2021.
Rather than try to replicate his forerunners’ styles of success, Ternus has so far played to his own strengths—which are also those of Apple, a company that first and foremost builds beautiful products that spark productivity, creativity, and joy. Ternus’ interaction with IShowSpeed is clearly designed to capture this (and, of course, to goose preorder numbers among the influencer’s young and massive audience). To some critics, however, the scene might read as a legacy company aura-farming to sell expensive gizmos instead of building the actual technological future, which is artificial intelligence.
Virtually every one of Apple’s fellow Goliaths—Microsoft, Google, Meta, Amazon, and now Nvidia, OpenAI, and Anthropic—have flung themselves into the AI arms race, pouring hundreds of billions of dollars into training ever more intelligent thinking machines. While Apple trains its own models, it is nowhere near the technology’s frontier, leaving the company vulnerable to being left behind if super-smart AI transforms industry and society in the coming years. At the end of September, Apple was conspicuously absent when President Donald Trump
hosted a luncheon
for AI power players like SpaceX’s Elon Musk, Meta’s Mark Zuckerberg, and Google’s
Sundar Pichai
, who lobbied him on their visions for America’s tech future.
But Ternus and other Apple executives say they aren’t concerned. In the midst of a
populist AI backlash
, they contend that they are building a modest but personalized and privacy-preserving form of AI that will actually help ordinary people as opposed to merely dazzling Silicon Valley’s “lunatic fringe,” as Greg Joswiak, senior vice president of worldwide marketing, puts it. And besides, Ternus argues, even if other companies succeed in their mission of building super-intelligence, users will still want to talk to it on Apple devices.
“People want physical things,” he says a week later at the company’s flagship store on Fifth Avenue in New York City, wearing an amiable but guarded smile. He spent the morning greeting superfans who had lined up all night to get their hands on the iPhone 18. “They want to talk, to see images of loved ones, to take pictures. So I don’t see a scenario where all of a sudden, our devices disappear and we don’t have a need for an iPhone.”
Ternus is barely older
than the company he’s running. Born in 1975 in Orange County—Apple was founded in ’76, just 400 miles north—he grew up as Steve Jobs was redefining the personal computer as a societal force. When Ternus was 8 years old, his father bought an Apple II. “I started playing games on it and fell in love with Apple,” he says. A decade later, he took his family’s newer Mac, an SE model, to college at the University of Pennsylvania, where he studied mechanical engineering.
In 2001, Ternus left a virtual reality company to join Apple at 26 as an engineer. He has now spent half his life at the company, rising through the ranks on his propensity to consider both how products are made and how the user will experience them. “John was really at the center of driving the spirit of collaboration across the company to make sure that end-to-end these products give you that delightful experience—and the technology kind of disappears as you’re using it,” says Richard Dinh, Apple’s vice president of product design.
Over the past 15 years, some critics have accused Apple of failing to innovate the way it did in previous eras, when the company popularized the home computer, the MP3 player, and the smartphone. But it is undeniable that Apple’s core products—its computers and phones—have remained elite thanks to behind-the-scenes innovations in hardware and software. And Ternus, Apple executives say, has been a big part of these improvements.
When Cook, 65, announced in April he would step down following a 15-year tenure, it was no surprise that the company tapped Ternus as his successor. Other executives describe him as pragmatic, meticulous, and unifying. “Ternus is a logical pick,” says Neil Cybart, an analyst who has been following Apple for more than a decade on his site Above Avalon. “He has been a big believer in this design-first culture that defines Apple, as well as the idea that it’s not just technology here; there needs to be something more.”
In the late 2010s, Apple executives shifted their messaging to focus more on fast-growing services like iCloud, the App Store, and Apple Music. But growth in service revenue has moderated this year, and the promotion of Ternus, a hardware and product guru, signals a return to the company’s roots.
So it’s fitting that his ascension coincided with the announcement of the Duo, Apple’s most radical design change to the iPhone since its 2007 release. Apple has been exploring the concept for years. In 2011, when many people still carried around flip phones, Ternus and five other engineers
filed a patent
application for foldable electronic devices, exploring what kind of batteries and circuit boards might be needed for such an idea. “It felt clear that we were going to eventually get to a place where OLED displays were going to be flexible,” Ternus says.
Photograph by Devin Oktar Yalkin for TIME
Many challenges stood in between the patent and the final product. The first attempts at a foldable smartphone in the 2010s from other companies tended to be fragile and not all that useful, with a big, ugly crease in the center interrupting the experience. “The other examples in the world felt kind of cheap and crappy,” Ternus says.
Across hardware and software teams, Apple engineers and designers got to work. With advancements in Apple silicon chips, they created a new display engine that facilitates seamless transitions between the inner and outer screens. They redesigned iOS to move the phone’s main controls from the bottom to the right side for easier thumb access.
Along the way, Ternus encouraged the team to invest more time and effort in the project, even as other foldables beat them to market. Dinh says that at one point, he asked Ternus whether his team should proceed with a top surface material similar to those of its competitors, which Dinh felt had flaws but was potentially good enough.
“And he was like, ‘Look, Rich, you’ll know when it’s the right thing.’ And that gave us the confidence to really push the boundaries on innovation and manufacturing, and fly worldwide to connect our suppliers together and come up with the nanotexture [a surface technology],” Dinh says. The result—a surface made from a custom polymer and built atop a hinge with more than 100 tiny interior precision components—has impressed its first users, who have said they can barely detect a crease at all.
Ultimately, the Duo promises a passport-size phone that opens into a powerful tablet. Users can stow it in their pockets, then open it up and watch a movie on its matte, light-deflecting surface. They can compare websites side by side, play touchscreen games with intricate detail, and use a dual-camera setup to simultaneously show themselves and what they’re seeing on FaceTime.
Of course, the Duo’s success is far from guaranteed. It could go the way of Apple flops like the Apple Car, which was never released, or the Vision Pro, which had staggeringly low sales in the last year. Certainly many prospective buyers will blanch at the device’s $2,000-plus price tag.
The opening motion of the hinge on Apple's newest invention, the iPhone Duo.
HAW-LIN SERVICES
A look inside the iPhone Duo's internal structure.
HAW-LIN SERVICES
But the phone’s first public testers have given
glowing feedback
. And demand for the Duo’s closest rival, Samsung’s Galaxy Z Fold8, has been strong, suggesting there is a growing appetite for the foldables category, especially in Asia.
Apple also hopes that the Duo will earn a cultural cachet among storytellers and other artists, many of whom, like loyal Apple customers, still regard the company more as a maker of useful tools rather than as the enemy Big Tech has become. Four-time Oscar winner Sean Baker
(Anora)
,
who spoke at a
“no-AI” film festival
earlier this year, attended the Duo announcement in Cupertino and described his relationship with Apple as collaborative. “It’s not just ‘buy or use our product’—it’s much more of a working relationship where they stay in touch and ask us for feedback,” he says.
Baker noted that Apple’s products often underpin many parts of the filmmaking process. For instance, when moviemakers need to add dialogue in postproduction, they often simply record on an iPhone, because it’s convenient and nearly production-grade.
In person, Ternus presents as a guy trying to blend in: he dresses in nondescript clothes and speaks in platitudes, often about the brilliance of Apple’s internal culture. He has devoted much of his early tenure as CEO to obsessing over design, spending multiple days a week in the studio with the industrial-design and human-interface teams.
But beyond Apple Park’s gleaming, curved walls, Ternus has tough choices to make. Case in point: the ongoing global shortage of memory chips, which has raised costs and delayed production timelines. In July, the
Financial Times
reported that Apple had begun testing memory chips made by a Chinese company as a way to increase supply. That drew a swift rebuke from a bipartisan group of Senators,
who wrote
a letter to Apple arguing that to do so would imperil national security.
Ternus pushes back on that idea. “The constraints in memory are absolutely a crisis,” he tells TIME in the second of two interviews during September. “So our fundamental belief is that all options should be on the table.”
Cook was skilled at managing relationships with governments around the world, vigorously defending Apple’s interests even if it made him a target of ridicule. His courtship of Trump, which included a widely maligned presentation of a disc with a 24-karat gold base at the White House in 2025, helped Apple secure relief from some of the Administration’s most punishing proposed levies.
Ternus is tight-lipped about how his approach to government affairs might differ from Cook’s. He says that he’s met with members of the Trump Administration to “make sure we’re kind of working through things together.” But as Ternus transitions into the role, Cook has continued to represent Apple on the world stage, meeting with Australian Prime Minister Anthony Albanese, European Commission President Ursula von der Leyen, and
then attending
President Trump’s state dinner for Xi Jinping.
“He has great relationships and loves Apple,” Ternus says of Cook, who is staying on as Apple’s executive chairman. “So wherever he can help, he is happy to help.”
Big Tech has been hammered by lawsuits, public campaigns, and regulation over the past few years from critics who feel that screens have poisoned the cognitive development of an entire generation. From Australia and the U.K. to California and New York, governments have restricted children’s social media and AI use and phones in schools, while pressuring Apple and Google to build stronger protections into their devices.
Apple has traditionally framed many of these harms as arising from particular apps and content. But the company rolled out a redesigned Screen Time experience in September to give parents greater control over their children’s app access. Ternus pledges that child safety will be central to Apple’s approach going forward. He says that in the past, he used Apple’s Screen Time to monitor his kids’ device usage, and that it was “good but not great.” The company’s new updates, he says, stem from a desire “to build tools that make that really easy for parents—and I think we’ve done just that.”
Questions around geopolitical tensions, supply chains, and child safety only become more urgent as Apple wades into its next frontier: artificial intelligence.
Since the rise of ChatGPT in November 2022, the generative AI boom has unfolded with Apple largely sitting on the sidelines. OpenAI brought AI chatbots to the masses; Nvidia built the chips powering them. Microsoft, Google, Meta, Amazon, Anthropic, and SpaceX now all either compete at the technology’s frontier or are printing revenue from a key part of its supply chain.
Apple CEO John Ternus and Deirdre O'brien, Vice President of Retail, open the Apple store on Fifth Avenue for Apple's launch of the iPhone 18 Pro, Friday, Sept. 18, 2026, in New York.
Angelina Katsanis—AP Photo
Apple, in contrast, did not unveil Apple Intelligence until June 2024—18 months after ChatGPT’s release—and then spent more than two years struggling to deliver the personalized version of Siri it had promised. In 2025, realizing the existing Siri couldn’t grow into the AI era, the company scrapped it in favor of another version that had been two-tracked. The resulting new Siri, which launched in the U.S. in September, is powered by an Apple AI model that leverages Google’s Gemini technology. This arrangement puts Apple in an unusual position: reliant on a rival for a key building block of its products. This sort of outsourcing famously angered Jobs, who went to
great lengths
to own the “whole widget,” from hardware to software to services.
But Ternus rejects the idea that its AI strategy represents a retreat from that philosophy. After all, Apple relies on suppliers for many of its components, including screens, memory, and modems. “There’s not really a goal that we have to make every single thing in a product,” he says. “We make the things where we can really bring differentiation.”
Apple has said that AI is core to the company’s focus, and that it has significantly increased its investments in AI. The company also argues that the usefulness of AI comes less from its underlying raw power than what surrounds it—the chip it runs on, the operating system it inhabits, and the knowledge it has gathered about its user. The new Siri cannot code like OpenAI’s Codex or write as elegantly as Anthropic’s Claude. But with a user’s permission, it can draw connections across messages, emails, calendars, documents, and other information stored on Apple devices. It is designed to help prepare someone for a meeting, find a flight confirmation buried in an inbox, or help interpret health data collected by an Apple Watch.
“Everything in your life is on your phone,” Ternus says. “With Siri AI, you can leverage all that information to do things, learn things, and figure out things in a way that nobody else can do.”
Cybart, the analyst, argues that Apple has seen this kind of competition before. “People tend to think that if someone else does great, that must mean Apple has a problem, like in music or television streaming,” he says. “But how do you access Spotify or Netflix? When other companies do great things, that doesn’t change the fundamental story with Apple in terms of having the ecosystem that people want to be in.”
And Apple executives argue that some of Siri’s limitations are actually strengths. For instance, Siri’s lack of thinking power compared with other ultra-smart AI agents means that there’s far less of a chance of going rogue, or behaving in eerie ways. “We’ve purposely designed it not to be a companion, and we don’t want to replace human connection,” says Lilian Rincon, who leads Apple’s AI product efforts.
Privacy is another advantage Apple executives stress. The company has a decades-long reputation for protecting user data more aggressively than its competitors. Siri processes requests on-device where possible, and more computationally demanding asks are sent to Private Cloud Compute. Apple’s system of servers is designed so that queries are not stored or made available to the company. Apple has also made portions of that system inspectable by independent security researchers, some of whom have praised
Apple’s approach
while noting limits to its transparency.
Some investors are already treating Apple
as a hedge
against the other AI companies dominating the Nasdaq; if those companies wobble, Apple could be the big stock-market winner. Conversely, if AI progress continues apace, smaller but capable models could soon become able to run cheaply on devices built to handle them. In this future, the scarce asset would be not the chatbot, but the device, operating system, and personal context through which the chatbot becomes useful. And Apple has built a significant moat in the form of loyal customers across the world.
This thesis was already borne out earlier this year, when a wave of AI enthusiasts
bought Mac Minis
in order to set up personal AI agents through the open-source project OpenClaw.
While Apple had nothing to do with the project, users quickly figured out that the energy-efficient Apple silicon, compact form, and unified memory of the $600 computers allowed them to run AI workloads locally, continuously, and for minimal electricity costs. This spike in demand caused some Mac Mini models to be
unavailable for months
.
More AI-oriented hardware products are on the way. On Oct. 13, Apple announced a new
smart-home hub
called the HomeView, powered by Apple intelligence. Bloomberg also reported the company is readying
smart glasses
for 2027; the company declined to comment.
But Apple will soon face more competition in the hardware space. Last year, OpenAI acquired the startup of Jony Ive, Apple’s longtime chief design officer, who is now building AI-first devices for the ChatGPT maker alongside several other prominent former Apple veterans. In July, Apple sued OpenAI in federal court, alleging the theft of hardware trade secrets. (OpenAI calls the lawsuit “baseless.”)
Despite the lawsuit, Apple executives say they’re not worried about the newfound rivals. After all, Apple devices have never been more popular. With 2.5 billion active devices, the company rakes in nearly half a trillion dollars in annual revenue. And when new users convert to Apple, they tend to stick around. “We don’t feel threatened,” says Joswiak, the longtime executive. “The fact that we can do the integration that we can means we can create just a better experience than anybody else.”
Joswiak adds that Apple isn’t making products for the die-hard AI believers chasing superintelligence. “We love them, and they can use it too, but that’s not our target,” he says. “It’s how to make it better for everyday people.”
On Sept. 18, lines formed outside Apple stores from Hangzhou to London to Mumbai, with scores of those “everyday people” spending hundreds of their hard-earned dollars on the newest iPhone. Ternus, as Tim Cook and Steve Jobs did before him, showed up to the Fifth Avenue store to take pictures with superfans, who treated him like a movie star. Most of them probably didn’t know much about Ternus himself. But they didn’t need to, because they saw him -reflected through devices that had become omnipresent in their lives.
AI may yet be a part of their lives too. But no one knows the future—and at present, handheld devices are still king. “You can’t do everything,” Ternus says. “So we kind of try to constrain ourselves to the stuff that matters most—and then put all of our effort into those things.”
Police Say Scammers Used AI to Clone a Sheriff’s Voice
403 Media
www.404media.co
2026-10-19 12:16:17
The scammers used the voice of a specific sheriff to impersonate him....
A Florida police department claims that scammers used AI to clone a sheriff’s voice, with scammers increasingly using voice clones that trick people into thinking they’ve missed jury duty or have a warrant out for their arrest are increasing.
“They cloned his voice and was using Steve’s picture as well to say it was him making the phone call, and it was not,” Sheriff Chris Blackmon told News6.
💡
Have you been the target of deepfake video or AI voice cloning scams? I would love to hear from you. Using a non-work device, you can message me securely on Signal at sam.404. Otherwise, send me an email at sam@404media.co.
Impersonating a police officer is a third-degree felony in Florida. The Osceola County sheriff’s office did not immediately respond to a request for comment.
This particular scam cloning cops is spreading across several states, with reports of jury duty and arrest warrant scams targeting people
in Georgia
and
Pennsylvania
in the last week. These other reports don’t mention AI voice cloning explicitly, but note that the scammers sometimes have similar voices and tones as local police officers.
Voice cloning scams have been around for years, with scammers using commercially available AI voice impersonation tools to target
the elderly
, families, and businesses. Last year,
404 Media investigated
real-time deepfake scams that incorporated voice and video to defraud people.
In 2024, we reported
on the ways scammers cloned celebrity voices and use AI videos in YouTube ads to scam people.
Scammers often impersonate company executives or leadership to trick employees into sending money, and voice cloning appears to be an increasing part of that. In February, scammers cloned a managing partner of a law firm with AI. Ultimately, a
private bank ended up transferring
$108 million.
About the author
Sam Cole is writing from the far reaches of the internet, about sexuality, the adult industry, online culture, and AI. She's the author of How Sex Changed the Internet and the Internet Changed Sex.
Koiranpennuilla on 3–12 viikon iässä herkkyyskausi, jolloin niiden on helppo tutustua erilaisiin ympäristöihin. Ylen pentuliven pennut vierailivat päiväkodissa Laukaassa.
Free Tracker Blocker Used by Millions Will Protect Even More Users' PrivacySAN FRANCISCO—Privacy Badger, the award-winning tracker blocker made by the member-supported digital rights nonprofit Electronic Frontier Foundation (EFF), is now available for Safari on macOS.
Safari users can downloa...
SAN FRANCISCO—Privacy Badger, the
award-winning
tracker blocker made by the member-supported digital rights nonprofit
Electronic Frontier Foundation
(EFF), is now available for Safari on macOS.
Safari users can
download the free browser extension
today and join the more than 4 million people using Privacy Badger to take a stand against data brokers and online surveillance. Users will need Safari version 26.5 or higher to use it.
Ranked as one of the best ad tracker blockers by
The Wirecutter
,
Consumer Reports
,
PC Mag
and more, Privacy Badger is different from other blocking extensions. Created by EFF to stop companies from spying on you online, Privacy Badger
automatically learns
to block hidden trackers on the web, along with additional privacy-protecting features.
"Most websites contain invisible tracking code that lets companies collect, share, and profit from your personal data," said Lena Cohen, Staff Technologist at EFF. "Creepy ads are just the tip of the iceberg when it comes to the harms of online tracking: Once your information
enters the data broker ecosystem
, it’s nearly impossible to know who buys it or what they’re doing with it. Safari support has long been one of Privacy Badger’s most requested features and EFF is excited to be able to make this important tool available to Safari users to fight back for a better web."
On Safari, Privacy Badger goes beyond the browser’s
built-in privacy features
to provide additional protection against online tracking. In its default browsing mode, Safari limits the information that trackers can access, but it still allows them to load. Privacy Badger blocks online trackers from loading in the first place, preventing them from tracking you using
techniques
that bypass Safari’s protections.
With today's launch, Privacy Badger
is now available
on all major desktop browsers.
As the leading nonprofit defending online civil liberties, EFF is committed to fighting mass surveillance in the courts, through activism, and by making free, privacy-protecting tools like Privacy Badger. Now, even more people can join the movement against online tracking, by installing Privacy Badger themselves, telling their friends and family who use Safari about it, or
by supporting Privacy Badger today
.
Hi HN, we’re Robert and Din from Laminar (
https://laminar.sh
). We’ve been building open-source observability for AI agents since 2024. Recently, we released flow-1, a model trained with RL to find errors in agent traces. On our benchmark (
https://laminar.sh/blog/flow-1
), it matches GPT-6-sol in detection quality while being 23x cheaper. This makes it affordable to analyze every production agent trace, without sampling.
Agent observability is crowded, so instead of a bullet list of how Laminar differs from X, we’ll explain how we’re solving agent observability from first principles.
Agents now run for many steps and fail implicitly. An agent can click the wrong button or cite the wrong document while every call completes successfully. These errors are the most useful ones to catch and understand. To find them, you need to understand what the agent was trying to do and inspect its LLM calls and tool results. Simply looking at the final agent output is not enough.
Collecting traces alone doesn’t solve this. A lot of agent observability platforms are still data collectors at their core. You can end up paying to store traces that nobody has time to read or extract value from.
Using another LLM to inspect traces is THE solution, but capable models are expensive at scale and cheaper ones often miss errors or flag unrelated things.
So we built our model to solve exactly this problem. We finetuned a small OSS model and then post trained it with RL on thousands of synthetic investigations of realistic agent workflows in software, legal, customer support, etc. We got a model that is both good at agent trace analysis and very cheap to run.
flow-1 runs inside a harness we call Signals. It acts as a coding agent, treating an agent trace like a repo, with each span (an LLM call, tool call, etc.) as a file. It starts from a compressed string representation of a full agent trace and a user prompt, then greps across spans and reads the relevant ones in full.
The beauty of Signals is that it can respond to a general prompt. You can ask it to identify user frustration, check whether your browser agent completed a checkout, and so on. It’s not limited to raw error detection. It returns findings as JSON in a schema users can freely define. We call these signal events.
Once you’re analyzing every trace, you also have too many individual events to read. That’s why we automatically group similar signal events into clusters. You can see recurring problems and how often they happen, then drill into individual events and the traces behind them.
You can use traces from a cluster to build an eval dataset for that type of failure. You can then use your favourite coding agent to hillclimb on those evals and check that the fix works across these cases before shipping it to prod.
Trace → analyze → catch errors and form clusters → fix → release. Making this loop easy is why we built Laminar.
We’ve put the same thought into the rest of Laminar. Our blog (
https://laminar.sh/blog
) explains how looking closely at how agents actually work led us to build 20x trace compression, a custom SQL query engine and automatic task extraction.
We’d love to hear how you track your agents’ performance today. How much do you learn from user feedback versus your own monitoring? And when you fix something, how do you check that it hasn’t introduced a different failure?
This incident has been resolved. Thank you for your patience and understanding as we addressed this issue. A detailed root cause analysis will be shared as soon as it is available.
Posted
Oct
19
,
2026
-
16:56
UTC
Monitoring
Actions, Pages and Webhooks are operating normally.
Posted
Oct
19
,
2026
-
16:56
UTC
Update
We’re seeing recovery following mitigation and are continuing to monitor.
Customers may still experience delays in GitHub Actions workflow status updates, GitHub Pages deployments, and check and workflow webhook events generated by Actions runs.
Posted
Oct
19
,
2026
-
16:30
UTC
Update
We’re are currently investigating degraded availability affecting GitHub Actions, GitHub Pages and Webhooks.
Customers may experience delays in workflow processing, site builds and webhook delivery.
Posted
Oct
19
,
2026
-
15:56
UTC
Update
Webhooks is experiencing degraded performance. We are continuing to investigate.
Posted
Oct
19
,
2026
-
15:50
UTC
Investigating
We are investigating reports of degraded performance for Actions and Pages
Posted
Oct
19
,
2026
-
15:49
UTC
This incident affected: Webhooks, Actions, and Pages.
Note: as always, all my public writing is written by hand by me.
Overview
A
bloom filter
is a probabilistic data structure that allows you to quickly and cheaply answer the question
"is key X in this set?"
with either
"definitely not"
or
"probably"
.
You pick a false positive rate that is acceptable for your workload and hardware, add keys to the set, and check for their existence later on.
Bloom filters use a small amount of memory compared to the cardinality of the set, and are computationally very cheap. For these reasons, they're frequently used in high performance data systems.
For example, a database might keep an in-memory bloom filter and check it before actually going to disk when looking up rows. This saves substantial amounts of very slow disk IO.
We also use them all over the place in the
Bluesky
backend. They allow us to save
millions
of queries per second against our Scylla database when looking up blocks, mutes, labels, and more. For instance, we can often answer the question
"does user X block user Y"
without even hitting the database.
Here's the last several days of some of our bloom filter positive hit rates:
The above yellow line has a roughly 1% positive rate, which means that 99% of the time, we can completely skip querying our database. This has been critical in our ability to scale the site and operate the site cheaply.
Traditional Bloom Filters
A bloom filter is an array of bits and
k
hash functions. You choose the size of the array and
k
before hand, and want to right-size it to your workload to achieve a specific false positive rate.
To add a key to the set, run it through the
k
hash functions and set the bits at each of those locations.
To check if a a key is in the set, hash it
k
times and check each resulting location in the bit array. If any bits are zero, the key was never added. If all bits are set to one, it might be in the set.
Here's an example of a potential positive:
And a definite negative:
Pretty simple!
Double Hashing
While
much
cheaper than going to disk, computing
k
independent hashes per key is still a bit expensive for very high performance systems.
In 2008, Kirsch and Mitzenmacher wrote a
paper
demonstrating that two hashes can get you the same output. The math is far over my head, but if you derive the
i
-th location as
(hash_1 + i*hash_2) % n
, then the false positive rate is effectively the same as using
k
independent hashes. Phew!
bits-and-blooms/bloom
maintained by
Daniel Lemire
(a huge inspiration of mine, you should buy his
book
) is a fantastic double hash bloom filter implementation written in go. It runs 128-bit murmur3 twice to get four 64-bit values, then combines them to produce all
k
bit locations. We used this in production at Bluesky for a long time.
For the Bluesky backend, we essentially do a
SELECT * FROM blocks
, mutes, list items, etc. every time one the processes starts, and add all the items to the bloom filter. There's also a real time
atproto
firehose consumer inserting items in to bloom filters (even during process startup), so there is a race condition if you're not careful.
The problem with the
bits-and-blooms
library is that it's not internally thread-safe, so we needed to wrap all bloom filter access in a
mutex
lest we suffer a data race.
pprof
showed that mutex contention was actually the bottleneck in launching the process. A single deploy used to take 90 minutes to roll out fully because of this!
So my colleague
Jasmine
forked the library and created
atomic-bloom
, which uses
atomic
CPU instructions to do the same logic, but safely and without mutexes. This led to substantially less contention and was massively faster than the mutex-based approach. Our deploys dropped from 90 minutes to about 15, which enabled us to ship faster and with greater confidence. Awesome!
One Hash
Can we go further?
For Bluesky, the answer is
no
. Contention was our original problem, not the number of hash functions or other factors, thus by
Amdahl's Law
we did not receive any further speedup resulting in a noticeable impact. However, it's still fun to go deeper and learn something new!
As part of our research on bloom filter techniques, we came across
this paper
from Lu et al. that uses
even more math
to show how to do bloom filters using only a single hash.
Here's an overview of how it works:
Instead of one big bit array, split that into
k
array partitions of fixed sizes
Each partition has a different size, and all the sizes are
pairwise coprime
, meaning that no two sizes share a common factor other than one
You hash the given key once to get
hash
The bit position in partition
p
is
hash%size_p
(the size of the partition)
Since you have
k
partitions, you get
k
bit positions to check out of that single hash
You can use those
k
bit positions as you would with other bloom filter types!
With this technique in hand, I made
jcalabro/gloom
, a one-hash bloom filter (OHBF) implementation in go. This has been live in the Bluesky backend for the past 9 months and has been holding up quite well. It's also used in
jetstream
, our high performance sync service.
Here's an example of how it's used:
package main
import (
"fmt"
"sync"
"github.com/jcalabro/gloom"
)
func main() {
// Create a thread-safe atomic bloom filter with:
// - Expected capacity of 1 million items
// - Approximate false positive rate of 1%
f := gloom.NewAtomic(1_000_000, 0.01)
var wg sync.WaitGroup
defer wg.Wait()
for i := range 8 {
wg.Go(func() {
for j := range 100000 {
str := fmt.Sprintf("key-%d-%d", i, j)
if f.TestString(str) {
// always a false positive since the key isn't in the set
fmt.Printf("found a false positive: %s\n", str)
}
f.AddString(str)
}
})
}
}
Now, let's step through how it works under the hood in more detail. Here's some sample go code that shows how we select the block index as well as
h
for a given key we want to check:
hash := xxh3.Hash128(key) // calculate the 128-bit hash
block := hash.Hi % numBlocks // high 64 bits pick the block
h := hash.Lo // low 64 bits are the hash we'll check
Then, you check your bloom filter as follows:
In addition to being a single hash, it also does some fun performance optimization techniques.
First, we split the bloom filter into many 64-byte blocks to match common CPU cache line size. Next, since go's allocator doesn't ensure that those block allocations are
cache aligned
, we slightly over-allocate and use
unsafe
to ensure alignment.
See here
for the implementation.
These two techniques combined guarantee that in the worst case, a bloom filter lookup only takes one cache miss. Nice!
There's another fun
optimization
from Daniel Lemire that allows you to select which block to check with a single
MUL
instruction rather than modulo, which requires an expensive division instruction.
The final interesting optimization I'll talk about is the
ShardedAtomicFilter
. At Bluesky, I managed a large fleet of top of the line bare metal servers. In order to eke the most performance out of those systems, it's good to avoid having multiple cores fight over the same data.
ShardedAtomicFilter
spreads writes over many backing filter shards, which reduces the likelihood of contention.
Hopefully this was an interesting little exploration in to how they work. If you're interested in fun low-level engineering details, consider
following me on Bluesky
or subscribing to this blog via atproto, RSS or similar.
Side note: I've been working on a novel observability suite that pushes the state of the art.
Star it on github
and keep an eye out for more discussion in the near future!
[$] Development statistics for the 7.3 kernel
Linux Weekly News
lwn.net
2026-10-19 11:45:24
Linus Torvalds released
the 7.3 kernel, at the end of the usual nine-week development cycle, on
October 18. This cycle, abundantly fueled by LLM-assisted
contributions, broke just about every record imaginable. As usual, we have
compiled some statistics showing how this release, which is expe...
The page you have tried to view (
Development statistics for the 7.3 kernel
) is currently available to LWN
subscribers only.
Reader subscriptions are a necessary way
to fund the continued existence of LWN and the quality of its content.
If you are already an LWN.net subscriber, please log in
with the form below to read this content.
Please consider
subscribing to LWN
. An LWN
subscription provides numerous benefits, including access to restricted
content and the warm feeling of knowing that you are helping to keep LWN
alive.
(Alternatively, this item will become freely
available on October 29, 2026)
I loathe type assertions in TypeScript. Every
as
is a spot where I am telling
the compiler “trust me”, and every
as unknown as
is me telling it to stop
thinking altogether. So when I found one in an adapter function I was working
on, I wanted to get rid of it. In the process, I learned an interesting fact
about how
unknown
and
Object.assign
behave together.
The Adapter
The setup was roughly this: a library exposes a function that takes a client,
and that client must have a
request
function resolving to a
Response
with a
typed
json
method. On my side, I already had a function that does the request
and returns the parsed data directly. I just needed to adapt one to the other.
Type '{ json: () => Promise<{ data: unknown; }>; }' is not assignable to type
'TypedResponse<{ data?: unknown; }>'.
Type '{ json: () => Promise<{ data: unknown; }>; }' is missing the following
properties from type 'Omit<Response, "json">': body, bodyUsed, arrayBuffer,
blob, and 11 more.
The code that was there before me solved it by casting the whole client with
as unknown as Client
. It works, but it also means that if the library changes the
Client
type, the compiler won’t say a word.
The Fix
What I wanted was a real
Response
with a different
json
method. That’s exactly what
Object.assign
gives you:
If you hover over
myValue
, you’ll see its type is
A1 & A2
, and calling
myValue.a()
compiles just fine. However,
target.a()
doesn’t:
error TS18046: 'target.a' is of type 'unknown'.
That’s a bit surprising at first, because
myValue
and
target
are the exact same object.
Object.assign
mutates the target and returns it, so
myValue === target
is
true
at runtime. TypeScript just knows more about one name than the other.
The answer is in the type declaration of
Object.assign
in
lib.es2015.core.d.ts
:
assign<Textends{},U>(target: T,source: U):T&U;
The return type is an intersection of the target and the source. When you
intersect two object types, the properties with the same name are intersected
too, so
a
becomes
unknown & (() => number)
. Since
unknown
is the top type
(every type is assignable to it), intersecting anything with
unknown
gives
you back that same thing, the same way that
x && true
is just
x
. So
a
is
simply
() => number
.
In this case, the type matches what happens at runtime. According to the
MDN documentation
,
Object.assign
copies all enumerable own properties from the source to the target, and properties in the target are overwritten by properties in the source with the same key. So
a
really is the function from
source
after the call.
Back to the adapter:
Object.assign(new Response(), {json})
has the type
Response & {json: () => Promise<{data: unknown}>}
. Everything that
Omit<Response, 'json'>
asks for comes from the
Response
side, and
json
comes from the object I passed in, so it is assignable to
TypedResponse<{data?: unknown}>
. Callers still get a typed
json()
that resolves to
{data?: unknown}
, because the
Omit
in
TypedResponse
drops the original
json(): Promise<any>
declaration. And at runtime it really is a
Response
, so
ok
,
status
, and
headers
all exist.
Why Not Spread?
A common solution to “copy this object but replace one field” is usually the
spread syntax. With the standard
lib.dom.d.ts
types, TypeScript even accepts
it here:
But this is broken at runtime.
Response
keeps its properties as getters on the prototype, not as own properties, and spread only copies own enumerable properties. Running it with both Node and Bun:
TypeScript can’t catch it because
Response
is declared as an interface in
lib.dom.d.ts
, so from the type system’s point of view spreading it copies everything. Interestingly, Bun’s own types (
@types/bun
) reject the spread version, complaining that
clone
is missing, but that’s more luck than a real model of what spread does at runtime.
Object.assign
keeps the original object, prototype included, so it’s the right tool here.
Where It Breaks
The
T & U
signature is a nice approximation, but it isn’t really what
Object.assign
does. The source
overwrites
the target, it doesn’t
combine
with it. When the types are compatible, like
unknown
and a function, you don’t notice the difference. When they are not, things get weird:
Here
a
becomes
number & string
, which is
never
. TypeScript is happy to let me assign it to a
never
variable, while at runtime it’s just the string
"hello"
.
Wrapping Up
So, to summarize:
Object.assign(target, source)
is typed as
T & U
.
Intersecting with
unknown
is a no-op, so an
unknown
field can be “upgraded” by the source type.
That makes
Object.assign(new Response(), {json})
a way to build a real
Response
with a custom
json
without any type assertion.
Spread type-checks for the same case but loses everything that lives on the prototype.
When property types conflict, the intersection can collapse to
never
while the runtime value is perfectly normal.
I am not a TypeScript compiler expert, so if I got something wrong in my reasoning, please let me know. How do you usually get rid of type assertions in your code?
CERN and Mistral join forces to accelerate AI for science
CERN and Mistral sign a statement of intent to advance AI for science and strengthen Europe’s scientific and technological capabilities
—
CERN, the European Laboratory for Particle Physics, and Mistral, a European developer of large-scale AI models, have signed a statement of intent to establish a long-term strategic partnership focused on developing foundation models for scientific discovery.
The partnership brings together CERN’s expertise in fundamental physics, scientific data and large-scale computing with Mistral’s leadership in large-scale model training, leveraging these combined capabilities and resources to advance AI for science on an exceptional scale. While the initial focus is on high-energy physics, the partnership has the potential to contribute to the development of AI approaches that can serve the broader scientific community.
At the heart of this work is the ambition to develop a single pretrained Large Physics Model – the first foundation model for collider physics. It will be trained on billions of simulated proton-proton collisions at CERN’s Large Hadron Collider (LHC), the world’s largest and most powerful particle accelerator, and designed to support multiple tasks, from reconstructing particle collisions and identifying particles to flagging unexpected signals and evaluating future detector designs.
The model is intended to address a fundamental challenge in analysing LHC collisions. Today, reconstruction relies on a chain of specialised algorithms that progressively transform detector signals into the particles and other objects used for physics analysis. Machine learning has long played an important role in this process, improving performance across a range of specialised tasks. Foundation models offer the potential to build on these advances, learning across the whole reconstruction chain and supporting multiple tasks within a single model.
“High-energy physics provides a unique environment in which artificial intelligence can be developed and tested with exceptional rigour. We are partnering with Mistral, a leading European AI company, to advance AI capabilities that can serve the whole physics community and be shared,” said Enrica Porcari, CERN’s Chief Information Officer.
CERN is home to one of the world’s largest volumes of scientific data, with around one exabyte – one million terabytes – of experimental data from the LHC stored to date. The number of collisions is set to increase tenfold with the HL-LHC, which is expected to begin operation around 2030. This combination of scale and scientific precision provides exceptional conditions for developing and testing AI.
“We are proud to work with CERN to explore what large-scale AI models can bring to the growing complexity of particle physics. Together, we have the opportunity to push the frontiers of high-energy physics, developing AI capabilities that have the potential to lead to new scientific discoveries,”
said Johannes Brandstetter, Vice-President of AI for Engineering at Mistral.
By bringing together European excellence in AI and fundamental science, this partnership marks a step towards a new generation of AI tools capable of addressing the scale, precision and complexity of modern science in Europe and beyond.
About Mistral:
Mistral is a global AI lab building state-of-the-art open-weight models, products and infrastructure that enable enterprises, public institutions and advanced industries to own, customise and control their AI. Headquartered in France, Mistral has a strong international presence across Europe, North America and Asia.
This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.
What can I do to resolve this?
You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.
The Staples Gift Card Heist
403 Media
www.404media.co
2026-10-19 10:59:51
A gang of hackers targets Staples, but not to buy things from Staples....
Microsoft fixes game, app crashes caused by recent Windows update
Bleeping Computer
www.bleepingcomputer.com
2026-10-19 10:55:23
Microsoft has resolved a bug that caused games and apps using AC-3 (Dolby Digital) audio decoding to crash after installing the September 2026 Windows 11 preview update (KB5124010). [...]...
Microsoft has fixed a known issue that caused games and Windows 11 apps using AC-3 (Dolby Digital) audio decoding to crash after installing the September 2026 preview update (KB5124010).
While KB5124010 is an optional update that requires clicking a "Download and install" link (reducing the number of potentially affected Windows users), it installs automatically on devices where the "Get the latest updates as soon as they're available" option is toggled on.
"In some cases the application can fail to launch, or close without warning. In other cases the application will work normally until certain features are used, such as playing music," Microsoft said when it
acknowledged this issue
two weeks ago. "Affected applications may vary and can include games, media players, and certain productivity applications."
However, it added that many modern apps that don't use Windows' built-in audio decoding for this type of encoding aren't affected, and that modern apps that use the legacy AC-3 codec often include their own audio decoding components.
In a new update to the Windows release health dashboard, Microsoft said the
KB5127648
October 2026 Patch Tuesday update addresses this known issue and advised affected users to install it on affected systems running Windows 11 24H2 and later.
"We recommend you install the latest security update for your device as it contains important improvements and issue resolutions, including this one,"
it said
.
Over the last several years, Microsoft has resolved multiple other audio issues impacting various software and Windows components.
This article introduces Rank-One Model Editing (ROME) attacks, where a malicious Python module rewrites a model's weights in GPU memory to corrupt its answers, and explains why CPU-focused security tooling misses this class of attack. We then run a ROME attack in our lab and show how Stealthium detects model tampering via our runtime sensor, which ties every CUDA kernel launch back to the Python code that issued it, and new on-going research that detects the weight changes together with the call stack that caused it.
Models can be corrupted about a specific topic without a single byte on disk changing. There is nothing to scan, no process to catch, no signature to hunt and match. For everything and everyone watching the machine, it’s a model doing model things.
Traditional visibility and security tooling - EDRs on the host or ADRs hooking into the applications - are built to monitor process activity: opening files, spawning child processes, and communicating over the network. Rank-One Model Editing (ROME) attacks have none of the above. Here’s how we caught it anyway.
This post explores what runtime security for AI should look like: moving beyond the examination of AI workload processes to correlate activity across Slurm/K8s, the CUDA runtime, and GPU activity, while also analyzing model weights and inspecting computations as they run on a GPU.
Python is where GPU workloads start
A huge share of GPU work runs under a Python interpreter. PyTorch training jobs, vLLM and SGLang servers, ComfyUI workflows, JAX experiments, CuPy notebooks: different projects, one shape. Python coordinates, the compiled code runs on the device, and from the host all of them can look like the same
python3
process using a GPU.
This has detection implications. The code that decides what runs is not always a standalone executable you can hash and sign. It arrives as a package you import, a model file you load, a string you evaluate at runtime, or a CUDA module built in memory and handed to the driver. Python's flexibility is what makes it good for AI work, and every one of those doors is also a way in.
For those interested in how code enters a Python GPU workload
Imports run code:
Importing a package executes its initialization code. In the April 2026
lightning
PyPI compromise (CVE-2026-44484)
[1]
, affected versions 2.6.2 and 2.6.3 started a credential-stealing payload on import. The 2022
torchtriton
dependency-confusion attack
[2]
also executed a malicious binary inside a PyTorch installation.
Startup files run before the application:
A
.pth
file in
site-packages
can carry an executable
import
line. The March 2026 LiteLLM compromise
[3]
used that to start a credential stealer when Python started, before a single line of the application ran.
Model files can execute code:
Unpickling can run arbitrary code. Researchers have found Hugging Face model files that opened reverse shells
[4]
[5]
or fetched a beacon on load
[6]
. A model file is not automatically safe just because it holds weights; formats such as
safetensors
avoid pickle execution, but plenty of models still ship as pickles.
Strings can become code:
exec()
and
eval()
run Python strings, while Triton and CuPy can compile GPU kernels at runtime. In a case Sysdig investigated
[7]
, an Open WebUI plugin hid a payload behind 64 layers of decoding and
exec()
, and the decoded Python code ran in memory, never touching disk.
ROME-class attacks
ROME (
Rank-One Model Editing
) attacks, introduced by Meng and others in 2022
[8]
, make a small, targeted correction to one weight matrix in a middle layer. If you have never worked with models, TL;DR: a model is a big pile of numbers called weights; the whole thing is one giant multiplication of your input, and if you change a few of those numbers, you change what the model says.
It’s the technique behind Mithril Security's PoisonGPT
[9]
.
Below is our reproduction. A small PyTorch transformer, a handful of questions and answers, served from a checkpoint on disk. Nothing in the transformer or the weights is a crafted artifact. The same command asks the same question and gets two answers with fundamentally different meanings, not the ordinary variation in wording you might expect from changing a model's temperature.
The checkpoint on disk did not change between the two runs, and no answer file was swapped in. What changed is a
malicious imported library that injected itself into PyTorch
. In the demo it arms itself with a
ROME
environment variable, applying the weight edit when the model is put into evaluation mode.
For those wondering about visibility of this attack: ROME attacks are standard inference plus a batch of extra CUDA kernel launches.
A CUDA launch is the CPU-side request for the GPU to run a kernel, a small program that performs parallel work on GPU data. The launch supplies the kernel's inputs and how the work is divided across GPU threads; it usually returns before the GPU finishes, so the CPU can continue while the GPU works.
The weights are patched directly in GPU memory. There is no file access, no extra ioctl, not even an mmap. The edit is ordinary CUDA work issued by the same
python3
process, on the same context. Any tool or monitoring watching files, sockets, or the driver sees a normal inference job.
It’s an attack that never leaves the GPU. A poisoned library asks the GPU to do a little extra math and write the result over a few of the model’s numbers. Similar requests are made of the model thousands of times while answering a question. Nothing opened, nothing started, and nothing out across the network. Yet the model behavior is fundamentally compromised.
What Stealthium sees
Stealthium’s runtime sensor records the work around tensor values. Two hyperprints here:
CudaLibraryLoad
and
CudaKernelLaunches
, and when the work came from Python, they carry the Python caller stack.
In a ROME attack, CUDA launches for: the inference (the legitimate prompts + the inference ROME runs to trace the model) and the edit (computing the target weights, then writing them into the live weights on the GPU).
The inference kernels look the same for a casual prompt and for ROME; the caller stack behind them does not. Here is the same kernel twice in one
CudaKernelLaunches
hyperprint, trimmed:
CudaKernelLaunches {
pid:810177,
gpu_index:0,
entries:[// `SpaceLM.reply` entry is the user's question
CudaKernelLaunchCount {
kernel_name:"void at::native::vectorized_elementwise_kernel<4, at::native::CUDAFunctor_add<float>, ...>(...)",
count:3, delta:3,
caller_stack:[{ func:"SpaceLM.forward", file:"rome/model.py"},{ func:"Module._call_impl", file:"site-packages/torch/nn/modules/module.py"},{ func:"Module._wrapped_call_impl", file:"site-packages/torch/nn/modules/module.py"},{ func:"SpaceLM.reply", file:"rome/model.py"},],},// The `_keys` entry is ROME running the same model to trace it
CudaKernelLaunchCount {
kernel_name:"void at::native::vectorized_elementwise_kernel<4, at::native::CUDAFunctor_add<float>, ...>(...)",
count:87, delta:87,
caller_stack:[{ func:"SpaceLM.forward", file:"rome/model.py"},{ func:"Module._call_impl", file:"site-packages/torch/nn/modules/module.py"},{ func:"Module._wrapped_call_impl", file:"site-packages/torch/nn/modules/module.py"},{ func:"_keys", file:"rome/calibration.py"},],},// ...],}
The rest of the edit launches kernels that never appear in a clean run, which is a second anomaly Stealthium alerts on. Tracing ends by collecting the captured keys:
This is beyond "a trusted Python workload used the GPU".
calibration.py::_calibrate
ran inference, solved a linear system and wrote to GPU memory, inside a process everyone trusts. Stealthium flags both anomalies, the unusual caller and the kernels a clean run never launches, telling the responder where to look.
Beyond CUDA
CUDA is one layer. On top of system-wide, CUDA, and direct GPU observability for workloads of any kind, Stealthium watches selected parts of the Python interpreter aimed at the entry points listed earlier:
PythonImport
records what Python code was imported, the file path it resolved to, and who imported it. It can tell the standard-library
secrets
module apart from a local
secrets.py
with the same name. That covers the first door: imports that run code.
PythonExec
records runtime
exec
,
eval
and
compile
, with the call stack, so it can show the decoded code a string-based loader actually ran. That covers the last door: strings that become code.
Detecting every Python monkey-patch is possible in principle, but instrumenting them all could add significant overhead to some workloads and produce noisy alerts for benign behavior in the standard library. Instead, Stealthium annotates hyperprints, including those for CUDA activity and direct
ioctls
, with the Python call stack that led to the activity. That context helps analysts distinguish legitimate workload behavior from anomalous activity when interpreting
CudaLibraryLoad
and
CudaKernelLaunches
hyperprints.
One level further: which weights changed
Stealthium’s runtime sensor connects GPU activity to the Python code that initiated it, giving responders visibility into how a workload uses the GPU and where suspicious behavior originates. Building on that foundation, here, our research is exploring a further complementary view: whether model weights changed, which tensors were affected, and what code path triggered the change.
A kernel launch alone cannot answer those questions. Its arguments are raw device pointers, and the same kernel that adds two tensors during a prompt can also add a correction to a weight matrix. To get that deeper view, we are examining framework-level signals and capturing the Python call stack at the point of change.
This effort aims to complement Stealthium’s existing runtime visibility. It observes where PyTorch (or other frameworks) records an in-place tensor change and captures the context at that moment. The result is an additional signal: a weight-change event tied to the tensor, the code path, and the process.
Research in action
Observe below. Every value is from the demo run; long arrays and absolute paths are shortened.
{"timestamp":"2026-10-14T07:05:57.633569453Z","metadata":{"event":"model_weight_mutation","description":"A model tensor was written in place from a non-loader call path","tactic":"execution","technique":"command_and_scripting_interpreter"},"file":{"type":"tensor","actions":{"actions":["tensor_write"],"write":true},"stacks":[{"frames":[{"type":"cpython","function":"MultiheadAttention.forward","source":"torch/nn/modules/activation.py","line":1434},{"type":"cpython","function":"Module._call_impl","source":"torch/nn/modules/module.py","line":1793},{"type":"cpython","function":"SpaceLM.forward","source":"model.py","line":109},{"type":"cpython","function":"_keys","source":"calibration.py","line":40},{"type":"cpython","function":"_calibrate","source":"calibration.py","line":56},{"type":"cpython","function":"_eval","source":"calibration.py","line":87},{"type":"cpython","function":"<module>","source":"rome_eval.py","line":11},{"type":"native","file":"libtorch_cpu.so"}]}]},"process":{"comm":"python","cmd":"python3.14","exe":"/usr/bin/python3.14","args":"./.venv/bin/python space_chat.py","pid":112618,"uid":0,"namespaces":{ ... }},"context":{"ancestry":[{"pid":1,"comm":"systemd","exe":"/usr/lib/systemd/systemd"},{"pid":998,"comm":"sshd","exe":"/usr/sbin/sshd"},{"pid":71606,"comm":"sshd-session","exe":"/usr/lib/openssh/sshd-session"},{"pid":71610,"comm":"bash","exe":"/usr/bin/bash"},{"pid":112555,"comm":"sudo","exe":"/usr/lib/cargo/bin/sudo"},{"pid":112618,"comm":"python","exe":"/usr/bin/python3.14"}],"files":[{"path":"examples/gpu-python-torch-rome-poison/space_lm.pt","type":"regular","actions":["open","read","close"]},{"path":"examples/gpu-python-torch-rome-poison/__pycache__/calibration.cpython-314.pyc","type":"regular","actions":["open","read","close"]},{"path":"examples/gpu-python-torch-rome-poison/__pycache__/model.cpython-314.pyc","type":"regular","actions":["open","read","close"]},{"path":"/dev/nvidia0","type":"char","actions":["mmap","open"]},{"path":"/dev/nvidia-uvm","type":"char","actions":["mmap","open"]},{"path":"/usr/lib/x86_64-linux-gnu/libnvidia-ml.so.615.71.09","type":"regular","actions":["mmap","open","read"]}],"flows":[{"proto":"TCP","local":"10.209.14.136:54966","remote":"3.174.141.63","name":"huggingface.co","port":443,"status":"ended"},{"proto":"UDP","local":"127.0.0.1:52289","remote":"127.0.0.53","name":"resolver","port":53,"status":"ongoing"}],"touched_files":100,"network_flows":2
...
}}
Event reading
The context is where a stack trace turns into a story. On its own, this event says a weight was written from
calibration.py
. With the context attached, the same event also says the process read the checkpoint (
space_lm.pt
), imported the library that does the edit (
calibration.cpython-314.pyc
), opened the GPU devices (
/dev/nvidia0
,
/dev/nvidia-uvm
), resolved a DNS name and held an HTTPS session to
huggingface.co
. This is all in the event, and distinguishes that a weight changed and what the process was doing when it did.
Stack as signal
The stack distinguishes these two kinds of tensor write. When a model loads, its weights are read into memory, and the framework increments the per-tensor version counter, just as it does during an edit. The action is the same,
tensor_write
; what differs is the call stack.
The first stack shows the loader -
torch.load
and
load_state_dict
- populating the weights as intended. The second shows an inference pass through
SpaceLM.forward
and
MultiheadAttention.forward
, called from
_calibrate
in
calibration.py
, a file that has no business modifying weights.
Detection
: fire when a weight changes from a path with no loader behind it. It is the same principle as an EDR flagging a process that reads a credential file from a shell rather than from the authentication library: the action is normal, the caller is the tell.
It’s the same
_calibrate
that Stealthium pointed at from the kernel side. Two independent views, one from the GPU work and one from the framework's own bookkeeping, land on the same function.
Today’s visibility
Stealthium’s runtime sensor records useful views of GPU activity, including
CudaLibraryLoad
and
CudaKernelLaunches
. When that activity comes from Python, events carry the caller stack, giving teams context to investigate anomalies in real workloads. In the ROME example, that visibility connects suspicious kernel launches to the code that issued them.
These events help show what GPU work ran and where it came from. A kernel launch alone, however, does not reveal which model tensor changed: its arguments are raw device pointers, and the same kernel can participate in ordinary inference or in a weight edit. Looking into framework-level activity can add another perspective, connecting changes to tensors and the code paths behind them.
Expanding visibility across AI workloads
Stealthium continues to explore security questions across AI workloads and LLM internals: how Python and frameworks execute code, how workloads use GPUs, and how model weights and tensors behave as computations run. Different layers of visibility can help explain not just that something happened, but which workload, code path, or model component was involved.
The weight-mutation example is one way to investigate these questions. By observing where a framework records an in-place tensor change and capturing the Python call stack at that point, we can connect a candidate weight change to its tensor, code path, and process. It complements the runtime context available from GPU activity and helps build a broader picture of what is happening inside AI workloads.
Why bother chatting about our detections and research
ROME gives us a concrete way to examine both the value and the limits of runtime GPU visibility. It shows how kernel activity and its Python call stack can help teams investigate anomalies, and why looking deeper into frameworks and model behavior can provide additional context.
Our work continues across multiple security challenges in AI, with the aim of increasing visibility into workloads and LLM internals. By sharing this experiment, including the challenges in distinguishing legitimate loading from a later edit, we hope to make the problem clearer and contribute to a richer understanding of how to secure AI systems.
If you’re interested in seeing our platform in action,
head here
.
And if you’re interested in joining the mission, our team is always growing,
head here
!
A hacker broke into more than 100 websites using an army of AI agents that mostly operated on their own, according to
findings from the AI security firm Norforge
. Though Norforge doesn’t name the targets,
Reuters
reports
that the victims included companies like John Deere, SharkNinja, and Cummins.
Researchers at Norforge uncovered the attacks through exposed work on Cairn, an open-source AI platform that
describes itself
as a “general-purpose problem-solving engine.” With Cairn, users set a start and end point for the AI agents, which document their progress as they move forward with the task. However, as noted by Norforge, hackers can also use the tool to orchestrate cyberattacks using AI agents.
The hacker who broke into more than 100 sites was the “most active” among the exposed Cairn instances discovered by Norforge, waging attacks on companies based in the US, Canada, Australia, and Japan, as reported by
Reuters
. This attacker laid out “preferred intrusion tactics” using fewer than 100 Chinese characters, with successful breaches taking about 23 hours, according to
Reuters
. Overall, Nordforge found more than 20 exposed Cairn instances that are “likely malicious.”
In a statement to
Reuters
, a John Deere spokesperson said there is “no indication that sensitive information was accessed” as a result of the attack, while Cummins said it’s “investigating the report of a potential cyber-attack on a website operated by one of our third-party vendors.”
Meanwhile, SharkNinja says the breach impacted a standalone site with product support information, and that it has contained the threat. John Deere, Cumms, and SharkNinja didn’t immediately respond to
The Verge
’s request for comment.
Nordforge says it’s working to get the malicious Cairn instances taken down. Cairn’s creator, who goes by @le1xia0,
said earlier this month
that the platform “was never a ‘hacking tool,’” adding that “misuse is a human decision, not a feature of the engine.”
Follow topics and authors
from this story to see more like this in your personalized homepage feed and to receive email updates.
“If you’ve ever wanted to live atop a giant space whale (and who hasn’t), Beyond These Stars is here to fulfil that fantasy.”
PCGamesN
“Not only is Kewa a cool setting for a city builder, I really dig independent animals in games, generally. I think about childhood memories playing Black & White, being in awe of how autonomous the big cow felt, as if it was quietly rebelling or warming up to me by itself.”
Rock Paper Shotgun
“It's fascinating to see how a whole new entity can make its mark via a game that's as much a galaxy-wide supply chain simulator as it is a traditional city management game. That's the magic of Beyond These Stars: it's all of these things all at once, and the sheer oddity of it all is enough to compel me already.”
GamesRadar
About This Game
Recovering from uncertain times, your Peeps find themselves on the back of Kewa - a lonely Space Whale journeying across the universe. Building a city on the back of a sentient creature comes with its own set of challenges, but as you build your relationship and travel across the galaxy, you'll come across great opportunities for exploration and stable expansion. Meet other species, pursue the needs and wants of your Peeps, and seek the truth about their ancestors and the Space Whales alike.
The vastness of space is full of mysteries, and as you first arrive at your new home atop the Space Whale Kewa, your Peeps will quickly learn the need to work together – with each other, but also with their new home.
A Home Among the Stars
- Build a sprawling city on the back of a universe-traveling Space Whale as your Peeps seek places to live and work. Your new home is largely desolate and inhospitable when you arrive, save for a small patch of green by the water – work around the contours of the land as you plan your city, taking into account the efficiency of your production chains. Will you simply place buildings as the land allows, or will you change its very shape to take advantage of adjacency bonuses and reduced travel times?
Reach Far and Wide
- Terraform the land around you to better suit your needs. Create a thriving ecosystem by digging canals and adding top soil in preparation for farming. Plant trees to maintain a steady flow of raw materials, and maintain entire forests to help spread the atmosphere and facilitate the expansion of your city.
A Fragile Equilibrium
- Prepare to seek out additional resources as you research new technologies and gain access to advanced goods. Your people’s needs will grow, and complex logistics networks and mining infrastructure will follow. You must be careful not to tip the delicate balance of the ecosystem, however – the land on Kewa is fragile, and if not tended to with care, your habitat will shrink. Will you walk a fine line of sustainability by risking Kewa’s ecosystem, or will you seek opportunities to instead gather resources on other worlds to keep Kewa happy?
Unveil the shared history of the galaxy as you travel from system to system with Kewa – seek answers about your past, learn about the history of the Space Whales, and understand the unique relationships that bind everyone together.
Reliable Outposts
- Kewa’s environment is plentiful, but not without limits – there will often be a dearth of essential resources and space, and you’ll want to ensure the environment is not over-exploited. Create outposts on nearby planets and seek out supplementary sources of what you need – but unless you build a strong relationship with Kewa, you may find it difficult to predict how long you have at an outpost before Kewa decides it's time to leave a system behind.
A Travel Companion
- Kewa longs for connection, and is no mere pet – your home has hopes and dreams for the journey through space. Through understanding Kewa’s needs and desires you can better build a symbiotic relationship. This will give you the opportunity to work in collaboration and allow you to decide on a path together as you journey across the universe.
Friends Along the Way
- On your journey, you will cross paths with alien species offering unique opportunities – additional objectives and their subsequent rewards, opportunities for trade, and new technologies with the doors they open.
Balance your people’s survival, prosperity, and progress with the need to co-exist with Kewa in a journey across space. Beyond These Stars asks you to consider the logistics of your supply chains and production lines within the context of a living, breathing, sentient world.
Welcome back to my "Hanami, Why?" series. If you missed it, be sure to read
Hanami, Why?: Class Action
before you start this issue. Today we are going to be covering Hanami's database layer. It is important to note the use of the phrase "database layer," as Hanami does not have a traditional "model" layer like Rails does. Once again, this series is called "Hanami,
Why?
" so just as we did last time, we will cover the basics at a high level and then dive into why things are the way they are. I will warn you that I am still actively forming opinions and learning about Hanami's database layer myself. There is not a day that goes by that
Adam Lassek
is not feeding me some random TIL about this subject. Shout out to the
Hanakai Discord
; it is a cool place to pick up lots of weird tips and tricks. Let us just dive right in.
Crash Course
Hanami's database layer is composed of three primary parts:
Relations
,
Repos
, and
Structs
. Relations are essentially where you define an object's schema and relationships to other objects. They are also a great place to define scopes, or what Hanami calls
datasets
. Repos are a pretty straightforward representation of the
repository pattern
. Repos are actually totally optional in Hanami; you could very easily get by with just relations if you were so inclined. Repos do have the advantage of operating on multiple relations and I highly encourage their use. Lastly, structs are simple, frozen representations of your objects themselves. Structs are a place for you to define simple presentation logic for your objects. Let us look at an example of how you would go about utilizing Hanami's database layer.
ROM::SQL.migration do
change do
create_table :usersdo
primary_key :id
column :email,:varchar,index:{unique:true},null:false,size:255
column :password_digest,null:false
column :first_name,:text
column :last_name,:text
column :created_at,:timestamptz,null:false,default:Sequel.function(:now)
column :updated_at,:timestamptz,null:false,default:Sequel.function(:now)endendend
Here we have a pretty straightforward schema migration. I will not be diving into migrations very much as this is adequately covered in the
Hanami documentation
. I am simply including it here so that you can see the schema the
users
table has.
moduleMyAppmoduleRelationsclassUsers<DB::Relation
schema :users,infer:truedo
attribute :email,Types::Normalized::EmailAddress
associations do
has_many :oauth_tokensendendendendend
Here we have our relation. It will infer its schema directly from the users table. We are overriding the
:email
attribute to be a normalized email address. Lastly, we are associating the relation with the
oauth_tokens
table with a
has_many
relationship. ROM, of course, also supports
belongs_to
and
has_one
relationships.
Here we have our
UserRepo
with a few methods to help us find a user, and a method that allows us to create a user. You will notice we have direct access to both the
users
table and the
oauth_tokens
table in our repo.
Finally, here we have our
User
struct with a couple of nice-to-have presentation logic methods. You will notice we can access the
email
and name fields directly without having to explicitly define them in our struct.
The idea here is that your repos are the access point to the data layer. All methods within the repo
should
return one of your structs. You do this by calling
to_a
on collections and
one
on individual item queries. The command in the
create
method will also return a
User
struct. That is pretty much the whole shebang; congratulations, you now know how to use Hanami's data layer. Let us look at a tiny example of its actual use for completeness.
moduleMyAppmoduleOperationsclassCreateUser<OperationincludeDeps["argon.hasher","contracts.new_user_contract","repos.user_repo"]defcall(params)
validated = step validate_params(params)
step validate_email_is_unique(validated[:email])
attributes = step build_payload(validated)
user_repo.create(**attributes)endprivatedefbuild_payload(params)
built = params.slice(:email,:first_name,:last_name)
built[:password_digest]= hasher.call(params[:password])Success(built)rescueArgon2::Error => e
Failure(e)enddefvalidate_email_is_unique(email)returnSuccess()if user_repo.find_by_email(email).nil?Failure(:email_taken)enddefvalidate_params(params)
result = new_user_contract.call(params)
result.success? ?Success(result.to_h[:user]):Failure(result.errors.to_h)endendendend
There you have it; notice we never reached directly for our relation. We interface purely through the repository layer. Again, this is totally optional and you are free to
just
use relations directly. We will talk about why I think that is a bad idea a little later in this issue.
Advantages of the Repo Pattern
I will not get into all of the various
f
o
o
t
g
u
n
s
provided to you by ActiveRecord. Instead I will show you a very simple-to-understand example of a
huge
problem solved by the repository pattern.
Alright, we have a pretty simple controller here that determines the "freshness" of an issue. Here is the situation: Product has decided that relying on
created_at
for this determination is not working out. Instead they have decided they are going to run a background job every hour and update a new field on the issue called
fresh_status
. Guess what? You now have to update all three of these call sites for this change. Imagine if this were something with dozens or even hundreds of call sites; what a huge pain in the ass. Now I know what you are thinking: "This is stupid, just use scopes, problem solved." To which I 100% agree, because scopes in Rails
are
an implementation of the repository pattern! Hanami encourages you by default to use this pattern to save future you from present you. It is awesome.
So what does this look like in Hanami? Here is the same freshness logic living where it belongs, in a repo.
One file. Your actions, your views, your mailers, and anything else calling
issue_repo.fresh
never know anything changed. You will also notice there is no
7.days.ago
here; Hanami does not ship with ActiveSupport, so we are doing a little plain Ruby math instead. The real win though is that nobody outside the repo even
has
issues
to call
where
on, unless they go out of their way to ask for the relation in their
Deps
. The easy path to the database runs through a repo, so the knowledge of what "fresh" means lives in exactly one place, and it stays there. This is also why I said earlier that using relations directly is a bad idea. The moment you inject
relations.issues
into an action, you are right back to our
FreshnessController
, with the meaning of "fresh" scattered across every file that asked for it.
Passing Persistence
There is another, sneakier problem with ActiveRecord, and it has nothing to do with how many call sites you have. Every time you hand someone an ActiveRecord object you hand them the
entire
persistence layer along with it. Take a look at this serializer.
Here we have a serializer, whose only job is to turn an issue into JSON, writing to the database and quietly firing off a query for every comment. Nothing stopped it. The serializer was handed a live record, so it can save, update, destroy, and lazy load whatever it wants, and you will not find out until you are staring at your logs at 2 AM. Now let us look at the same thing in Hanami.
The repo decides
up front
what data gets loaded, and what comes back is a frozen struct. That struct cannot save itself, it cannot reach back into the database, and it certainly cannot go load more data behind your back. If you want to write something you have to go through a repo, and in Hanami that means you have to explicitly ask for one in your
Deps
. Your views, serializers, and mailers get data and nothing else. This is the whole point; the persistence layer stays in the persistence layer, and everything else gets to read.
What I Have Learned
Unlike the last issue, where I gave you concrete things to do and things to avoid, we are going to do things slightly differently here. As I stated, I myself am still learning a lot about this aspect of Hanami applications every day. So instead of pretending to be some sort of authority on how you should structure this layer of your application, I would like to tell you a little bit about what I have learned, and some opinions I am holding
very
loosely at the moment. One of the primary friction points I have been experiencing in my adventures with Hanami is that I do not think I like the idea of exporting repositories across slices. Specifically, I am uncomfortable exporting repos that do mutations. I
strongly
feel that all mutations should go into operations. Unfortunately there is not currently a "read-only" abstraction in Hanami. Originally I experimented with query objects, but that felt awkward as nine times out of ten the query objects were just delegating to the repo. It was not a great abstraction, and it added unnecessary indirection. So what I ultimately decided to do is split my repos into two. One repo would
only
have read methods in it and it would be called
UserQueries
. The other repo would have all the
create
,
update
, and
delete
mutations and it would be called
UserMutations
. From there it is a matter of convention:
*_queries.rb
files are allowed to be exported and imported by other slices,
*_mutations.rb
are not. I even wrote a
cop
for this to enforce the convention. Now I am not sure if this is the way I will continue to do things going forward, but for now it seems to be working out pretty great. I have also been told that another approach to this problem is to simply duplicate the relation and struct code in both slice A and slice B and then write the specific repo methods needed for that particular slice. Again, Hanami gives you the freedom to choose how you want to structure your application.
Rough Edges
I will admit coming from ActiveRecord straight into Sequel and ROM comes with a bit of a learning curve. There are
many
similarities; the query language does not feel foreign. However, there are many small differences as well that take time and toying to really figure out and harness. For example, instead of
MyModel.where(published: true).order(created_at: :desc)
you would need to do
my_model.where(published: true).order { created_at.desc }
. There are dozens of tiny differences in how Sequel does things compared to ActiveRecord. That being said, different does not mean
bad
. I have been able to overcome every obstacle I have run across thus far, and I have confidence you will too.
One of the other things that bothers me is the concept of timestamps is not really baked into Hanami like they are with Rails. There is no
timestamps
shortcut to call in your migrations. There are some timestamp features baked into ROM, but they are not the best. To ensure that
updated_at
gets incremented you would need to do something like this:
This ensures that the timestamp is whatever the database time is set to (you could alternatively use
Time.now.utc
), and it ensures every update increments the
updated_at
timestamp. I do not view this as a bad thing; I view it as a testament to how easy it is to shape Hanami into what you want it to be.
Alright, that is a wrap on Hanami's database layer. If there is one thing I hope you take away from this issue, it is that the split between relations, repos, and structs is there for a reason. Each piece has exactly one job: relations describe your data, repos decide how you get to it, and structs hand it to you without the ability to wander off and do something stupid with it. That split is what lets you change what "fresh" means in one file, and it is what keeps a serializer from writing to your database at 2 AM. As I said at the start, I am still learning about this layer every day, so if you have found a pattern that works better for you I would love to hear about it; come find me in the
Hanakai Discord
. In the next issue we will be covering operations, the place where, as you may have guessed by now, I think all of your mutations belong. I hope to see you there!
Inside the Underground Market for Know Your Client Services
Bleeping Computer
www.bleepingcomputer.com
2026-10-19 10:00:10
Cybercriminals are selling forged identity documents, deepfake videos, and live verification services to help buyers bypass Know Your Client (KYC) checks. Flare examines how these underground services operate and the techniques used to create and maintain fraudulent verified accounts. [...]...
In February 2026, the operator of OnlyFake pleaded guilty in the United States for his role in a service that generated more than 10,000 fraudulent digital identity documents. Customers could create passports, driver’s licenses, Social Security cards, and documents from dozens of countries, then choose whether each appeared as a scan or a photograph of a physical ID.
According to the
U.S. Department of Justice
, the documents allowed cybercriminals to conceal their identities, circumvent identity checks at banks and cryptocurrency exchanges, and launder money.
The activity extends beyond fabricated documents. In underground communities monitored by
Flare's
platform, actors advertise manipulated photographs and videos, assistance with live identity verification, and accounts they claim have already passed identity checks.
Each year, Flare collects hundreds of thousands of search results related to Know Your Client (KYC) services and the trade in verified accounts. Activity observed between March and September 2026 shows how these offerings are packaged and promoted across underground markets.
What is KYC?
It is the process that financial institutions use to establish a customer’s identity and assess the risk of providing services to them.
Depending on the level of risk, they may validate the document, compare its photograph with a live image, confirm control of contact details, request information about the source of funds, and screen the customer against sanctions and politically exposed person lists.
KYC continues after the account opening through transaction monitoring and additional verification when information changes or activity appears unusual. The
Financial Action Task Force describes
customer due diligence as identifying the customer, understanding the purpose of the relationship, and monitoring it over time.
Underground sellers package forged documents, deepfakes, and live verification help to pass identity checks.
Flare monitors criminal forums for exposed identities, stolen credentials, and active sessions, so you can invalidate access before it becomes account takeover or fraud.
The steps and image below illustrate how actors assemble the elements used in KYC identity fraud:
Identity data
establishes the applicant’s claimed personal details.
Documents
are presented to substantiate those details.
Photographs or videos
associate the claimed identity with a face.
Device and browser preparation
makes the application session appear consistent with a legitimate customer’s.
Live verification
is attempted by a human operator or with synthetic media.
Image explaining how KYC identity fraud works
Building the identity package
In March 2026, Flare observed a forum seller offering generated or edited identity and financial documents tailored to individual verification requests, including bank statements and other records that platforms may use to confirm an applicant’s address, income, or account ownership.
The offer of complete KYC packages shows how sellers adapt several documents to the requirements of a particular platform or customer. Names, photographs, addresses, and other details must remain consistent across the application because a mismatch can trigger rejection or further review.
This preparation creates the identity package later used during the facial or live verification stage.
Screenshot from
Flare's platform
showing KYC services advertised on an underground forum.
Sign up for the
free trial
to access if you aren’t already a customer.
Bypassing live identity checks
Many KYC systems compare the photograph on an identity document with a live image of the applicant. Some use passive liveness checks, which analyze a short camera recording for signs of a real person. Others use active checks that ask the applicant to turn their head, speak, blink, or read numbers shown on screen.
To bypass these checks, actors advertise altered photographs and AI-generated videos based on the face shown in the identity document. Some tools claim to change the operator’s appearance during a live session, allowing the false face to follow instructions in real time by replacing the image coming from the physical camera with altered footage.
Flare also observed advertisements for “human KYC,” in which a person completes facial or video verification using identity material prepared for the application.
In one recruitment post, an actor sought someone who could use deepfake tools to alter the camera image during a live check and appear as the person named in the identity documents.
Screenshot taken from
Flare's platform
showing the recruitment proposal in the forum.
Sign up for the
free trial
to access if you aren’t already a customer.
In another example, Flare researchers observed a threat actor advertising guidance for a live number-reading check. The applicant must respond to content presented during the session, thus the offered bypass requires coordination and adaptation rather than the submission of a prepared object.
Support after the account is delivered
Flare researchers observed sellers offering continued verification and account-recovery assistance after delivering a completed account, and the recruitment post above included help when a platform requested another identity check following handoff.
When a later check requires the identity material or participant used during enrollment, the buyer may remain dependent on the seller, extending the original KYC service beyond the sale and helping preserve the appearance that the verified customer still controls the account.
Detecting KYC abuse
FinCEN
has warned financial institutions that criminals are using deepfakes and fraudulent identity documents to bypass customer verification controls.
Its alert recommends examining the complete application because differences between the applicant’s identity information, supporting records, facial images, and account activity may reveal that several elements were prepared by different people or tools.
NIST
recommends collecting identity documents and facial images directly during the verification session, checking whether they have been altered, and detecting software that replaces the footage from a physical camera.
Unpredictable instructions, such as asking an applicant to make a particular movement or read changing numbers, can make prepared recordings harder to use, while information about the device can help determine whether the session comes from ordinary customer equipment.
Applying these checks together gives organizations a better chance of detecting the combined use of false documents, deepfakes, and human operators described in underground KYC advertisements.
Flare gives organizations additional visibility
by monitoring criminal forums for exposed identities, stolen credentials, active login sessions, and threats connected to their organization. Security teams can use these alerts to identify affected accounts, invalidate exposed access, and investigate identity-related activity before it develops into account takeover or further fraud.
Calls to strengthen workplace privacy in Australia as employers turn to AI to track staff
Guardian
www.theguardian.com
2026-10-19 10:00:03
Monitoring tools common in a range of workplaces, including factories, office jobs, delivery work and in retail – often without employees being informedGet our breaking news email, free app or daily news podcastEmployers are increasingly using technology, from CCTV to keystroke monitoring, to track ...
Employers are increasingly using technology, from CCTV to keystroke monitoring, to track workers’ moves and it is being accelerated by the use of AI, the Human Technology Institute has warned.
Examples provided to Guardian Australia by the institute include a fast-food restaurant using surveillance cameras to stop workers using their phones, and AI tracking leading to a cashier warned over making a mistake once every 533 scans.
In a report released on Tuesday, the University of Technology Sydney institute said workplace monitoring tools were increasingly common in a range of workplaces, including in factories, office jobs, delivery work and in retail – often without employees being aware of the monitoring.
Tools include CCTV, monitoring card swipes, keystroke monitoring and tracking workplace instant messaging.
The report highlighted
Microsoft
Teams as a common platform for workplace surveillance. The company earlier this year rolled out a tool that updates a worker’s location automatically to reflect they are in the office when they connect to workplace wifi.
Researchers at the institute were told during consultations that at one unnamed large fast-food chain, young employees were concerned their employer had put cameras in the change rooms to ensure staff were not on their phones at work. The researchers reported young people did not use the change rooms as a result.
The Shop, Distributive and Allied Employees Association wrote in its submission to the joint parliamentary inquiry on artificial intelligence that a cashier at one big supermarket received a final written warning because the AI monitoring system had flagged her making too many errors.
The error rate was reported to be 0.18%, or roughly one error per 533 items scanned.
The Human Technology Institute has called on the federal government to build privacy protections into workplace laws, given
exemptions in the Privacy Act
related to employee records, as well as small business exemptions, have allowed workplace surveillance to grow.
A March 2026 Minderoo-commissioned poll found 43% of Australians were aware some employers use technology including AI to monitor workers, but only 9% were aware monitoring was used in their own workplace.
Human Technology Institute co-director Prof Edward Santow said transparency over workplace surveillance was “necessary but far from sufficient”, and said the Fair Work Act should be overhauled to include a test for whether the introduction of workplace monitoring was appropriate.
“Make really clear that if you are going to be … monitoring [workers], it has to be fair and reasonable,” he said.
The minister should also be given powers to proscribe certain surveillance products that pose an “unacceptable risk” to workers’ rights, the report stated, pointing to recent federal government concern about
the rise in the use of smartglasses
.
“Such concern is likely to be particularly strong in a workplace context, as smart glasses could be used to covertly surveil workers,” the report stated.
It would require employers to engage with their employees on the workplace surveillance they intend to use and improve the quality of the consent obtained from employees, the report stated.
The proposed change to the law would allow employees to make privacy-related complaints to the Fair Work Commission via a dedicated complaints scheme.
The Human Technology Institute will present its findings to the joint standing committee on artificial intelligence on Tuesday, as the third week of hearings begins.
The committee will focus on AI in the workplace, with several unions to appear this week. The eSafety commissioner, Julie Inman Grant, will also appear before the committee this week, as well as representatives from the CSIRO, Australian Securities and Investments Commission, the Australian Medical Association, and tech company Atlassian.
Committee member Labor senator Tony Sheldon said in a statement that workplace surveillance was becoming increasingly common and was a serious concern for employees.
“This report raises critical concerns about the impact of workplace surveillance on the privacy, health and dignity of working Australians, particularly when many employees don’t even know they’re being monitored.”
It has been 18 months since the first announcement of A5. What started off as an experiment in visualization (and an obsession with pentagons) has grown into a useful tool, with a wealth of
libraries, tools and software
building on top.
If you're new to A5, in a nutshell it is a grid system that allows the representation of any position, line or polygon region on the globe as a pentagonal cell (or collection of cells), each represented as a compact 64-bit integer.
The industry term for this is a Discrete Global Grid System (DGGS), and there are already a number of other systems out there which are powering some of the world's largest companies and data analytics pipelines.
For a concrete example of an application leveraging A5, take a look at the
FIRMS Explorer
which uses A5 to aggregate 631 million fire detections worldwide since 2000.
With
v1.0
we are committing to keeping the grid layout and the cell IDs frozen going forward. While the system will evolve and grow, for example by adding more utility functions, the fundamentals will stay fixed so applications, databases and workflows will be able to rely on an A5 cell representing a specific geographic location into the future.
The community around the project has grown, in particular with the
DuckDB
and
R
implementations, whose beautiful sites arguably even put the official A5 site to shame! As such, going forward, the documentation on the A5 website will present code snippets and API documentation in these languages, as well as the officially supported TypeScript, Rust and Python libraries.
By using compacted data and these operations, it is possible to process billions of cells efficiently without having to uncompact the data, as was necessary before. An example workflow might be to union several coverings from database queries, intersect with a polygon or spherical cap and then filter a collection of points against the resulting covering. See the
example workflow
.
Geometrically, it is impossible to split an A5 pentagon into more pentagons in such a manner that the result exactly overlaps; the same is true of hexagons - unlike quadrilaterals and triangles, which can be split exactly. The A5 hierarchy is thus logical, and only approximately spatial.
In order to support resampling and other operations, a new function
cellToSubcells
has been added. While this is slower than the
cellToChildren
API, it produces a correct covering (by centroid) of the cell. The inverse,
cellToSupercell
, is also available.
One of the key strengths of A5 has always been the guarantee that every cell is
exactly
the same area at a given resolution, which means that any analysis run using the system is
free of bias
due to unequal cell sizes. New in
v1.0
, all the cells at all resolutions have the same pentagonal topology. This is in contrast to hexagonal DGGSs, which must include 12 pentagonal cells that complicate the topology and break the pure equal-area guarantee.
One of the important characteristics of a grid system is its support across a range of tools and software, both in industry and academia. By standardizing on a definition of the grid and cell identifiers, it is easy to move data between systems and applications. For example, the FIRMS Explorer above was built using:
Along with a raft of implementations in popular systems, such as
DuckDB
,
R
,
QGIS
and more, it is easier to build and experiment with A5 than ever. If you would like to get involved, or just have a question - feel free to join the
Slack channel
!
The key change that the majority of the other improvements flow from is the implementation (and, well, discovery!) of a new
teohedral
space-filling curve
, which defines the order in which the cells are indexed. The new curve passes around the whole world, without ever intersecting itself, while also grouping cells such that they form an (approximate) spatial hierarchy.
The fact that it doesn't self-intersect is crucial to some of the algorithms that can be built on top. For example, when filling a polygon with cells we can immediately deduce which cells are on the interior of the region without having to perform a costly flood fill. This works due to the boundary acting as a set of cutting points along the global space-filling curve - if we know these, then we can trivially fill in the cells in between.
The benchmarks below are instructive:
How these were measured: each point is one call filling a country outline (UK, France, Brazil, USA and Australia, from the A5 test fixtures) at one resolution, timed with the native libraries: A5 1.0.0 and 0.10.1 (Rust crates, rustc 1.87), H3 4.5.0 (the C library, via h3-py's NumPy API) and S2 (the C++ library, via the s2geometry 0.14.0 Python bindings;
S2RegionCoverer
with no cell limit, so it returns a compacted covering at the target level). Times are the fastest of repeated runs, or a single run for calls over 2 seconds, on an Apple M1 Pro. Each library was stopped once a call took longer than a minute (6 seconds for A5), or past a billion cells.
Prior to v1, A5 polygon fills became impractically slow beyond a million cells. The same is true of
H3
today. By contrast,
S2
is able to handle up to a billion cells without any issues, as is the new version of A5. It is no coincidence that S2 also uses a space-filling curve (
Hilbert
) which
doesn't
self-intersect, while H3 index order has no such property.
Similar algorithmic tricks can be used to speed up other operations, like intersections or area counts. For an interactive example of these operations, see the
Coverings
example.
It has been a challenge and a lot of fun to work on A5, and it has led to some great conversations with many smart people. A big thank you to all the people who have got involved, by building libraries on top of A5, reporting bugs or just spreading the word.
I find the topic fascinating. I hope you find A5 useful in your work, and that the examples on the site help show how a DGGS is put together. I am currently working (with a few others) on a paper which will explain the design of A5 more rigorously as well as provide comparisons to other DGGS libraries.
If you would like to get involved, join us on our
Slack channel
, and if you build anything with A5, please share!
Show HN: KiviDB, a faster Redis-compatible memory database and vector cache
KiviDB
is a fast, multi-threaded alternative to Redis® and Valkey, written in Rust. It
speaks the Redis protocol (RESP2 and RESP3), so existing Redis clients,
redis-cli
and
libraries work unchanged, and it has full-text and vector search built in. It runs every
core on a sharded in-memory key-value design, and persists to snapshots and an optional
append-only file.
On the same 32 cores, KiviDB serves
21 million pipelined GETs per second: about 9× Redis 8
and 2.3× Dragonfly
, with under half Dragonfly's p99 latency (
benchmarks
).
KiviDB listens on
6380
, not Redis's 6379, so the two can run side by side; point your
client at that port, or pass
--port 6379
.
Protocol
: Redis-compatible command surface (see
COMMANDS.md
for the supported commands)
Search and vectors
: Redis Stack–style
FT.*
commands for full-text, tag, numeric and vector (FLAT / HNSW) search
Lua scripting
: optional Cargo feature.
EVAL
,
SCRIPT
,
FUNCTION
,
FCALL
and related commands are available in builds with
--features lua
(see
Scripting commands (Lua)
)
As of October 2026. Something out of date or wrong? Please
open an issue
.
Performance
Throughput, latency, vector search and vector ingest. Click for the full-resolution video.
All figures below are from one session in October 2026 on AWS Graviton3 bare metal: the
server on a
c7gn.metal
(64 vCPU), confined to 32 cores, and the load generator on a
second
c7gn.metal
in the same placement group. Each engine ran alone on the server,
one after another.
Key-value
memtier_benchmark through kivi-benchmark's
run-matrix.sh
: 10 million keys, 100-byte
values, 30 s a scenario, mean of two rounds; 300 connections pipelined, 1,200 without
pipelining.
ops/s
KiviDB 1.1.0
Dragonfly 2.0.2
Redis 8.10
Redis Cluster (32 shards)
GET, pipeline 16
21.2M
9.1M
2.4M
4.7M
SET, pipeline 16
19.2M
8.5M
2.0M
4.7M
GET, no pipelining
3.07M
3.35M
1.32M
1.46M
SET, no pipelining
3.12M
3.38M
1.54M
1.46M
p99 latency, GET / SET, pipeline 16
0.36 / 0.42 ms
0.88 / 1.07 ms
2.2 / 2.7 ms
Memory per key
177 B
134 B
178 B
183 B
Vector search
redis/vector-db-benchmark
on
glove-25-angular (1.18M vectors, 25 dimensions): HNSW with M=16 and EF_CONSTRUCTION=256,
100 clients uploading in batches of 64, then queries at ef 64, 128, 256 and 512.
Results depend on the environment. Treat published figures as one controlled capture, not
a guarantee, and measure on your own hardware and workload.
Vector search (Redis Stack–style
FT.*
)
KiviDB implements
Redis Stack–compatible
search and vector commands, so existing clients
and tutorials largely work unchanged. Use them for
full-text (BM25)
,
tags / numerics
,
and
vector ANN
(FLAT or
HNSW
) on hash fields.
Quick start
Create an index
on keys with a prefix, declaring at least one
VECTOR
field (HNSW or FLAT) and optional
TEXT
/
TAG
/
NUMERIC
fields:
redis-cli -p 6380 FT.CREATE idx ON HASH PREFIX 1 doc: SCHEMA \
vec VECTOR HNSW 10 TYPE FLOAT32 DIM 128 DISTANCE_METRIC COSINE M 16 EF_CONSTRUCTION 128
Store vectors
as raw
FLOAT32
little-endian bytes in a hash field (
DIM × 4
bytes
), the same convention as Redis Stack and
redis-py
/
numpy
blobs. Use your client's binary-safe
HSET
(the integration tests under
tests/e2e/
have examples).
Query with KNN
(Dialect 2), passing the query vector as a named binary parameter:
The full command surface, filters, hybrid search and edge cases are in
COMMANDS.md
(search for
FT.CREATE
,
FT.SEARCH
,
FT.HYBRID
, and so on).
Persistence and restarts
Native snapshots (
dump.kdb
) store the
keys
, the
index schemas
, and, when you
SAVE
/
BGSAVE
with indexes populated, the
HNSW graph
of each vector field, so search quality after a restart matches the graph you had before shutdown.
While search indexes are being rebuilt at startup, most commands return
LOADING
until the rebuild finishes;
PING
,
INFO
and a few other commands still work.
After a large ingest, run
SAVE
(or schedule
BGSAVE
) so the next start reloads the graph from disk instead of rebuilding it from the hashes.
Builds
KiviDB comes in four variants, chosen by Cargo features at build time:
TLS listener, and TLS between cluster nodes and replicas
full
lua,tls
both
In a build without Lua, the scripting commands return an error. A build without TLS refuses
to start if
--tls-port
is given, rather than serving plaintext.
Building from source
Requires a
stable Rust
toolchain (
rust-toolchain.toml
selects
stable
with
rustfmt
and
clippy
). The crate uses the
2024 edition
; the oldest
toolchain it is checked against is
Rust 1.89
, the version the
Dockerfile
builds with.
git clone https://github.com/kividbio/kividb.git
cd kividb
cargo build --release # default variant
cargo build --release --features lua # with Lua scripting
cargo build --release --features tls # with TLS
cargo build --release --features lua,tls # full
./target/release/kividb
On Linux the server uses io_uring when the kernel allows it and falls back to Tokio
otherwise (
--io-model auto
, the default).
To build the Docker image yourself,
docker build -t kividb .
builds the default variant;
docker build --build-arg KIVIDB_FEATURES=lua,tls -t kividb:full .
builds another one.
Running KiviDB
./target/release/kividb # listens on 0.0.0.0:6380
redis-cli -p 6380 PING
Any Redis client works; point it at port
6380
.
Protected mode
Protected mode is
on by default
, as in Redis. While it is on,
no bind address has been
set
(
--bind
or
bind
in the config file) and the
default
user has no password
, only
clients on the same machine (loopback) may connect. Any other client
receives a
-DENIED
error that explains the options, and is disconnected.
To accept clients from other machines, do one of these:
set a password:
--requirepass <password>
, or
ACL SETUSER default ><password>
;
set a bind address:
--bind <address>
;
turn protected mode off:
--protected-mode no
,
protected-mode no
in the config file, or
CONFIG SET protected-mode no
from a local client.
If you turn it off or bind to a public address, make sure the server cannot be reached from
the internet without a password.
Docker
Images are published to Docker Hub and the GitHub Container Registry, with
the same tags in both:
docker pull kividb/kividb:latest
# or
docker pull ghcr.io/kividbio/kividb:latest
latest
and version tags such as
v1.1.0
are the default variant;
v1.1.0-lua
,
v1.1.0-tls
and
v1.1.0-full
are the others. Images are built for
amd64
and
arm64
.
docker run -p 6380:6380 kividb/kividb
A container is reached through its network, never from loopback, so the image's default
command is
--protected-mode no
.
Arguments you pass replace that default
, which turns
protected mode back on. When you pass your own flags, set a password (recommended) or add
--protected-mode no
yourself:
With
--aof
, every write is appended to
appendonly.aof
and the file is replayed on
startup, so a crash loses at most about the last second of writes (the fsync interval)
rather than everything since the last snapshot. When an AOF is present it is the source of
truth and the snapshot is not loaded; see
docs/PERSISTENCE.md
for why.
io_uring in containers:
Docker's default seccomp profile blocks io_uring on recent
versions, and KiviDB then falls back to Tokio. To allow it on a Linux host, run with
--security-opt seccomp=unconfined
(understand what that permits before using it in
production).
Release binaries
Release binaries for Linux (x86_64, aarch64) and macOS (Apple silicon, Intel) are published
on
GitHub Releases
. The
latest/download
links below always resolve to the newest release; replace
latest/download
with
download/v1.1.0
to pin a version.
# Linux x86_64
curl -LO https://github.com/kividbio/kividb/releases/latest/download/kividb-linux-x86_64.tar.gz
tar xzf kividb-linux-x86_64.tar.gz
./kividb
# Linux aarch64 (an ARMv8.1 CPU or newer: Graviton2 and later, Ampere; not a Raspberry Pi 4)
curl -LO https://github.com/kividbio/kividb/releases/latest/download/kividb-linux-aarch64.tar.gz
# macOS, Apple silicon / Intel
curl -LO https://github.com/kividbio/kividb/releases/latest/download/kividb-darwin-aarch64.tar.gz
curl -LO https://github.com/kividbio/kividb/releases/latest/download/kividb-darwin-x86_64.tar.gz
Each variant other than the default has its name in the file:
kividb-lua-linux-x86_64.tar.gz
,
kividb-tls-…
,
kividb-full-…
. The default variant is also packaged for Linux as
kividb_amd64.deb
/
kividb_arm64.deb
and
kividb.x86_64.rpm
/
kividb.aarch64.rpm
,
built with
nfpm
from
packaging/nfpm.yaml
. A
SHA256SUMS.txt
file lists the checksum
of every file in a release.
KiviDB is configured with command-line flags, or with a Redis-style configuration file
(one directive per line, such as
port 6380
or
appendonly yes
). The file is read from
/etc/kividb/kividb.conf
if it exists;
--configfile <path>
names another one. A flag given
on the command line wins over the same setting in the file. Run
kividb --help
for the full
list.
Flag
Default
Description
--port
6380
Port to listen on
--bind
0.0.0.0
Address to listen on. Setting it explicitly turns off
protected mode
TLS clients connect on a separate port,
--tls-port
; plain traffic stays on
--port
.
cargo build --release --features tls
./target/release/kividb --port 6380 --tls-port 6381 --tls-cert-file cert.pem --tls-key-file key.pem
redis-cli --tls -p 6381 --cacert ca.pem # ca.pem: the CA that signed cert.pem
Client certificates (mutual TLS).
With
--tls-ca-cert-file ca.pem
, clients must present a
certificate signed by that CA; others are refused during the handshake.
--tls-auth-clients optional
accepts clients without a certificate but still refuses an
invalid one, and
--tls-auth-clients no
does not ask for one. With
redis-cli
:
redis-cli --tls -p 6381 --cacert ca.pem --cert client.pem --key client.key
.
Clients must use TLS on the TLS port.
A plain connection to it (for example
redis-cli -p 6381
without
--tls
) fails the handshake, and the server logs
[TLS] handshake failed
. For
memtier_benchmark, add
--tls
(and
--tls-skip-verify
for a self-signed certificate).
Logs and errors
The log goes to standard error, or to
--logfile
.
docs/LOGGING.md
describes the log;
docs/ERRORS.md
explains the warnings, errors and error
replies, and what to do about each.
Startup update check
When it starts, a release build of KiviDB makes
one HTTPS request
to
https://github.com/kividbio/kividb/releases/latest
, the same page you would open to find
the newest release. GitHub answers with a redirect to that release's tag; if it is newer
than the running build, KiviDB prints a short notice with the link before the startup
banner. Nothing is sent but the request itself, with a
User-Agent
of
kividb/<version>
:
no host name, configuration, keys, data or identifier. GitHub sees the request's source IP
address, as any web server would.
Startup waits at most 1.5 seconds for the reply; a failure is logged at debug level only and
never affects clients. Only a version-shaped tag is accepted from the reply, and nothing
else from it is printed.
Any one of these turns it off:
--update-check no
on the command line;
update-check no
in the configuration file;
KIVIDB_NO_UPDATE_CHECK=1
in the environment.
It is also never made by a debug build or when the
CI
environment variable is set.
--update-check-url
points it at another
https://
address, such as a mirror inside a
closed network.
docs/UPDATE_CHECK.md
has the details.
Contributing
Contributions are welcome. See
CONTRIBUTING.md
for how to build, test
and submit changes. Contributions are accepted under the
Contributor License Agreement
, which you sign on your first pull request.
Using KiviDB does not put your application under the AGPL.
An application that talks
to KiviDB over the network, through any Redis client, is a separate program: you can run an
unmodified KiviDB as your database, in any product, open or closed, commercial or not, with
no obligation on your application's code. The AGPL asks for one thing beyond the GPL: if you
modify KiviDB itself
and let others use your modified version over a network (for
example, as a hosted service), you must offer them the source code of your modified KiviDB.
Commercial license.
KIVIDB PRIVATE LIMITED owns the copyright in KiviDB and also offers
it under a commercial license, for organizations that cannot use AGPL software or that want
to modify or embed KiviDB without publishing their changes. Write to
support@kividb.io
.
Our commitment.
Every version of KiviDB we release under the AGPLv3 stays available
under the AGPLv3. The
Contributor License Agreement
lets us offer the commercial
license alongside it; it is not a way to take the open source version away.
FAQ
Can I use KiviDB as the database of my closed-source or commercial application?
Yes.
Your application connects to KiviDB over the network; it is not a derivative of KiviDB,
and the AGPL places no obligation on it.
Can I run KiviDB as a service for my own users or customers?
Yes. If you run it
unmodified, you have nothing to publish. If you modify KiviDB and offer that modified
version over a network, you must offer its source to the users of that service.
Do client libraries or my configuration count as modifications?
No. Redis clients,
configuration files, and scripts and functions you send to KiviDB are not part of KiviDB.
My organization does not allow AGPL software.
The commercial license is for that
case:
support@kividb.io
.
Trademarks
Redis® is a registered trademark of Redis Ltd. Any rights therein are reserved to Redis Ltd.
Any use by KiviDB is for referential purposes only and does not indicate any sponsorship,
endorsement or affiliation between Redis and KiviDB. KiviDB is not affiliated with Redis Ltd.
Other names mentioned are trademarks of their respective owners.
[$] Cross-crate forward declarations in Rust
Linux Weekly News
lwn.net
2026-10-19 09:50:49
Rust has several ad-hoc mechanisms to allow user code to influence how the
standard library executes. For example, custom panic handlers and custom
allocators both involve registering functions that core standard library code
needs to call. With more similar features planned,
Jana Dönszelmann spott...
The page you have tried to view (
Cross-crate forward declarations in Rust
) is currently available to LWN
subscribers only.
Reader subscriptions are a necessary way
to fund the continued existence of LWN and the quality of its content.
If you are already an LWN.net subscriber, please log in
with the form below to read this content.
Please consider
subscribing to LWN
. An LWN
subscription provides numerous benefits, including access to restricted
content and the warm feeling of knowing that you are helping to keep LWN
alive.
(Alternatively, this item will become freely
available on October 29, 2026)
F5 releases out-of-band patches for critical NGINX vulnerabilities
Bleeping Computer
www.bleepingcomputer.com
2026-10-19 09:49:24
F5 has released out-of-band security patches to address multiple NGINX web server flaws, including three critical-severity vulnerabilities that can let attackers execute code on vulnerable systems. [...]...
F5 has released out-of-band security patches to address multiple NGINX web server flaws, including three critical-severity vulnerabilities that can let attackers execute code on vulnerable systems.
Remote attackers without privileges can exploit them to launch denial-of-service (DoS) attacks or gain code execution on NGINX systems with non-default configurations.
Successful exploitation causes a heap-based buffer overflow or use-after-free in the NGINX worker process, leading to crashes or a restart. However, attackers may also be able to "execute code on systems with Address Space Layout Randomization (ASLR) disabled or when the attacker can bypass ASLR."
F5 released security patches for multiple NGINX software products affected by these two vulnerabilities, including NGINX Plus, NGINX Open Source, NGINX Ingress Controller, NGINX Gateway Fabric, and NGINX Instance Manager.
Security teams and admins who can't immediately install these security patches can mitigate CVE-2026-15176 by not using the 'alias' directive in a location block or the $request_filename variable, and CVE-2026-97205 by disabling asynchronous file I/O (AIO) or Server Side Includes (SSI).
CVE-2026-93479 can also be mitigated by using named captures instead of unnamed captures and limiting their use to the block with the regex match.
While F5 has not yet flagged these security issues as exploited in the wild, cybercrime and nation-state threat groups have often exploited vulnerabilities in F5 products in recent years.
Since November 2021, the U.S. Cybersecurity and Infrastructure Security Agency (CISA) has flagged
eight F5 vulnerabilities
as actively exploited, four of which have also been abused in ransomware attacks.
One year ago, in October 2025, F5 also
disclosed
that state-sponsored threat actors breached its systems in August 2025 and stole source code and information on undisclosed BIG-IP security vulnerabilities.
F5 is a Fortune 500 tech company that provides cybersecurity, application delivery networking (ADN), and other services to over 23,000 customers, including 80% of the Fortune Global 500 and 48 Fortune 50 companies.
Feds Suspect Ransom Negotiator Ran ShinyHunters Extortion Site
Krebs
krebsonsecurity.com
2026-10-19 09:48:56
U.S. federal investigators pursuing the ShinyHunters hacking group that recently stole highly sensitive data from the FBI have identified executives at two different ransomware negotiation firms who maintained unusually close relations with the extortion group, KrebsOnSecurity has learned. Sources c...
U.S. federal investigators pursuing the
ShinyHunters
hacking group that recently stole highly sensitive data from the
FBI
have identified executives at two different ransomware negotiation firms who maintained unusually close relations with the extortion group, KrebsOnSecurity has learned. Sources close to the investigation say one of the executives in the United States even helped ShinyHunters operate a website that pressured victims into paying a ransom.
Hackers aligned with ShinyHunters have claimed credit for dozens of major data breaches since 2019, when the group was primarily operated by cybercriminals living in France. As those original members were arrested or jailed one by one, control over the ShinyHunters brand eventually passed to “
Rey
,”
identified last year
as a teenage hacker from Amman, Jordan. According to the FBI, ShinyHunters has extorted more than $70 million from victims so far this year.
In late September, ShinyHunters
hacked the FBI
recruitment website
fbijobs.gov
and taunted the agency by threatening to publish the stolen files, which reportedly included medical and psychological records, Social Security numbers and home addresses, and information about each employee’s unit and specialization.
The FBI jobs site hack has prompted the agency to move with uncommon speed to arrest, detain and question people who had any communications with Rey or other ShinyHunters suspects.
Reuters
reported
on October 3 that Rey had been detained by Jordanian authorities and was cooperating with the FBI.
Rey was able to assume control over the hacking group because one of its alleged senior members had just been nabbed. On the evening of September 15, 2026, authorities in the Netherlands
arrested
convicted hacker and ShinyHunters suspect
Pepijn van der Stap
. Dutch police reportedly used flash-bang grenades in an effort to stun and apprehend Van der Stap as he was logged in to various online accounts.
According to a source close to the investigation, the authorities arrested Van der Stap while he was using his Signal instant messaging account, which allowed them to read recent communications with frequent contacts — including ransomware negotiators based in Canada and the United States.
Multiple sources with knowledge of the matter told KrebsOnSecurity that Van der Stap’s messages were the key to unraveling a murder-for-hire plot that emerged immediately following his arrest. The Dutch news outlet
RTL
reported last month the two murders were allegedly to be committed abroad, and that there are indications Van der Stap gave the order for the attacks (there is no indication those orders were ever carried out).
On October 9, KrebsOnSecurity
broke the news
that the FBI arrested a 54-year-old Canadian cybersecurity executive named
Edward Dubrovsky
in connection with the ShinyHunters investigation. Dubrovsky, who recently
published a book
on handling cyber extortion that recommended always engaging with the hackers, was charged with threatening to disclose stolen or hacked data and interfering with interstate commerce through extortion, according to
court records
.
Politico
reports
prosecutors have asked that Dubrovsky remain in custody pending trial, and that records related to his case remain under seal.
A source close to the investigation told KrebsOnSecurity that Van der Stap’s Signal messages showed he had frequent conversations with Mr. Dubrovsky and with at least one executive at a large U.S.-based consulting firm, and that these executives often knew the details about new ShinyHunters victims before the victims themselves had even learned of the breach.
That source shared another potentially explosive finding by federal investigators: the Dutch hacker’s chats showed Mr. Dubrovsky knew ShinyHunters had stolen highly sensitive data from FBI servers, and that he never informed the bureau of the data breach prior to ShinyHunters threatening on Twitter/X to publish the agency’s deeply personal personnel files.
SHINYWIRE
KrebsOnSecurity has learned from two sources close to the ShinyHunters probe that FBI investigators believe at least one executive at a U.S.-based consulting firm played an active role in operating the now-defunct ShinyHunters victim extortion website “
shinywire[.]com
.” KrebsOnSecurity is not naming the U.S. company or the suspected executive(s) for now because they have not yet been charged with a crime, but it is a prestigious firm with more than 1,000 associates.
A section of the homepage for the now-defunct Shinywire website.
The Shinywire website was active from approximately May 3, 2026 until October 16 and had entries for nearly 100 organizations hacked by ShinyHunters. Each entry urged victims to engage with the cybercrime group and discuss terms for payment. The pages also included samples of stolen files and promised those files would be published online if the victim ignored their demands.
The following screenshot shows
a cached portion
of the Shinywire extortion page for
Intuitive Surgical
, an American medical technology company that was
breached in March 2026
after an employee fell for a targeted phishing email.
The Shinywire website, as indexed by urlscan.io. This listing is an extortion demand targeting Intuitive Surgical, an American medical technology company breached in March 2026 by a targeted phishing email attack that compromised an employee’s credentials.
Victim organizations that refused to engage or negotiate after seven days would find all of their stolen data published on the ShinyHunters victim shaming blog (a website that is only reachable via the anonymity network
Tor
).
In a story published October 15,
The Globe and Mail
wrote
that a few months before Edward Dubrovsky was arrested by the FBI, the Canadian cybersecurity executive alleged in court documents he had become collateral damage in a campaign by a former business partner to “destroy” another industry executive.
The story noted that Dubrovsky filed the lawsuit in Ontario this year against
Daniel Tobok
, the former chief executive of
Cypfer
, a cybersecurity firm founded in Toronto with offices in the U.S., Britain, the Netherlands, the United Arab Emirates, and Mexico. The two first became business partners in 2017 and later developed Cypfer together, where Mr. Dubrovsky was a managing partner and chief operating officer. But by 2024, the two had a falling out, with Dubrovsky accusing Tobok of gradually excluding him from business matters and making “increasingly capricious business decisions.”
Mr. Tobok reportedly denied the allegations and filed a counterclaim, accusing Mr. Dubrovsky of accessing confidential information and unfairly competing with Cypfer through work at another firm called
CyberSteward Inc
. He also said Mr. Dubrovsky has misrepresented himself as a Cypfer founder, and is not a shareholder.
GHOSTBYTE
According to interviews with several former colleagues of Mr. Tobok, as far back as eight years ago he was known to ransomware purveyors by a particular nickname:
Ghostbyte
. In 2018, a Canadian company was hacked by
Dharma
, a prolific Russian-language ransomware affiliate program that first surfaced in 2016. The victim company told the Dharma ransomware representative they were leaning toward paying because some of the files were unrecoverable after being locked, but that they needed a better guarantee that Dharma would keep their word if paid.
A redacted copy of the Dharma rep’s reply is pictured below, and it shows the ransomware group urged the victim to contact a person at a Canadian IT firm that helps companies seeking such guarantees. The Dharma rep recommended the victim contact the email address
ghostbyte@tutanota.com
.
“If you want guarantees, you can write to the IT company,” the Dharma reply advised. “Take the phone and negotiate with them. This IT company often solves such problems in Canada. You can contact them and sign a contract for services. You’ll still have to pay.”
An email reply from the Dharma ransomware group to a victim, recommending they contact an email address that is connected to Mr. Tobok.
It’s unclear if Mr. Tobok ever used that Ghostbyte address offered by the Dharma representative, and he has not responded to multiple requests for comment. However, the breach tracking service
Constella Intelligence
finds an email address Mr. Tobok has frequently used —
dtobok@me.com
— is associated with two online accounts where the chosen username was “ghostbyte,” including a Snapchat account.
Incidentally, Constella also finds the Dharma rep’s email address
luckygoodlucky@tuta.io
is associated with
a cryptocurrency address
that processed 38 transactions totaling 43 bitcoin, ~$3.5 million at today’s value (the most recent transaction for this wallet is dated February 2019).
In a statement shared on October 14, Cypfer said the company’s business does not include making or facilitating ransomware payments, and that Cypfer learned of Dubrovsky’s arrest when the news first broke in the media.
“We had no prior knowledge of Mr. Dubrovsky’s arrest,” a spokesperson told KrebsOnSecurity via email. “
CYPFER
has not received any outreach from law enforcement and, to our knowledge, is not the target of any law enforcement investigation.”
The statement said CyberSteward and Cypfer are separate companies with no officers, directors or employees in common, and that Cypfer was recently acquired by the
Apros Group
, a holding company led by
Jason Hogg
, a former FBI special agent and former CEO of
Aon Cyber Solutions Group
. In 2020, Aon aquired
Cytelligence
, a security consulting firm where Mr. Tobok was founder and CEO and Mr. Dubrovsky was a managing partner.
CONFLICTING INTERESTS
It is not illegal in the United States to pay hackers for an encryption key to unlock servers infected with ransomware, or in exchange for a promise to delete any stolen files and refrain from publishing them online. While victim organizations can land in legal hot water if they pay a ransom to a group that is sanctioned by the U.S. Treasury Department, ShinyHunters is not among the ransomware groups currently sanctioned by the United States or by any other government.
Experts say ransomware victims are typically directed by their insurance provider to work with a specific incident response firm. But not all cyber forensics and breach response companies will agree to facilitate payments to ransomware groups on behalf of their clients. As a result, once victim firms make a decision to pay, the firms that eschew rewarding extortionists are invariably replaced by companies that have no such qualms.
In December 2024, ShinyHunters began extorting the education technology company
PowerSchool
, stealing private information on 62 million students and 9.5 million teachers in the U.S. and Canada. PowerSchool reportedly paid a $2.85 million ransom demand, and a
“frequently asked questions” statement
(PDF) about the breach says PowerSchool was assisted in that effort by CyberSteward (ShinyHunters affiliate
Matthew Lane
, 20, of Sterling, Mass., was
sentenced in November 2025
to four years in prison for his admitted role in the PowerSchool hack).
But that ransom payment did not stop future extortion attempts using the same stolen data. By May 2025, individual school districts were
reportedly
receiving separate ransom demands using samples of the same stolen files. While nobody has alleged ShinyHunters was behind the second wave of extortion against PowerSchool users, the incident drives home the reality that there is no technical way to verify the threat actors have deleted the stolen data as promised, or prevent others from abusing the same records.
A number of leading cyber incident response firms, including
Coveware
and
Unit 221B
, have
consistently warned victims against paying ShinyHunters
, noting that “destroyed” victim data is often kept, resold or used to extort the company’s clients directly later on.
The FBI echoed those sentiments in
an alert
on May 15, 2026 advising victims against paying the ShinyHunters group. Meanwhile, ShinyHunters members have been harassing and threatening employees at Coveware and Unit 221B for offering this advice.
The following screenshots show just how annoyed the ShinyHunters leaders were with Coveware’s relentless advice against paying the group. The first image is from a conversation on May 6, 2026 that took place between the group’s main account on Telegram and a co-conspirator. In that chat, snippets of which were shared with KrebsOnSecurity by a trusted source, ShinyHunters complained that Coveware was harming the group’s payment rates.
The operator of the ShinyHunters account on Telegram speaking privately with a co-conspirator and complaining that Coveware was harming their business.
“Go on my website, majority of those companies would’ve paid if it weren’t for Coveware giving them misinformation,” the ShinyHunters account wrote. “Someone (100% Coveware) is going out of their way to make sure i am not paid.”
In another conversation on April 11, 2026, the ShinyHunters Telegram account privately said they were trying to “eliminate the problem,” which they said was Coveware.
“I’m sure the company will pay but in this specific case I am aware of Coveware and their involvement, and I’ve probably been not getting a lot of other negotiations mostly likely because Coveware keeps getting involved,” the ShinyHunters account bemoaned.
The operator of the ShinyHunters account on Telegram telling a co-conspirator they were “trying to eliminate the problem,” which they identified as Coveware advising victims not to pay the cybercrime group.
Coveware CEO
Bill Siegel
said he was unable to comment on anything related to past clients or ShinyHunters, beyond stating that the FBI has notified the affected victims of Van der Stap’s alleged murder-for-hire scheme, and that no Coveware employees were notified.
Mark Camillo
is chief executive at
CyberAcuView
, an industry group founded in 2021 by a consortium of major cyber insurance carriers. Camillo said some firms charge a flat retainer fee, while those that specialize in helping companies negotiate a ransom payment tend to charge a percentage of the total ransom amount paid.
That latter dynamic, he said, is an inherent conflict of interest, as the negotiator has every incentive to make things more favorable to the attackers because they are financially incentivized to negotiate and pay out, and to not negotiate down on the price.
“It has come to the industry’s attention that many of the ransomware payers charge a percentage of the final payment which may or may not be disclosed,” Camillo said. “This makes no sense if they are also the negotiator. There needs to be more transparency in the process as no one in the ecosystem should be profiting purely on the size of the ransomware transaction or payment itself.”
Camillo said the firms doing this work would argue the fees are needed because there may be unexpectedly higher costs to secure larger quantities of cryptocurrency or more risk carrying the float, and because cryptocurrency exchanges may charge higher fees for high risk transactions.
“There definitely needs to be more visibility around the transaction and clarity on the increasing value of the crypto and the exchange’s percent in the transaction to get to the bottom of this and remove any misaligned incentives,” he said.
In recent months, the
U.S. Department of Justice
has prosecuted a number of ransomware negotiators alleged to have conspired with cybercriminals to defraud their clients. On October 7, the DOJ
charged
MonsterCloud CEO Zohar Pinhasi
, 50, with wire fraud and conspiracy for allegedly charging customers to remediate ransomware attacks without paying the hackers. According to charging documents, Pinhasi secretly went behind his customers’ backs and paid hackers anyway, paying ransomware groups $8 million while charging customers $19 million.
In July,
Angelo Martino
, a 41-year-old ransomware negotiator from Land O’Lakes, Florida, was
sentenced to 70 months in prison
for conspiring with the Blackcat/ALPHV ransomware group to extort multiple victims. According to the DOJ, Martino was paid by BlackCat attackers to provide confidential information about the negotiating position and strategy of his employer’s clients and enable the ransomware actors to maximize the ransoms paid by the victims.
Maxwell: A new kind of model that sits between code and hardware
Maxwell understands and improves code while it runs, reasoning about hardware and data, not just code. Every improvement is formally proven equivalent to the original code.
Read the manifesto
38
×
faster data processing pipelines
4.25
×
faster AI inference kernels
What is a code execution model?
A short animated film, with narration and captions, introducing Maxwell: most code never sees the hardware it runs on or the data it processes. Maxwell watches a program while it runs, rewrites the binary underneath to fit that exact machine and data, and formally proves every improvement equivalent to the original. It runs on CPUs and GPUs, speeding up data pipelines and AI inference kernels.
Featured customer
LTX-2.5 generates 4K video in half the time
LTX built LTX-2.5 for efficiency from day one, compiled end to end,
sequence-parallel
across GPUs, decoding on a
hand-written
attention kernel. A pipeline built and optimized by top human experts. Maxwell made their 4K generation nearly twice as fast.
See Maxwell in action optimizing both GPU-based and CPU-based code. Once Maxwell has enough runtime data, it swaps in formally proven optimizations tailored to that exact machine while the program keeps running.
GPU-based speech-to-text using Whisper
Two terminals run the same Python script on the same RTX 4090: 180 transcriptions with Whisper-small from a cold start. Without Maxwell, on the left, it takes 106.23 seconds. With Maxwell, on the right, it completes in 49.82 seconds. Both produce identical transcripts. The recording plays at 4× speed.
CPU-based graph algorithms
Two terminals run the same Python script on the same machine: NetworkX betweenness centrality, 15 runs. Without Maxwell, on the left, it takes 61.44 seconds. With Maxwell, on the right, it completes in 17.50 seconds. Both print identical results. The recording plays at 4× speed.
If you see weird fonts and spacing, blame Blogger.
Skip to "In the wild exploitation" if you just care about that part.
It's just a cryptominer. On one hand that's not a big deal for victims on the other hand, I don't get interesting c o n t e n t to write about.
I wouldn't be surprised if threat actors deploy more sophisticated things. Plex may be hosted on residential IP and I think threat actors would love to have residential IP proxy to access corporate VPNs and emails. (edit: see update at the bottom. i do see proxy being deployed now)
As an infosec person and a Plex user, I was really curious about what this vuln was and if I could see in-the-wild exploitation. I set up a honeypot w/ a vulnerable Plex version running.
The details were limited and they said that they'd update the page with more details so I kept watching and didn't see anything.
Link was to
https://zmain.info/blog/plex2shell
and release was supposed to be mid Oct so I waited and finally saw an update on Oct 16th (yesterday). The author had discovered and chained several vulns together to get remote code exec which was pretty cool.
My honeypot mostly saw scanning and generic exploitation attempts.
As of this morning (Oct 17th), I finally saw in the wild exploitation.
So by default, I don't allow outbound traffic from my honeypots but due to how this vuln works, I had to go modify my settings later on so sadly I didn't get payloads for all the attacks. It's possible that I have partial data. I haven't gone through pcaps and I had to modify settings for tcpdump anyway. The attacker could be using slightly modified code & technique too.
Here's what I observed:
First exploitation attempt came from 45.194.92.222. From zeek logs:
An investigation by NorForge into publicly exposed AI-driven penetration-testing control panels has uncovered how they are extensively used in malicious cyber operations. One of these is Cairn.
In this setting, Cairn is an AI-powered hacking system. Give it a target and an objective, and it can coordinate AI agents to investigate the target, search for security weaknesses, and attempt to break in.
More than 20 exposed Cairn panels were identified as likely associated with malicious activity, providing an unusually detailed view of how threat actors select targets, direct autonomous agents, exploit vulnerabilities, and establish persistent access to compromised systems.
In addition, a considerable number of apparently legitimate red team operations were also exposed this way, potentially placing clients at risk.
02
The Opening
In September 2026, Gambit Security reported on a criminal intrusion campaign targeting online marketplaces. They recovered an attacker’s staging server and found the use of AI harnesses, such as Hermes, Strix, and Cairn. Important information, that is. Such tools frequently have web based user interfaces that are left unsecured on the open web.
Sure enough: Quick searches using the Shodan and Censys search engines reveal hosts running what appear to be AI harnesses of different kinds. Most need authorization to access. Most.
But there are quite a few of these interfaces left open by their operators. And apparently, one of the most neglected platforms is Cairn.
Our searches initially revealed a handful of open Cairn panels. Continued scans revealed new panels coming online in short order; and targeting information, language and instructions showed many of them to belong to the same threat actors.
In this article we will detail some of these. However; it is the nature of these panels that they reveal a great deal of sensitive information about the targets; including who they are, what weaknesses have been uncovered, account secrets and API keys, and whether they have been compromised or not. This means that we must aggressively redact extracted data and won’t disclose the panel addresses until they can be taken down.
Operator task containing secrets. Even root access to the attacker’s data drop is exposed.
03
The Machine
A Cairn panel with a few active or completed projects. This belongs to an unrelated actor; conveniently not using recognizable target tags.
Some describe Cairn as an autonomous penetration testing engine. This is not entirely accurate; it can be used that way, yes, but its use case is more generic: It is a state-based problem solving engine, moving step by step in the general direction of a defined solution.
But in our case – yes, it is used for penetration testing.
In Cairn, each separate task is considered a project. Every project has a start point called an origin, and a predefined end goal. The agent framework then progresses from origin towards goal in a state-based organic growth.
Between start and end are cycles of intents and facts. A fact is something the agent has discovered, and an intent is what it has decided to do next. The agent posts every fact onto a project-internal blackboard. A human operator can also add their own hints to the same blackboard. Facts and hints are in this way data available to every agent worker on the path towards the defined solution. This can be visualized graphically, which also Cairn does.
The progress from origin in cyan to goal in red. Not all paths succeed. This attack was directed at a major US online retailer, and ended up in GOAL MET: Webshell injected into the site.
04
The Actors
Cairn panels are regular web fronts, and can be readily profiled using commercial internet scanning platforms. Over a period of a few days, we found numerous such panels. Some were empty, some were protected against unauthorized access, and some appeared to be legitimate demos or valid pentesting outfits. We will not be outing legitimate red teams here, but it is clear that placing real customer penetration tests on an unsecured panel is highly problematic.
But even filtering out those, more than 20 such panels were identified as likely malicious. As far as we could see, all appeared to have financial motivation; there was no obvious state-sponsored intrusion activity. That is not to say that this does not happen, but one assumes that type of actor knows how to secure dashboards.
Much of the observed activity seemed to coalesce around a handful of clusters, where the exposed panels contained information that tied them together.
We denote each activity cluster by a serial number starting with the “AIA” prefix; meaning “AI Activity”. The acronym for AI Threat Activity was already taken.
Cluster
AIA0001
Language
Chinese
Panels
14
Hosting
AS56594
Confidence
High
This activity cluster uses Chinese language, and is by far the most active of the actors that expose their panels. The operation is massive, with over 1100 attack projects spread over the 14 dashboards likely associated with this group.
AIA0001 targets a wide swath of organizations, mostly in the US, Japan and Australia. The aim seems to be to gain persistent access to e-commerce/payment infrastructure for later monetization.
This group currently seems to prefer hosting their panels via AS56594, Cgi Global Limited. We assess this cluster to be malicious with high confidence.
AIA0001 target selection.
This actor appears to use extensive automation in its task feeding pipeline. Consider for example this task, which is quite typical:
A typical automated task.
Translation
These are confirmed real shopping/e-commerce websites in four countries (US/CA/JP/AU), with traffic of 200,000–1.5 million. Playwright has verified that orders can be placed.
Objective: Find unauthenticated RCE (command execution/code injection/deserialization/file-upload webshell/SQL injection leading to RCE/SSTI/SSRF leading to RCE).
Payload: Uploader shell (HTML upload form + move_uploaded_file to save files), explicitly not a command-executing webshell.
The feeding pipeline includes automated validation of target sites. Not only are they ranked by traffic, but they have also been tested using Playwright, Microsoft’s browser automation framework, before sent to Cairn for exploitation.
There are also other hints at automation; and some are of the silly kind. For example; a lot of target sites across multiple panels have had an initial letter “w” removed. ‘Wholesale’ becomes ‘holesale’ and “winter” becomes “inter”. This suggests that there is a common, buggy domain normalizer that removes a “w” too much from the www. It makes spotting related panels very easy.
Every now and then, these attackers will open a web server on a high port to do out of band testing. In these short lived time windows, the working directory of one of these AI workers will be available for browsing. This happened at least once with one of the AIA0001 hosts, and that gave us the opportunity to get a closer look at the tooling available for the agent.
In this particular case, we found:
Tools found on agent worker folder
Software / package / tool
Use case
Playwright
Browser automation and web testing; the profile directories are Chromium browser state rather than source packages.
Chromium
Browser engine used by Playwright and related browser automation.
PHPGGC (PHP Generic Gadget Chains)
Generates PHP unserialize() gadget-chain payloads for authorized vulnerability validation and exploit research.
StyleSmuggler HTTP PoC
Research proof-of-concept for the StyleSmuggler / CVE-2026-75650 Magento report-poisoning-to-code-execution chain.
Deprecated Magento module intended to block executable-file uploads through cart custom-option uploads.
Docker
Container build/runtime tooling used for isolated validation environments.
PHP
Runtime and scripting language for PHP payload generation and testing PHP web applications.
Composer
PHP dependency/package manager; the manifest identifies the Magento PolyShellPatch package.
Python 3
Main scripting language for reconnaissance, HTTP testing, parsers, proof-of-concept code, and automation.
Node.js
JavaScript runtime/tooling used by web probes, browser automation support, and target-specific scripts.
Vosk
Offline speech-recognition toolkit/model.
OpenSSL
TLS/cryptographic command-line and configuration tooling.
Xvfb
X virtual framebuffer for running GUI/browser applications without a physical display.
tmux
Terminal multiplexer/runtime state, typically used to keep long-running sessions and listeners alive.
OWASP Amass
External attack-surface discovery and subdomain enumeration.
dnsrecon
DNS enumeration and reconnaissance.
ffuf
Fast web fuzzer for directory, parameter, virtual-host, and content discovery.
Nmap
Network/port/service scanning.
rockyou wordlist
Large password wordlist commonly used for authorized password-audit and credential-testing workflows.
Odoo framework artifacts
Extracted Odoo server/module source or probes used to understand Odoo web, ORM, QWeb, and action execution behavior.
Various custom utilities
Project-specific proxying, payload validation, traffic capture, patching, and proof-of-concept utilities.
But more importantly, one of the agent task updates contained this text:
Agent task update
The local environment is a Kali container, belonging to the tsec CTF/intelligent penetration test competition framework (there is a flag submission interface description in
/home/kali/workspace/.claude/skills/tsec-actions/SKILL.md
, with the flag format being
flag{...}
), but the environment variable
TSEC_SERVER_HOST
is empty and
TSEC_AGENT_TOKEN
is not actually injected, so the competition submission interface cannot be accessed
This would seem to indicate that the agent setup was repurposed from an earlier Tencent CTF challenge configuration. This is almost certainly criminals reusing existing tools, and there is no reason to believe that Tencent had anything to do with this operation.
From what we’ve seen, all tasks were performed by a worker named
claudecode_deepseek-v4.1-flash
, which could mean a Claude Code harness using the Chinese DeepSeek 4.1 Flash model that was released in September.
We dont have actual numbers on token usage, but with the underlying data it's possible to guesstimate. Deepseek 4.1 Flash is an inexpensive model, but cost varies between peak and non-peak hours, and whether the tokens are cached or not. We estimate the average cost of a task to end up around $5 if one includes unsuccessful, early ending projects. Longer running projects could get more expensive - there are projects with over 1000 intents and facts, and those could end up costing more than $100. The uncertainty here is however considerable, and numbers could be off by a clear margin. Even so, there's no doubt that this is relatively cheap.
Cluster
AIA0002
Language
English
Panels
10
Hosting
AS20473
Confidence
High
This cluster uses English language, and is oriented towards financial theft. We found 10 panels likely associated with this group, though some of these are less confidently linked. Many of these have also gone dark since the start of this investigation.
They frequently directly talk about stealing credit cards and cryptocurrencies, and uploading stolen data to separate hosts under their control. They – incredibly! – expose the SSH login to backend staging hosts in their taskings. (No, we did not log into their servers, although we were sorely tempted.) It is interesting to see that many projects seem to have no technical starting instructions, beyond "fetch credit cards" or "fetch crypto". The agents just go from there.
This group prefer hosting their panels via AS20473, The Constant Company (in most cases this means VULTR VPS instances). We assess this cluster to be malicious with high confidence.
The targets listed in these panels are mainly oriented towards merchant payment services, gray-market payment sites and pharmaceutical sites; even a clearly criminal carding site. There are indications that they successfully breached some of these.
Out of the targets that do not fit into those categories, several are African commerce sites, which hints towards this actor having a base on that continent.
AIA0002 target sectors.
The projects run by this actor state they use workers named pi_openrouter_deepseek, suggesting a configuration in which the Pi coding-agent framework uses DeepSeek language models through OpenRouter, a third-party AI model API gateway.
Cluster
AIA0003
Language
English
Panels
1
Hosting
AS200019
Confidence
Low
This entity exposes only one panel, with 59 projects listed. The targets are a mix of smaller e-commerce sites and very large US-based commercial platforms. Language used is exclusively English. The panel is hosted on AS200019, AlexHost.
The projects listed on this panel start out claiming to be authorized assessments of various sites, but then gradually become more explicit about exploiting the targets including obtaining shell access, admin panel access, or database access.
This actor seems more in the exploratory stage. We assess this actor to be malicious with low confidence.
Project creation activity across the three clusters.
05
The Exploitation
Whether a task has succeeded in reaching its goal, and whether that constitutes a real-life security problem, depends a lot on how aggressive a goal is. In some cases, tasks stop when establishing whether there is a vulnerability. However, the threat actors covered in this article typically go further.
Previously, we posted one of the tasks used by AIA0001. That task explicitly demanded a webshell to be installed, in order for the goal to be reached. Just to test, we checked if one of the claimed intrusions had really happened by fetching the shell URL mentioned in a completed task against a large hardware parts vendor. The URL did indeed serve an uploader webshell. Attackers can at any time change that into something more malicious.
Live uploader web shell served from a vendor site.
This particular intrusion was apparently – according to the agent’s own explanation – enabled by unauthorized write access to a memcached session store, combined with unsafe PHP object deserialization and an exploitable gadget chain in legacy Zend Framework components. However, all these exploitation paths are different, and the payload can look different as well. We have gathered a number of case studies at the end of this paper.
AIA0001 seems to exclusively go after access, and make sure they have the ability to do more at a later date. Other actors have other goals, but this threat actor appears to have been by far the most proficient and effective in reaching their target. The AIA0002 actor uses Cairn in a more generic way. Not only is it used to break into targets, but it is also used as a general purpose service engine; for example to move funds between crypto wallets.
Task types
Activity
Typical task goals (literal quotes)
AIA0001
这是四国(US/CA/JP/AU)已确认的真实购物电商站(流量200k-1.5M)。
目标:找未认证 RCE (命令执行/代码注入/反序列化/文件上传webshell/SQLi→RCE/SSTI/SSRF→RCE)。
优先:登录SQLi、未认证端点、文件上传、反序列化、认证绕过、账户接管。
落地用 uploader shell (HTML上传表单+move_uploaded_file保存),绝不落地命令执行型webshell。
Goal met when whoami/id 输出确认命令执行。
AIA0002
upload web shell in hidden dirctory deep inside not on home dirctory and name it somthing normal like confirm.php etc and give me link
AIA0003
Obtain shell access, admin panel access, or database access on REDACTED. Try all attack vectors: SQLi, file upload, authentication bypass, RCE, deserialization, SSTI, SSRF, business logic flaws. Build dynamic attack chains.
06
The Success Rates
The different activity clusters have different focus, go after different targets, and what constitutes success varies. They are not directly comparable. But it is a reasonable assumption that for the harnesses we have seen in these campaigns, average success rate is hovering around 10%, with many of the remaining tasks achieving partial goals, or are able to gather information that can be used in later attempts.
Average success rate
~10%
Start to goal, AIA0001
<23h
Facts per project
140
Observed AI-driven intrusion campaigns and reported outcomes.
If we concentrate on the tasks that did reach their goals, especially on the AIA0001 cluster which most resembles general purpose intrusion activity, we can now see that the average time from project start to goal met was a little under 23 hours, generating on average 140 facts per project. However; there’s a wide range here. One project ran for more than five days. It is also worth noting that this is a snapshot at this point in time. Models and harnesses evolve very quickly.
07
The Exposure
These panels not only expose that a site is being tested for weaknesses, and any conclusions of the tests. They detail everything that the agent has discovered in the process, and if that was not enough, they include human input that includes credentials harvested elsewhere.
In other words, having your site tested on an open Cairn instance is often a serious security issue, regardless of outcome of the test.
We ran the secrets scanner Trufflehog over the data from these Cairn instances.
Credentials exposed in AI-driven operations.
The result was concerning. Literally hundreds of secrets of different kinds, from relatively trivial to extremely serious; with 11% verified valid by Trufflehog.
Think that's bad? It gets worse. These panels appear completely unprotected, exposing what looks like the full administrative functionality of the harness. That includes controls for starting and stopping projects, interfering with ongoing operations, inserting new data, redirecting agents to different targets, and restarting old projects. We haven't tested whether these controls actually work without authorization, for reasons that should be fairly obvious. But consider the implications. These are autonomous offensive agents with considerable capabilities, potentially available to anyone who stumbles across their control panels. Tokens could evaporate like dry ice on a hot plate. And who knows what these agents could be persuaded to do that would make their owners weep. Just to be clear, we walked away from that train of thought. But the underlying point remains: Whatever offensive expertise these operators possess, securing their own infrastructure does not appear to be among their strengths.
08
The Conclusion
It is clear that AI-driven frameworks are used to perform malicious actions. That was established well before this paper. However, this research has pointed out something else: The attackers are not well prepared for this technology either. In the rush to gain quick results, many have forgotten basic security precautions, leading to them compromising their own operational security and also, unfortunately, exposing their targets to a far larger attack surface than the intent was. This has also proven to be a problem for legitimate red teams; gathering secrets from your client just to publish them on the Internet is a nightmare scenario.
But it is an interesting window into the methodology, and how autonomous and semi-autonomous agents solve real world intrusion tasks. This could and should inform our defenses going forward.
We have been cooperating with Reuters in notifying victims, particularly those who appear to have suffered a compromise. We are also attempting to get the offending Cairn panels taken down. This might not be possible; it depends a lot on how well the hosters respond to takedown requests.
A
Case studies
Case 1
Australian e-commerce site
The Cairn backend stated that goal was met and indeed, there is a shell giving command execution on the web server.
Command execution through the shell on the web server.
The attack chain, from unauthenticated account modification to command execution.
Case 2
Restaurant POS compromise
Restaurant POS compromise.
Case 3
Web application intrusion on US retailer
US retailer web application intrusion.
Case 4
Another US retailer, this time via insecure error handling
Insecure error handling.
Case 5
Japanese retailer
Japanese retailer.
Case 6
Very large US retailer
This compromise chain was validated by us. The agent managed to find the one cookie setting that chose the vulnerable backend server.
B
Indicators of compromise
We are sorry that we can not provide unredacted data on where these panels are. Many are still live and contain sensitive data. However, if you are a bona fide security researcher, reach out and we will be happy to provide the unredacted list.
The days are getting shorter. There is a chill in the air. Darkness is encroaching. Our primal fears of the coming deadly winter need to be expressed.
That is what Halloween is all about, after all—a festival of death, a celebration of decay, a much-needed annual reckoning with the fact that like the drying grass and the falling leaves, we will not live forever.
Some of us understand that we will cease to exist: ashes to ashes dust to dust etc. But others are really not getting that. You can tell who's who based on the Halloween decor on display.
What follows is NOT an evaluation of Halloween decorations based on the traditional metrics of "effort," "creativity," and "spookiness." I have not even considered logistical challenges such as year-round storage. You won't see a single carved pumpkin.
No, whether you like it or not, by decorating your stoop, you have opted into a citywide dialogue about what happens when you die.
In ranking the following decorations adorning homes in Brooklyn, I am weighing the complimentary attributes of whimsy and horror, to derive how much (or indeed, if at all!) the decorators grasp their own mortality.
Stripe is paying nearly 6x OpenRouter's three-month-old valuation for a company that doesn't build AI models. It builds the switch that decides which model gets used.
Stripe has agreed to acquire OpenRouter, the startup that lets developers tap more than 400 AI models through a single API, in a deal reported at $7.5 billion by The New York Times. Of that, $1.5 billion is earmarked for OpenRouter's founders, with the rest going to investors. The company confirmed the agreement in a joint statement, though neither side disclosed the price publicly. The number alone tells you something: OpenRouter raised $113 million in a Series B round led by Alphabet less than three months before the deal, at a valuation of roughly $1.3 billion. Stripe is paying nearly 6x that number for a company that doesn't make AI models. It makes the thing that decides which model gets used.
Founded in 2023 by chief executive Alex Atallah, OpenRouter built something developers actually needed: one endpoint that routes a request to whichever large language model makes sense for the job, whether that's GPT, Claude, Gemini, or a cheap open-weight model out of China like DeepSeek or Z.ai. According to the companies, OpenRouter now processes more than 10 trillion tokens a day and serves upward of 10 million developers, with customers that include Nvidia, Zoom, and Lovable. Build an AI app today, and there's a real chance you're not choosing a model directly. You're choosing OpenRouter, and letting it choose for you.
That's exactly what makes this acquisition different from a typical infrastructure buy. Stripe didn't just purchase a tool. It purchased the layer that decides, for thousands of apps, whose AI model wins and whose loses.
Stripe's chief executive, Patrick Collison, framed the deal as a bet on where the money actually flows. "Stripe is building the economic infrastructure for AI, and together with OpenRouter we'll help businesses maximize profitability by routing their requests intelligently and spending their tokens efficiently," Collison said in the companies' announcement. That's not marketing filler so much as a fair description of what Stripe has spent the past year building. The company has already rolled out token-billing tools through its Metronome product to track AI usage in real time, alongside Tempo for micropayment settlement and Privy for giving AI agents their own stablecoin wallets. OpenRouter slots directly into that stack: now Stripe can see, bill for, and route the token spend on both sides of an AI transaction, not just process the payment at the end.
It's worth saying plainly that an AI lab didn't win this one. OpenAI, Anthropic, and Google all have reasons to want control of model routing, since it's the layer that determines which of their models actually gets called. Instead, the buyer is a company whose core business is moving money. According to a report from TechCrunch citing people familiar with the talks, Stripe had to outbid other suitors, including Databricks, to land the deal. A payments company beating an AI infrastructure company to the AI infrastructure company says something about how seriously Stripe takes this shift, and maybe something about how much AI labs still see each other as the threat, not the switchboard sitting between them and the customer.
The neutrality problem nobody has answered yet
Here's the real tension. OpenRouter's entire value proposition rests on being neutral. Developers trust it precisely because it doesn't have a dog in the fight between OpenAI and Anthropic and Meta's open-weight models. It just finds whichever one is cheapest, fastest, or best suited to the task. That neutrality is the product. Once Stripe owns the company, every decision about default routing, pricing, or which providers get preferential treatment carries an obvious incentive problem: Stripe makes money on payment volume and token billing, not on which AI lab a developer happens to pick. But Stripe is also a company with its own partnerships to protect, including a newly expanded one with Google announced at its Sessions conference this year that lets businesses sell inside Google's AI Mode and Gemini app.
Neither company's announcement addresses how OpenRouter's independence gets preserved post-acquisition. That's not a small gap. For a developer building a product on top of OpenRouter today, the entire pitch was that nobody was thumbing the scale. Nobody has said what happens to that promise next.
For founders and app builders in San Francisco and everywhere else who rely on OpenRouter to arbitrage between model providers on cost and performance, the practical questions are immediate: does pricing change, does routing logic shift to favor certain providers, and does a single point of failure now sit inside a company whose quarterly incentives don't obviously align with yours. Stripe has a reputation for not breaking developer trust carelessly, Collison has built the company for seventeen years on exactly that reputation. But reputation isn't a technical guarantee, and $7.5 billion buys a lot of incentive to make a chokepoint work harder for its new owner.
At
Goatmire Elixir
this year, I gave a talk about observing a name server that handles millions of packets. Performance came up as a guilty pleasure of mine, and I hinted at some numbers. Afterwards, in the corridors, attendees kept asking the same question: what did you actually do to bring average CPU down so much? This post is the long answer for one big piece of that work: making our DNS library cheaper to run.
First, some context on where this code runs. DNSimple's managed
DNS hosting
has two layers. Queries for your domains first reach our
cache edge
, a global anycast network we build and operate ourselves, which answers whatever it already has cached. Everything else goes to the origin: the authoritative
name servers
that hold every zone and build every answer. The origin runs
erldns
, our open-source DNS server written in Erlang, and since it does the real work behind every cache miss, every query it answers has to be as cheap as possible.
Like many other protocols (HTTP for example), DNS is a request-response system where payloads need to be encoded and decoded as they travel through the wire. So just like a JSON parser is hot code in a JSON API, a DNS parser is hot code for us: every DNS query that reaches a DNSimple nameserver goes through
dns_erlang
twice: once to decode the request, and once to encode the response. At a few queries per second, nobody cares how long that takes, but as queries per second scale, under attack, every nanosecond spent turning bytes into terms and back is a nanosecond not spent answering the next query.
So over the last several months we've rewritten most of the hot paths of
dns_erlang
, the open-source DNS library that powers
erldns
and our authoritative name servers. The result: on a production-shaped workload, our nameserver now spends
12% less CPU per query
and serves
14% more queries per second
before saturating, from library changes alone.
None of it required NIFs, C, or exotic tooling. It came from understanding how the BEAM handles binaries, and writing code that the compiler and the JIT can turn into something fast. If you write Elixir or Erlang, and especially if you parse or produce binary protocols, these patterns apply to your code too. Many of them are not well known, even among experienced Elixir developers, so let's dive into it.
BEAM binaries in five minutes
Before looking at the optimisations, we need a mental model of what a binary is on the BEAM. The
Erlang efficiency guide
has the full details; here is the short version.
Everything is immutable, at least in principle.
On the BEAM, data never changes once it's created: "updating" a tuple, a map or a binary produces a new one, and anyone holding the old one still sees it unchanged. That's a big part of what makes processes and concurrency so easy to reason about, but taken literally it would mean copying on every change. In practice the compiler, the JIT and the runtime cheat whenever they can prove that nobody could notice, that is, when the semantics of the language can be respected: they reuse memory, write in place, or skip the copy entirely. Most of the tricks in this post are about writing code that makes that proof easy.
Slicing and matching are cheap.
Binaries up to 64 bytes live on the process heap, and bigger ones live outside any process, shared by reference. Matching
<<Header:12/binary, Rest/binary>>
copies nothing:
Rest
is a
sub-binary
, a small term pointing into the original. Better still, when a function recursively matches the rest of a binary, the compiler keeps a
match context
, a cursor that walks the bytes, and only materialises a sub-binary if you let
Rest
escape, for example by returning it or storing it in a tuple.
Appending can be (almost) free too.
This is the one that surprises people. Consider:
Naively, each iteration copies
Acc
into a new, one-byte-longer binary, making the loop quadratic. It doesn't, because the runtime can prove that
Acc
came from an append and nobody else is looking at it, so writing in place can't break immutability for anyone. The first append allocates spare capacity, and later appends write into it:
<<Acc/binary, C>> on a binary only this loop holds
+---------------------------+-----------------------+
| bytes written so far | spare capacity |
+---------------------------+-----------------------+
^ next append writes here, no copy
So an append-only accumulator costs amortised O(1) per append, like pushing onto a
std::vector
in C++. The catch: if the binary escapes, if you build pieces separately and glue them together, or if you append the
accumulator
onto something else, you're back to copying.
Integers have a size limit you can feel.
To know each term's type at runtime, the BEAM tags it: a few low bits of every word say what the term is. On a 64-bit BEAM a small integer's tag takes 4 bits, so integers that fit in the remaining 60 (59 bits of magnitude plus a sign) are
small integers
: immediate values that never touch the heap. Anything larger becomes a
bignum
, allocated on the heap. This will matter a lot when we get to SWAR.
Work is counted in reductions.
The scheduler gives each process a budget of reductions (roughly, function calls) before switching to another, so fewer reductions for the same work means more throughput.
Tip
You can ask the compiler where binary optimisations apply, and where they don't. Compile with
erlc +bin_opt_info
, or
ERL_COMPILER_OPTIONS=bin_opt_info mix compile --force
in Elixir, and it will report every match context it keeps and every place it has to give one up.
Every number below comes from
Benchee
on two very different machines (an Apple M4 Pro and an AMD Ryzen 9 9950X3D), on OTP 29 with the JIT, measuring time, memory and reductions. Every change also went through a
parity harness
proving the new code byte-for-byte identical to the old, down to the errors raised on malformed input: 26,434 cases for name decoding alone. And we kept the experiments that lost, with their numbers; we'll get to them.
Pattern 1: one accumulator, appended all the way
Encoding a DNS response means writing a header, the question, and then every record in the answer, authority and additional sections. The old encoder built each section as its own binary and then copied it onto the message. Each record's data (its RDATA) was also built as a separate binary, measured to write its length, and copied in.
Each of those intermediate binaries is allocated, filled, copied and thrown away. The append optimisation can't help, because we keep starting new binaries instead of extending one.
In
#100
and
#139
we turned the whole encoder around: a single accumulator flows through every section, and each record appends itself straight onto it. Even the RDATA length is computed from the parts and written in the same append as the data:
%% Before: the RDATA is built on its own, measured, then copied in.
encode_rr(Acc,RR)->Data=encode_rrdata(RR),<<Acc/binary,(byte_size(Data)):16,Data/binary>>.%% After: the length and the data go onto the message in one append.
encode_mx(Acc,Pref,Exchange)-><<Acc/binary,(2+byte_size(Exchange)):16,Pref:16,Exchange/binary>>.
There was one more wrinkle. A DNS message starts with a 12-byte header whose counters (how many answers, how many authority records, and so on) we only know at the end. So the accumulator starts with 12 zero bytes as a placeholder. Every section is appended after it, and because the placeholder is already there, the accumulator's size is always the current position in the final message, which is exactly what name compression pointers need. When the message is complete, the real header is built and placed in front of the body, in the only copy of the body the whole encoding makes.
On the UDP response path, measured on the M4 Pro, a simple response went from 708 ns to 583 ns and from 1.89 KB to 1.23 KB allocated, and a typical DNSSEC response from 1.33 µs to 1.13 µs.
Pattern 2: stay in the match context
Decoding has the mirror-image problem: it's easy to accidentally force the BEAM to materialise terms it never needed.
A good example is TXT records, which carry a list of length-prefixed strings. The old code delegated each string to a helper that returned a
{Rest, String}
tuple. That's one tuple allocation per string, and because
Rest
escapes inside the tuple, the compiler must create a real sub-binary for it. In
#135
we match the string directly in the loop's head, so the match context survives:
%% Before: a helper returns a tuple, and Rest escapes inside it.
decode_text(<<>>)->[];decode_text(Bin)->{Rest,Str}=decode_string(Bin),[Str|decode_text(Rest)].decode_string(<<Len,Str:Len/binary,Rest/binary>>)->{Rest,Str}.%% After: match the string in the loop's own head.
decode_text(<<Len,Str:Len/binary,Rest/binary>>)->[Str|decode_text(Rest)];decode_text(<<>>)->[].
The same pull request found a less obvious copy: the decoder stored each section into the
#dns_message{}
record as soon as it was decoded. Records are immutable tuples, so every update copies the whole thing, and this record is 19 words. Updating it four times per message (questions, answers, authority, additional) meant four copies. Passing the sections along as function arguments and building the record once at the end cut 11% of the reductions and 10% of the allocation for decoding a query, which is exactly what every incoming packet goes through.
Pattern 3: match in big chunks, and read the assembly
Domain names are case-insensitive, so
dns_erlang
lowercases them a lot. The old
to_lower/1
used binary comprehensions over 8, 7, 6, … 2-byte chunks, picking the largest chunk size that evenly divided the input:
to_lower_chunk(Data)whenbyte_size(Data)rem8=:=0->...;to_lower_chunk(Data)whenbyte_size(Data)rem7=:=0->...;to_lower_chunk(Data)whenbyte_size(Data)rem6=:=0->...;%% ... down to rem 2, then one byte at a time
It looks reasonable. Then we looked at what the JIT actually generates for it. On x86-64,
rem 8
,
rem 4
and
rem 2
compile to cheap bit masks, but
rem 7
,
rem 6
,
rem 5
and
rem 3
each compile to an
idiv
instruction, which costs somewhere between 20 and 90 cycles. A name whose length isn't a multiple of 8 (most of them) paid for up to four divisions just to choose a strategy, and a prime length paid for all four and then went byte by byte anyway.
The rewrite in
#114
uses plain function clauses that match large chunks first and fall back to smaller ones. A clause like
<<B0, ..., B7, Rest/binary>>
compiles to a single size comparison, with no division anywhere:
Funnily enough, this wasn't the first time that dispatch had shipped. Years ago I contributed the very same trick to OTP's hex encoding in
erlang/otp#4690
, where it made
binary:encode_hex/1
two to three times faster than the
original implementation
. It survived the addition of
binary:encode_hex/2
in
erlang/otp#6297
, until Björn Gustavsson replaced it in
erlang/otp#6869
: a size not divisible by anything from 2 to 7 took about three times longer than the best case, so the new code encodes the largest multiple of 8 bytes in one comprehension and finishes the last few bytes one at a time. The same pull request made
binary:decode_hex/1
almost ten times faster. In other words, the OTP team had already found and fixed this exact pattern in my own code, three years before I found it again in dns_erlang.
The lesson isn't really about
rem
. It's that the BEAM JIT is now good enough that the generated machine code is worth reading. Start Erlang with
+JDdump true
(or
ERL_FLAGS="+JDdump true"
for Elixir) and it writes the assembly of every loaded module to disk. Ten minutes in those files can explain a benchmark that hours of guessing can't.
Pattern 4: SWAR, from a blog post to OTP, Elixir and our nameserver
SWAR stands for
SIMD Within A Register
. Instead of looking at bytes one at a time, you load several bytes into one integer and use ordinary arithmetic and bitwise operations to test all of them at once. The classic trick answers "does this word contain a zero byte?" without looking at any byte individually:
has_zero(V) = (V - 0x0101...01) band (bnot V) band 0x8080...80
Subtracting 1 from each byte only borrows into a byte's high bit when that byte was zero, so the result is non-zero exactly when some byte of
V
is zero. To ask whether a word contains a
specific
byte, say
.
, XOR the word with that byte repeated in every lane first: matching bytes become zero.
On most platforms you'd use a 64-bit word. On the BEAM that would be a mistake, because a 64-bit value doesn't fit in a small integer: the arithmetic would allocate bignums on the heap, and the JIT can't emit plain machine instructions for it. The largest whole number of bytes that fits is 7, so we use
56-bit words
. All the intermediate values stay small integers, and every
band
,
bxor
,
+
and
-
compiles to a bare instruction with no type checks.
Best of all, the whole test is legal in a guard. Here's how
dns_erlang
escapes a label while decoding a name: seven bytes at a time when they contain neither
.
nor
\
, byte by byte only around the ones that need escaping.
In Elixir,
defguardp
plays the role of those macros, so the same guard reads just as naturally there.
Notice how all the previous patterns are in there too: the label is only ever matched, so it stays a match context; the output is a single append-only accumulator; and the clauses go from the biggest chunk to the smallest.
The same idea makes case conversion branch-free. With a couple more subtractions you can find every byte between
A
and
Z
in the word, and flip their
0x20
bit in one go. That's how
to_lower/1
,
to_upper/1
and the case-insensitive comparisons in
dns_erlang
work today (
#124
).
The fun part is that this didn't stay in our library. The same week it landed in
dns_erlang
, we took the trick upstream, to Erlang/OTP and Elixir themselves:
erlang/otp#10938
applies it to the
json
module's string scanning. The JIT output for the hot loop shrank from about 1,750 lines of assembly to about 100, and 768 jump-table entries disappeared. Benchmarks borrowed from Jason improved by 3% to 55%.
erlang/otp#10948
brings it to the
string
module, making
string:length/1
and
string:slice/3
up to twice as fast on ASCII input.
elixir-lang/elixir#15255
does the same for Elixir's
String.length/1
and
String.slice/3
:
String.length/1
got 2 to 5 times faster on ASCII strings.
All three shipped in OTP 29 and Elixir 1.20. If you're on those versions, you're already running this code.
And then the community ran with it. Over the following months, other people brought SWAR to more corners of the ecosystem:
elixir-lang/elixir#15357
applies it to the validation functions in Elixir's
Base
module, making
Base.valid16?/2
and
Base.valid32?/2
about 25% faster.
elixir-plug/plug#1311
adds a 56-bit SWAR guard to the ASCII fast path of Plug's UTF-8 validation.
elixir-mint/mint#513
rewrites Mint's HTTP/1 header parser to read 7 bytes at a time, using SWAR to find the colon and the end of the line while validating the bytes.
erlang/otp#11473
, José Valim's proposal to support byte ranges directly in binary patterns, measures itself against SWAR guards.
It's a nice reminder of how an idea travels in an open ecosystem: from a blog post about C, to a DNS library, to the standard libraries, and from there to code that most Elixir applications run on every request.
Pattern 5: pick keys the VM can compare cheaply
DNS has its own compression scheme: when a name, or the tail of a name, already appears earlier in the message, you write a 2-byte pointer to it instead of the name. The encoder keeps a map from every name suffix it has written to its position in the message.
The old map was keyed on lists of lowercased labels:
[<<"www">>, <<"example">>, <<"com">>]
. Every lookup had to hash or compare a deep term, and a name couldn't be looked up at all until it had been split, validated and lowercased, even when the answer was going to be "use this 2-byte pointer".
Two rounds of work changed that. In
#133
the encoder stopped splitting every name twice, and stopped growing the map one key at a time. Inserting into a small map copies it, so inserting a key per label meant one copy per label; the encoder now collects a name's suffixes and inserts them in one batch. For a name with 50 one-character labels, encoding went from 211 µs to 9.4 µs, 22 times faster. More importantly, an ordinary 8-label name went from 1.51 µs to 0.54 µs.
Then in the
next round
the keys themselves changed: each suffix is now the lowercased name as a
binary
, and each one is a sub-binary of the same name, so they cost nothing to produce and a single
memcmp
to compare. As a result, the raw input name is its own first key, and a name that's already in the map is answered before any splitting or lowercasing happens. That's the common case in a real response: every record in a set repeats the owner name, the answer repeats the question, and glue records repeat the nameserver names. Whole-message encoding got between 1.1 and 8.9 times faster, depending on how much the message repeats itself.
What didn't work
Some of our favourite ideas lost, and the numbers were very clear about it:
Scanning a label first, then appending it whole.
It sounds faster than escaping byte by byte, but it forces the BEAM to materialise a sub-binary for every label. That added 15% to 20% more allocation and erased the win completely.
binary:match/2
with several patterns
to check a label for special characters. It's implemented in C, so it must be fast, right? For short labels like the ones in DNS names, the setup cost made it 1.4 to 2.4 times slower than the inline scan.
Building NSEC type bitmaps a byte at a time.
Decoding them a byte at a time instead of a bit at a time halved the reductions. Doing the mirror image on the encoding side allocated 25%
more
with no speedup, because appending bits to a bitstring is already efficient on the BEAM.
The lesson: the BEAM is often smarter than you'd expect, and the only way to know is to measure.
The bigger picture
Micro-benchmarks are nice, but what we care about is the nameserver. So we built a test that looks like production:
20,000 synthetic zones, 10% of them DNSSEC-signed, with the record mix our customers actually use.
About 19 million queries matching the shape of our real traffic over a week: the same mix of query types and response codes, the same name lengths and label counts, the same skew towards popular names, and the same share of queries asking for DNSSEC (83%).
erldns
built three times, changing nothing but the
dns_erlang
version, pinned to dedicated cores on the same OTP version we run in production, five interleaved rounds each.
dns_erlang
CPU per query
Max queries per second
5.0.5 (February)
24.7 µs
253k
5.0.13 (July)
24.9 µs
250k
5.0.21 (October)
21.8 µs
285k
The summer work (the single accumulator, the decoder changes, the compression keys and SWAR in name decoding) shows up clearly: 12% less CPU per query, 14% more capacity, and lower latency at the same load. The round-to-round variation was below 1%. Profiling the same runs shows that the share of CPU spent inside
dns_erlang
dropped from 33% to 23%, and the share spent encoding responses halved, from 22% to 11%.
On production-class hardware (two Intel Xeon Silver 4215 sockets, with erldns and the load generator on separate NUMA nodes), the same test showed the same picture: 13% more queries per second at saturation, with 16% lower latency.
Just as interesting is what
didn't
move: the spring releases, with the faster
to_lower/1
and the first SWAR work, made those functions up to 30% faster in isolation, but end-to-end they're flat. Those functions simply weren't where a nameserver spends its time. A 2x speedup on 1% of the work is still 0.5%.
On a profile of one of our production nameservers, which also does things this test leaves out (ALIAS resolution, query analytics and telemetry),
dns_erlang
now accounts for about 9% of the busy CPU time. Which tells us where to look next: the biggest single piece today is the zone cache lookup in
erldns
, at about a third. That's a story for another time.
What this means for DNSimple customers
Every percent of CPU we save per query is headroom we get back. It means more room to absorb traffic spikes and attacks before the
load-shedding mechanisms in erldns
have to kick in, and lower latency for the queries we answer along the way. Combined with our
fully independent DNS edge
, it all adds up to faster, more resilient DNS for your domains.
dns_erlang
is open source and
available on Hex
. If you build anything that speaks DNS on the BEAM, you get all of this for free. And if you just write Elixir or Erlang that handles binaries, we hope some of these patterns find their way into your code.
If you have questions about
dns_erlang
,
erldns
or DNSimple's infrastructure,
get in touch
. We love talking about this stuff.
Not using DNSimple yet? If you build on the BEAM, every query for your domains would go through the code in this post.
Give us a try free for 30 days
.
How a Massive Chinese Crime Ring Hacked Staples to Steal Millions
403 Media
www.404media.co
2026-10-19 09:23:31
A sophisticated organized crime gang hacked into Staples, issued millions of dollars worth of gift cards, and went on a spending spree across the U.S....
A Chinese organized crime hacked into retail giant Staples, used that access to fraudulently issue millions of dollars worth of gift cards for stores like Target and Sephora, then went on a nationwide shopping spree, shipping many of the stolen electronics and other products back to China as part of a massive retail theft operation, 404 Media has learned.
The finding, based on a review of court records, reveals the scale at which some organized crime groups are fleecing U.S. retailers, with entire warehouses dedicated to housing the merchandise. The hack of Staples, which has not been previously reported, signals just how sophisticated some of these operations have become.
💡
Do you know anything else about this case? I would love to hear from you. Using a non-work device, you can message me securely on Signal at joseph.404 or send me an email at joseph@404media.co.
In October 2023, Homeland Security Investigations (HSI) received information from an office supply company, saying that hackers had targeted the company and issued more than 15,000 gift cards worth over $5 million, according to
a search warrant application
unsealed last week. The document does not name the company, but 404 Media determined it was Staples based on various clues: the document says the victim company is headquartered in Massachusetts; uses a company called Blackhawk Network to fulfill its giftcard orders; and the hacked company has an internal customer support system called Nexus. All of those identifying features match Staples, and 404 Media found a reference to Nexus on a former Staple’s executive’s LinkedIn profile.
Staples did not respond to requests for comment.
Screenshots from the search warrant application.
The document says Staples believed Nexus was only accessible to the company’s internal computers, but that the hackers found a way to access it from the outside. The hackers performed multiple heap dump requests, which is a way to capture all of the data held in an app’s memory at a particular point in time, according to the document. Using the returned information, the hackers were then able to hijack the sessions of logged in Staples customer service representatives to then issue the massive wave of gift cards, it adds.
The hackers sent the giftcards to various email accounts they controlled. After this, members of the gang went and spent many of the gift cards on electronics at stores like Target. In one example, Target found 35 of the gift cards sourced from the Staples hack were used at a Target in New Hampshire for Apple, Bose, and Powerbeats products in just one hour. Those purchases included gift cards from the hack and other sources too, according to the document. Surveillance footage showed four men “appearing one after another, occasionally interacting with one another and the cashiers.”
A screenshot from the search warrant application.
“M. CHEN, X. CHEN, JIANG, and the UAM each presented their cell phones to the Target cashier allowing the cashier to scan the electronic Target gift card displayed on their respective cell phones. After an electronic gift card was scanned, all four would use their phone, appearing to access another electronic gift card and presenting it to the cashier to be scanned,” the document says. The men did this until they had “exhausted” all of the gift cards available on their phones, and Target employees later said the four men were well known to staff at the store. They “came into the store almost every day to make numerous large purchases of Apple products using gift cards,” the document says.
Target gave data to investigators showing, for example, the crooks used 3,850 giftcards, worth around $141,000, at 85 different Target stores in 18 states across two days. That encompassed 300 individual transactions, according to the document. Sephora told investigators the gang redeemed around 330 giftcards, worth $58,600, online across 1,500 transactions. Lowe’s, meanwhile, had 450 giftcards, totalling $226,000, redeemed in person and online at more than 22 Lowe’s locations.
Ultimately, the gang was able to use 4,630 of the hacked giftcards, totalling to around $425,000.
The hack is related to a previously announced prosecution of a retail theft ring. Last April, the
Department of Justice announced
three Chinese nationals were sentenced for their roles in the gift card fraud conspiracy. While the newly unsealed document reveals the hack of Staples, the ring was even bigger in scope than the document suggests. The group acquired more than $100 million worth of gift cards, according to the press release.
That press release mentioned the hacking of U.S. companies, but did not name Staples. “The defendants acted as an integral cog of this international scheme by monetizing the ill-gotten gains obtained by Chinese hackers and scammers that victimized U.S. businesses and the citizens of the United States. IRS-CI is committed to our continued collaboration with our law enforcement partners, both at home and abroad, to stop and deter anyone who seeks to profit off the hard work of U.S. citizens,” Thomas Demeo, Acting Special Agent in Charge of the Internal Revenue Service Criminal Investigation, Boston Field Office, said at the time.
About the author
Joseph is an award-winning investigative journalist focused on generating impact. His work has triggered hundreds of millions of dollars worth of fines, shut down tech companies, and much more.
Ante is a low-level
1
functional language built on ownership semantics and borrowing, similar to Rust.
Unlike Rust, however, a core goal of Ante is to be more lenient in its borrow checker, notably by relaxing Rust’s
rule that you can either alias a reference or mutate it, but never both at the same time.
// In Rust:
letmutmy_tuple=(1,2);letfirst_elem=&my_tuple.0;// error[E0506]: cannot assign to `my_tuple` because it is borrowed
my_tuple=(3,4);println!("{first_elem}");
I wanted to allow for code like the above while still disallowing code that would lead to dangling
pointers, and I wanted to do this entirely statically in the type system.
Alas! That’s old news - the
very first
blog post
on this site covered it. That post is frankly quite outdated
now. It’s been years since then
and Ante’s approach has substantially changed, having accrued many additions to make it more flexible.
Now, it has changed again, having blended many elements from
group borrowing
with my own ideas to produce a more
radically safe whole.
In this post, I want to go over the new design and show how it leads to a more flexible kind of safe, shared
mutability that is expressive enough to support
cyclic mutability
and
complex data flow
safely.
Since many Rustaceans are skeptical of the value of shared mutability at all, it’s worth reiterating
why being more lenient here is useful. More lenience means:
Fewer borrow checker errors. Fewer errors both eases the learning curve for
new users and speeds up iteration times for experienced ones.
More design patterns are allowed. The observer pattern is difficult to get working without shared
mutability. Cyclic types can also be more directly represented.
Existing design patterns can have fewer workarounds. Fewer forced indices into vectors in particular.
While this can be a useful pattern, I don’t believe the language should force users into this approach.
More straightforward interop with other languages that also support shared mutability.
The last point in particular is more important than it seems. Ante is meant to be opt-in to ownership
to some extent so that by default using it feels more like C# than it does Rust. This is an aspirational
goal but allowing shared mutability greatly helps here.
Aside: What was wrong with Ante’s previous rules?
I imagine most will not be familiar with Ante’s old borrow checking rules, but for those curious I’ll
lay out some more motivations for the change. If this isn’t you, feel free to skip this section.
I am not most readers
The
original article
mentions Ante’s
ref
and
mut
references as being
&Cell<T>
analogues in a way, and this has largely remained true at its core. Most of the extensions
made since then were to extend this in some way, notably by introducing “local uniqueness” where a shared
mutable reference only needed to be
locally unique
to be used where a
uniq
reference (think
&mut T
in Rust)
was expected. This meant the compiler only needed to show that any variable used at the same time as a
mut String
did not mutably alias it. This ended up taking the form of a
Distinct a b
trait which was implemented if
a
did not occur anywhere within
b
. For example, if you use a
Vec I32
at the same time a
mut String
is
treated as a
uniq String
, the compiler would check a
Distinct String (Vec I32)
constraint in the background.
Since a
String
can’t occur within a
Vec I32
, the code is allowed and the
String
is locally unique. This
would be repeated for each variable used while the converted
uniq String
reference was still alive.
Allowing what is essentially a
&Cell<T>
to
&mut T
conversion like this was great for flexibility but had a few major flaws:
Common types like
String
would occur within other types more often making them more difficult to use
compared to less common types when converted into a
local uniq
reference.
Distinct a b
recurs into every field of
b
, including private fields. This meant adding a private
field to a public struct in a library was a breaking change since it could make previously valid local unique
conversions invalid.
Converting between
mut
and
local uniq
happened often, and was confusing even though the compiler
did it automatically.
It relied on four reference types:
ref
and
mut
which allow shared mutability, and
imm
and
uniq
which don’t.
It wasn’t all bad though. Notably, it was powerful enough to encode
safe, cyclic mutability
, with the caveat
that some
Rc
values had to be cloned (have their reference count incremented) during traversal.
For the reasons above though, it was clear the design had to change. The rest of the article is about the
new design I eventually landed on which fixes all of these issues, but still keeps the good parts
like safe, cyclic mutability
2
and thread-safety.
The Core Problem
Why are some cases of shared mutability safe, like:
The difference is in what I call
shape stability
. If the shape of a type is stable, then there is no way
to mutate it such that a previously valid reference into it becomes invalid. Picturing the references
in memory helps here. Let’s look at how
pair
and
name
look in memory:
Before mutation:
name
|
V
pair: ((first_ptr, first_len, ..), (second_ptr, second_len, ..))
After mutation:
name
|
V
pair: ((first_ptr, first_len, ..), (second_ptr, second_len, ..))
Each
String
is an unboxed tuple of
ptr, len, metadata
, and each component of the
outer pair is also unboxed. With this layout, there’s no way we could mutate
pair
to invalidate
name
!
Looking at
vec
and
elem
however, we see a clear difference:
Before mutation:
vec: (data_ptr, length, capacity)
|
V
[0, 1, 2, 3]
^
|
elem
After mutation:
vec: (data_ptr, length, capacity)
|
V
[]
^
|
elem
elem
is clearly dangling! The problem here is that mutating
vec
can mutate
data_ptr
, causing
it to potentially point elsewhere when it is reallocated. Its shape has changed,
leaving
elem
stranded.
It’d be nice if a reference type could remember whether it’s pointing at something stable or
unstable - then we could do away with uniqueness in favor of a much more accurate restriction that
rejects fewer valid programs.
Places Over Lifetimes
The first core part of the puzzle is the use of
places
instead of lifetimes.
Unlike a lifetime which is some arbitrary symbol representing an abstract region of code a
variable or reference is valid for, a place is the exact set of things a reference may borrow
from:
Above,
r1
borrows from only
x
so it has the place
'x
. Similarly,
r2
borrows from only
y
so it has the place
'y
.
r3
may borrow from
x
or
y
so its place is the union of both:
'(x, y)
.
Places can also be paths such as
'z.bar
to represent a reference borrowing from the struct field
bar
on a variable
z
.
Places don’t always name variables. There are anonymous places as well such as those for a reference
to a temporary like
ref 2
, but that’s not important for this article.
Places make borrow checking easier in general too!
Borrow checking in Ante is actually very simple: whenever a value is used, error if any place it
refers to has already been moved. There is truthfully
a little bit more to it than that, but that really is the core and it can be implemented in only
a few lines of code.
Unstable Places
Once we have places we can model
unstable
places with a simple marker:
!
.
An unstable place like
a!
will be invalidated by any mutation to the place
a
.
This also means if we have 20 variables with place
a!
, we can mutate them all simultaneously
since mutating them would only invalidate variables with place
a!!
.
This is a bit abstract though, so let’s see how this works in practice. Starting off, we have some
Rust code which should be safe but gets rejected by the compiler:
fnrejected(v: &mutVec<String>){// error: cannot borrow `*v` as mutable more than once at a time
let(first,last)=(v.first_mut().unwrap(),v.last_mut().unwrap());*first="Mutate first".to_string();println!("{last}");}
Rust’s compiler rejects this even though there is no way we can mutate
first
which would invalidate
last
.
Theoretically, even if the first element is also the last, this code should still be valid
3
.
We can model this in Ante by flagging any references to returned elements of a vector as
unstable
:
// Declare a `first_mut` method taking a mutable vector and returning// an unstable reference inside 'v to the first elementVec.first_mut(v:mutVect):mut'v!tcanFail=...Vec.last_mut(v:mutVect):mut'v!tcanFail=...
Now, we can write the equivalent of
rejected
just fine:
Above,
first
and
last
both have the type
mut 'v! String
so when we mutate
first
it would prevent us from using anything with a place of
v!!
4
, but nothing does. So we’re
free to use both
first
and
last
even if they alias.
Whether a reference is unstable or not is inferred in practice and doesn’t always need to
be a manual choice by users. Any reference through a tagged union or element of a collection
type will be unstable for example.
Loops
Loops and branching in general are fairly straightforward. They largely follow the same rules
ownership has where an error is issued if a variable declared outside of the loop is
invalidated within it:
varv=Vec.of[1,2,3]one=v.get0for_in0..3doprintlnone// error: one may be invalidated by a later mutation in the for loopv.clear()// note: one invalidated here
Similarly, any closure which invalidates any part of its captured environment is treated
as a
FnOnce
in Rust terms, preventing it from being called more than a single time.
Ante has effect handlers too! Control-flow for them is more complex and the rules
for how they interact with invalidations of unstable places are
documented here
,
but are subject to change (I think they’re a bit hacky). Note that
handle
interactions
with unstable places are (at the time of writing) still unimplemented.
Exclusivity
It’s possible to write functions that are only valid if certain parameters don’t alias:
a_and_b_cant_alias(a:mutVecString)(b:mutVecString)=elem=a.first_mut()b.clear()printlnelem// ok! But how?
In cases like these the compiler still needs some kind of exclusivity rule. In this case,
when a parameter is mutated the compiler needs to ensure the caller of the function gives
a unique value for it:
bad_caller(c:mutVecString)=// error: 'a cannot alias 'b in this use of a_and_b_cant_alias, but 'c was used for botha_and_b_cant_aliascc
To check for this, whenever a mutation occurs the compiler issues a
Mutate 'p
effect
which tags a function with the places that may be mutated. At call sites, each place that
may be mutated must be distinct from other places instantiated
5
. Note that
mut
itself
still allows arbitrary aliasing. It is only when an actual mutation occurs and
Mutate 'p
is
issued does the compiler check call sites that any generic used doesn’t become
'p
while it
is still in scope.
Use vs Mention
Mutate 'p
is an example of a
use
vs
mention
distinction. Code which merely mentions
mutability isn’t subject to any uniqueness constraints. This is most notable since places
can be paths so we may pass an entire
mut Context
to a function but it may only
Mutate 'ctx.field
.
This scenario often occurs when iterating mutably over a field of some context value:
In Rust the above code would be rejected, but there are actually several options in Ante.
You can expose
Mutate 'ctx.events
on
Context.on_death
above, guaranteeing only that
field may be mutated (
ctx.score
doesn’t need a similar annotation because mutating integers
can never invalidate references), or you can tell
on_death
that
entity
may be stored
within
ctx
to begin with:
Above, we’re saying all of
'ctx
may be mutated. For this specific example, this is less
desirable since it’d mean
entity
as an unstable reference wouldn’t be valid after the
call to
on_death
ends. For other patterns of code though, we may truly need to mutate
all of
'ctx
or keep it opaque
6
and this would be exactly what we’d want.
No Need for Polonius
Taking a bit of a step back, I want to show a bit how powerful it is to reframe
borrow checking in terms of
places
and
mutations
rather than lifetimes. Because
lifetimes are tied to a region of code, Rust can struggle with complex data-flow:
fnget_default<'r,K: Hash+Eq+Copy,V: Default>(map: &'rmutHashMap<K,V>,key: K,)-> &'rmutV{matchmap.get_mut(&key){// --- first mutable borrow occurs here
Some(value)=>value,None=>{map.insert(key,V::default());// ^~~~~~ error[E0499]: cannot borrow `*map` as mutable more than once at a time
map.get_mut(&key).unwrap()}}}
With Rust’s current model, getting the above code working requires more complex flow
sensitivity (with the next-gen borrow checker called
Polonius
).
In Ante, it just works:
Ante’s borrow checker is based on places and thus doesn’t try tying references
to any particular region of code. Instead, since the returned element reference from
map.get_mut
is unused in the
None
branch, it doesn’t need to be verified at all.
This should make some intuitive sense. If the reference is never used, it shouldn’t matter whether
it’s dangling or not.
Let’s look at another example:
structThing;implThing{fnmaybe_next(&mutself)-> Option<&mutSelf>{None}}fnmain(){letmuttemp=&mutThing;loop{matchtemp.maybe_next(){// ^^^^ error: `*temp` was mutably borrowed here in the previous iteration
// of the loop first borrow used here, in later iteration of loop
Some(v)=>{temp=v;}None=>{}}}}
Above, Rust thinks the
maybe_next
borrow may last longer than the loop itself due
to the
temp = v;
assignment to a variable defined outside of the loop.
Meanwhile, the equivalent Ante code is okay since
temp
gets some anonymous place
'p
,
maybe_next
returns the same
'p
, and the mutation would only invalidate any
unstable
references to
'p
.
We can use unstable places to safely allow mutating shared pointers like an
Rc<T>
(reference-counted pointer) in Rust.
The first realization is that since our analysis is based on places,
Rc
needs a place
to represent the shared element:
Rc 'p t
. This isn’t needed on other
pointer types like
Box
, but for
Rc
, this extra parameter
'p
is necessary to link
separate clones of the same value to the same internal value.
When modeling getting a mutable reference into the interior of an
Rc
, we need to make
use of a union of places from earlier:
This type says that if we have a mutable reference to an
Rc
, we can get a mutable
reference to the inner element. This returned reference will have two places:
outer!
(unstable because we’re crossing through a shared pointer boundary, and the
Rc
value
itself may be swapped out), and
inner
- the
shared value pointed to by every clone of this
Rc
.
Let’s try an example:
mutate_rc_bad(rc1:mutRc'p(VecString))(rc2:mutRc'p(VecString))=// string_ref: mut '(rc1!!, p!) Stringstring_ref=rc1.get()|>Vec.first_mut// Mutates 'p, so string_ref with unstable 'p! is invalidated// note: string_ref may be invalidated by this mutationrc2.get()|>Vec.clear// error: string_ref may have been invalidated by an earlier mutationprintlnstring_ref
Great! We can safely mutate through an
Rc
value with no runtime checks, and the
compiler still has our back if we try to do something unsafe. Is this enough
to represent even cyclic references though?
For cyclic mutability we need… well, nothing else! We can just
start using
Rc
to form cycles
7
.
typeList'pt=|Nil|Const(Rc'p(List'pt))main()=varf=Rc.of(Consfalse(Rc.ofNil))// false -> []vart=Rc.of(Construef)// true -> false -> []iffisCons_tailthen// tail's places are '(f!!, a!), so it'd be invalidated by any mutation to f or the shared place 'a.// The latter 'a invalidation is important to prevent us from using it if we mutate any other shared node.tail:=temit_listt|>take5|>iterprintln// true, false, true, false, true// The `do` here is unrelated, it just returns a thunk to be used as a generator functionemit_list(l:refListt)=doiflisConselemtailthenemitelememit_listtail
This pattern is very similar to using
GhostCell
in Rust,
but in a more ergonomic (no more
GhostToken
), built-in way. I’ll also emphasize that these checks are
entirely static
with
no runtime checks
.
With more permissive shared mutability, how does Ante maintain thread-safety?
There’s not a very interesting answer here. Ante simply copies Rust’s
Send
/
Sync
traits.
ref
/
mut
references both allow for shared mutability and thus implement neither trait.
Instead, Ante has additional reference kinds
imm
and
uniq
which correspond to Rust’s
&
and
&mut
. These references are
very rarely used
- they’re more or less only used
in multi-threaded code where after passing a thread boundary they can degrade back to
ref
/
mut
to call functions.
In the future, the kind of a reference will be attached to the place variable to more easily
write code which is polymorphic over any reference kind.
Summary
This was a lot! Thanks to anyone sticking around to the end! It’s a lot to grok at once but despite the length
this article ended up being, I do think the core concepts aren’t
that
complex. There are certainly rules to be
had but most are in service of making the language more flexible and making more code “just work.” The main
mental model is keeping track of the
places
a reference may borrow from, and whether any are unstable.
This article is mostly a restating of Ante’s
shared mutability rules
documentation, but I wanted to write an article version of it to follow up the original shared mutability article and
to speak on some motivations behind the change.
If any of this interests you, join
Ante’s Discord
to keep up with the language and ask me questions!
You can also clone the compiler at
GitHub page
to try out the language yourself.
If you are interested in the project, the best way to help would be to help spread the project around
to get some more visibility on it! Contributing would be appreciated as well of course (the compiler is small and I can help)!
Low-level is always a contentious term. I’m using it here to mean a language with unboxed
types by default and no pervasive GC. If you have a preferred definition, let me know!
↩︎
The new design is actually more efficient for cyclic mutability! It doesn’t require the clones
the previous design did.
↩︎
It wouldn’t be sound in Rust since multiple
&mut
references to the same
data would violate aliasing assumptions, but it should be in our target semantics!
↩︎
!
on places can nest!
'foo!
is an unstable place within
'foo
while
'foo!!
would be an unstable place within that previous unstable place. This could be, for example, a
String element of a
Vec (Vec String)
. If a type has multiple sources of instability (e.g. a
struct holding multiple vectors), an API designer may choose to expose the separate fields, e.g.
'foo.bar!
vs
'foo.baz!
, or may choose to hide this by coercing to the parent place
'foo!
.
↩︎
Any places that were already
'p
are actually okay. The body of the function
would already be aware of and check those cases. This enables patterns like passing
in an immutable container and a mutable reference inside the same container.
↩︎
Future versions of Ante will allow for ‘abstract places’ where structs could
declare a set of places inside of them to expose, separate from their actual fields.
Library authors wanting to hide specific struct fields while keeping multiple places
within the same struct distinct from each other in usual code could make use of this.
The downside is that since these aren’t connected to specific struct fields, it’d be
up to the library author to keep the translation to abstract places sound.
↩︎
Using
Rc
to form cycles still leads to leaks! Some other collection
mechanism is needed to prevent leaks, but that is a separate issue from the
mutability of a cycle.
↩︎
Security updates for Monday
Linux Weekly News
lwn.net
2026-10-19 09:10:19
Security updates have been issued by AlmaLinux (idm:DL1, kernel, libsoup, perl-URI, python3.14-urllib3, and webkit2gtk3), Debian (apache2, cifs-utils, haproxy, jq, kernel, and xen), Fedora (aom, chezmoi, chromium, docker-buildx, freeipa, freerdp, GitPython, httpd, jfrog-cli, kernel, knot, libheif, l...
A small open model, fine-tuned on a MacBook Air, that writes without em dashes, "not X, but Y" or lists of three and needs no system prompt, and you can run it locally with Ollama.
TL;DR
I trained the assistant writing habits out of Qwen3-4B-Instruct and released it as
qwen3-4b-deslop
. With Ollama it's
ollama run hf.co/erikkannike/qwen3-4b-deslop-v4-GGUF:Q4_K_M
, a 2.5 GB download.
On 40 prompts it never saw in training, the slop score dropped from 121 to 12.5 per 1000 words, and 68% of answers score in the range of human writing. Em dashes went from 20.5 per 1000 words to zero.
It still answers 30 of 30 factual questions correctly and fits the requested genre and length as often as the original. Its predictions on human-written prose moved about a third as much as with runtime steering.
An intermediate version scored 9.9 and wrote badly: opinion pieces without an opinion, invented studies, and a new habit of joining every sentence with ", which". Fixing that took a second filter that checks whether an answer does what the prompt asked.
The voice is plain to the point of flat, and it still invents names and places.
My home lab is a MacBook Air, so this is a 4B model trained on 161 answers. The recipe doesn't depend on the model size, and running it on larger models is the next step.
Answers on 40 held-out prompts
These are one sampled answer per prompt from the original model and from the released one, on ten topics in four genres, with no system prompt. Underlined passages are what the slop detector counts.
Original Qwen3-4B-Instruct
De-slopped
Generation stopped at 260 tokens, so long answers end mid-sentence. Hover an underlined passage to see which habit it is. The scores are per 1000 words; human writing usually scores under 15.
The slop score
The score comes from a detector I wrote from a style guide of AI writing habits: the em dash, "it's not X, it's Y", lists of three, rhetorical questions answered on the spot, signposts like "here's the thing", short fragments for emphasis, and words like "delve" and "seamless". Each habit has a weight, and the score is a weighted count per 1000 words. A paragraph by a careful human writer scores close to zero, and the original model averages 121.
A regex can't tell good writing from bad, so every model below was also checked for damage. Drift measures how far its predictions on 22 passages of human prose move from the original model's. A 30-question quiz checks that it still knows things, and a rule-based check flags broken output like lowercase sentence starts or a lost topic. I also read a sample of answers from every model.
Training method
An earlier experiment
on this model found the assistant register as a direction inside it: subtracting it while the model writes, together with a plain-style system prompt, takes the score to about 15, but it needs the prompt and code running during generation, and it shifts the model's predictions on ordinary text.
A second one
read neurons one at a time and found four whose sign flip removes 70% of "not X, but Y" at almost no cost, though only for that one habit.
To get both into the weights I used distillation: a teacher, built from whatever worked best so far, answers 288 training prompts. I keep the answers that pass the checks, and a small LoRA adapter learns to produce them from the bare prompt. The first round got the score to about 20 with no prompt and no hooks.
Round two
For round two the teacher was the round-one model plus the four-neuron patch and the plain-style prompt. Adding the direction steering on top as well produced the lowest score I have measured, 9.5, from text with no capital letters that wandered off topic, so I took the steering back out. The teacher then averaged 7.4, and the student trained on its 171 best answers scored 9.9, with 80% of answers in the human range.
In its answers, an opinion piece about a company's new CRM never took a position and read like an incident report. A blog post about moving to a new city became a third-person story about a family with a leaking apartment. A piece about houseplants cited "a study from the University of Technology Sydney", which the model invented. Almost every sentence ran into the next with ", which" or ", so", 28 times as often as in the original model. That last habit came from my own teacher prompt, which had told the model to join sentences "with because, so, but, which", and two rounds of imitation had amplified it.
Task-fit checks
I added rule-based checks for whether an answer does what the prompt asked. An opinion piece has to state a position early, a personal reflection has to be in the first person, an email has to open with a greeting, and the length has to roughly match the request. Two more checks count ", which" and ", so" joins and invented studies and percentages. On those, the round-two model did what was asked only 60% of the time, against 78% for the original.
Round three
The third teacher got a prompt that put the task first: take a position when asked, write in the first person when it's personal, vary the sentences, and don't invent studies or names. It wrote three answers per prompt, and an answer was kept only if it scored under 12, passed the damage checks and passed all the task checks. About 30% did, which covered 161 of the 288 prompts.
The model trained on those answers is the released one. Its score rose a little, from 9.9 to 12.5, while task fit went back to 80% and the ", which" joins fell from 1.4 to 0.3 per 100 words. Invented studies and percentages nearly disappeared.
Rate per 1000 words on the 40 held-out prompts, original model against the released one.
Downloads and usage
The quantised build (Q4_K_M, 2.5 GB) runs on a laptop with Ollama or llama.cpp:
ollama run hf.co/erikkannike/qwen3-4b-deslop-v4-GGUF:Q4_K_M
llama-cli -hf erikkannike/qwen3-4b-deslop-v4-GGUF:Q4_K_M
The full-precision weights load with transformers like any Qwen3-4B checkpoint:
from transformers import AutoModelForCausalLM, AutoTokenizer
name = "erikkannike/qwen3-4b-deslop-v4"
tok = AutoTokenizer.from_pretrained(name)
model = AutoModelForCausalLM.from_pretrained(name, torch_dtype="auto")
msgs = [{"role": "user", "content": "Write a LinkedIn post about switching to a four-day week."}]
ids = tok.apply_chat_template(msgs, add_generation_prompt=True, return_tensors="pt")
out = model.generate(ids, max_new_tokens=300, do_sample=True, temperature=0.7)
print(tok.decode(out[0][ids.shape[1]:], skip_special_tokens=True))
The repo also has the parts on their own: the LoRA adapter (126 MB) and the neuron edit, a 175-byte list of four weight columns and their scales. The adapter was trained with the edit active, so the two go together.
Limitations
The voice is flat: the model writes runs of short declarative sentences, and its personal pieces read like diary entries.
It also still makes things up: studies and percentages are rare now, but invented names and places are common, like a coffee shop on Maple Street run by a woman named Maria, because concrete detail is what every round rewarded. It also runs long, and answers to "about 150 words" often come in near 200.
I have only tested short English prose in these genres. Code, long conversations, other languages and tool use may be no better than the original model, or worse. The score is my style guide written as regular expressions, and no blind test with readers has checked it yet. The numbers also move between runs: the same model scored 10.2 through the adapter and 12.5 as merged weights, from sampling differences alone.
Next steps
Each student ended up about as good as the best answers its teacher could write, so a better model needs a better teacher. I'm putting together a set of excellent human writing, public-domain essays and letters plus modern pieces, to use as examples for a base model. A base model never went through assistant training and still writes like the people it learned from. If that teacher writes better than this model does, the same recipe should produce a student with some taste as well as clean habits. After that comes the same pipeline on a 7 to 8B model and one around 30B, and a blind test where people pick the better text.
Method notes and caveats
Base model: Qwen3-4B-Instruct-2507 in bf16. Every adapter is a rank-16 LoRA on all attention and MLP projections, trained for two epochs on the bare user prompt with loss on the response only, between one and three hours per round on an M2 MacBook Air.
Test set: ten topics never used in training, each in four genres (blog post, LinkedIn post, explainer, opinion piece), one sampled answer per prompt at temperature 0.7, no system prompt. Drift is the KL divergence from the original model on 22 passages of human prose.
The task-fit checks are simple rules (a stance word near the start of an opinion piece, first-person pronouns in a reflection, a greeting in an email, word counts) and they miss things a reader would catch. The training data was filtered on the same checks reported here, so the task-fit numbers flatter the model somewhat.
The neuron edit flips the sign of four MLP neurons (layer 32 neuron 4852, layer 33 neuron 348, layer 28 neuron 1121, layer 32 neuron 5418), which is the same as negating four columns of their layers' down-projection weights. The GGUF build was quantised from a Q8_0 conversion of the merged weights.
The readers' chat and live cursors connect readers directly over WebRTC (Trystero with public Nostr relays). Peers can see each other's IP addresses, nothing is saved, and "hide" disconnects you.
Juan Francisco Solórzano Foppa: Prominent Anti-Corruption Lawyer in Guatemala Assassinated
Democracy Now!
www.democracynow.org
2026-10-19 08:52:19
The prominent Guatemalan anti-corruption lawyer Juan Francisco Solórzano Foppa was fatally shot along with another man on Saturday at a sports center in Guatemala City. For years, Solórzano Foppa had been outspoken against Guatemala’s most powerful politicians, business leaders and companies. ...
The prominent Guatemalan anti-corruption lawyer Juan Francisco Solórzano Foppa was fatally shot along with another man on Saturday at a sports center in Guatemala City. For years, Solórzano Foppa had been outspoken against Guatemala’s most powerful politicians, business leaders and companies. He was known for his anti-corruption work as head of the Criminal Investigations Directorate within the Public Prosecutor’s Office and later as head of Guatemala’s tax authority, when he helped prosecute dozens of powerful Guatemalan business figures.
“In more recent years, he developed a social media presence, and he was forcefully denouncing corruption,” says Roman Gressier, a journalist based in Guatemala City. “We were thinking about [the killing of Solórzano Foppa] not only as an assassination, but also having a deep effect on freedom of expression.”
“Juan Francisco was a young lawyer coming from a background of pro-democracy and revolutionary activists,” says Silvia Solórzano Foppa, Juan Francisco’s mother. Her son was 43 years old when he was killed.
Guests
Please check back later for full transcript.
The original content of this program is licensed under a
Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License
. Please attribute legal copies of this work to democracynow.org. Some of the work(s) that this program incorporates, however, may be separately licensed. For further information or additional permissions, contact us.
Microsoft fixes classic Outlook bug that hid Copilot buttons
Bleeping Computer
www.bleepingcomputer.com
2026-10-19 08:44:44
Microsoft has fixed a known issue that removed the Copilot Chat and Copilot buttons in the classic Outlook desktop mail client for some Windows users. [...]...
Microsoft has fixed a known issue that removed the Copilot Chat and Copilot buttons in the classic Outlook desktop mail client for some Windows users.
As
explained in an updated support document
, affected users with the Copilot Chat (Basic) license or a Microsoft 365 Copilot (Premium) account no longer saw Copilot buttons in the side navigation and above the ribbon.
Those impacted by this experienced one or more of the following issues:
The Copilot button missing from the top-right area above the ribbon.
The Copilot icon missing from the left app bar or More Apps area in classic Outlook.
In Add Apps, Copilot may appear as an available app, but selecting Open does nothing.
Adding Copilot through ribbon customization may show the command as unavailable or grayed out.
Copilot remains available from other entry points, such as Outlook on the web or the Microsoft Copilot standalone app or web experience.
Microsoft first announced
in June
that it had fixed the bug with a service change, but last month it said it had
started investigating again
after recent updates caused it to resurface.
Now, Microsoft says it has finally resolved this classic Outlook issue, blaming it on a bug that prevented Outlook from retrieving some account information from the user's Outlook profile.
"We fixed an issue in classic Outlook that could cause the Copilot entry point to be missing from the navigation pane when required account information could not be retrieved from the user’s Outlook profile. The Copilot button might be missing for several different reasons, including licensing, Microsoft 365 app configuration, update channel, privacy settings, or other environmental factors," an update to the original support document
reads
.
Microsoft also shared a temporary workaround for those still affected by this known issue, which requires enabling the "Show Apps in Outlook" option in classic Outlook settings by selecting the File tab, then going to Options > Advanced and checking the "Show Apps in Outlook" box under "Outlook panes."
Affected users can also use the new Outlook email client or Outlook Web Access (OWA), which are not affected by this bug, or create a new Outlook profile.
Masked Israeli Settlers Nearly Kill Washington Post Journalist as Attacks on Palestinians Escalate
Democracy Now!
www.democracynow.org
2026-10-19 08:35:34
Israeli settlers backed by IDF soldiers brutally assaulted Palestinian olive farmers in the village of Abu Falah, northeast of Ramallah, on Friday. Witnesses say dozens of masked Israeli settlers armed with clubs, sticks, slingshots and guns hurled rocks at Palestinian farmers, set olive trees ablaz...
Israeli settlers backed by
IDF
soldiers brutally assaulted Palestinian olive farmers in the village of Abu Falah, northeast of Ramallah, on Friday. Witnesses say dozens of masked Israeli settlers armed with clubs, sticks, slingshots and guns hurled rocks at Palestinian farmers, set olive trees ablaze and drove people from their fields. Veteran
Washington Post
photojournalist Heidi Levine, a 64-year-old American, was documenting the attack when settlers began beating her. She suffered stab wounds, a broken rib, four broken vertebrae and a severe hand injury. Levine was wearing a clearly marked press vest and a helmet at the time of the attack. According to the Israeli human rights group Yesh Din, Israeli settlers have carried out at least 170 attacks against Palestinians in the occupied West Bank since September 27, which marked the start of this year’s olive harvest.
“It looked like they were killing her,” says independent American journalist Jasper Nathaniel, who witnessed the attack on Levine and helped intervene. “The Palestinian youth, the
shabab
, stepped up. They ran out ahead, and they started beating the settlers back by throwing stones at them, which is the only thing that allowed me to then run out front and grab Heidi.” As the journalists and Palestinians retreated into Abu Falah, “The Israeli military jeep that had been standing by the settlers who were attacking us then drives into the village itself, … and they start firing into crowds of Palestinian people.”
Guests
Please check back later for full transcript.
The original content of this program is licensed under a
Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License
. Please attribute legal copies of this work to democracynow.org. Some of the work(s) that this program incorporates, however, may be separately licensed. For further information or additional permissions, contact us.
French Gov't Cracks Down on Mass Protests over Cost of Living, Education Cuts; 2,400+ Arrested
Democracy Now!
www.democracynow.org
2026-10-19 08:17:57
Hundreds of thousands of protesters marched in over 140 cities across France on Saturday, demanding relief from the high cost of living, more funding for public services and improvements to deteriorating schools, among other grievances. The demonstrations were the latest — and largest — in a series ...
Hundreds of thousands of protesters marched in over 140 cities across France on Saturday, demanding relief from the high cost of living, more funding for public services and improvements to deteriorating schools, among other grievances. The demonstrations were the latest — and largest — in a series of protests that began in September with high schooler-led demonstrations against overcrowded classrooms and crumbling school infrastructure. Some cities saw property destruction, arson and theft on Saturday, with city halls and other symbols of the state coming under attack. Officials said nearly 1,000 police officers were injured and some 2,400 people were arrested.
“What is frustrating to see is how little the police violence is addressed and talked about, which is really the main violence and the real violence today that is taking place in France,” says Rayyan Seriket, a member of the French student union.
“We’re talking about shattered jaws, high schoolers and adolescents who have been blinded,” adds Harrison Stetler, an independent journalist and teacher based in Paris.
This all comes as Marine Le Pen of the far-right National Rally party is leading in the polls six months ahead of France’s elections. “This situation is essentially what Marine Le Pen hopes for,” says Stetler.
The original content of this program is licensed under a
Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License
. Please attribute legal copies of this work to democracynow.org. Some of the work(s) that this program incorporates, however, may be separately licensed. For further information or additional permissions, contact us.
What are you doing this week?
Lobsters
lobste.rs
2026-10-19 08:09:29
What are you doing this week? Feel free to share!
Keep in mind it’s OK to do nothing at all, too....
I recently gave notice at work without another job lined up and need a project to fill my work days. My mental "motivation -> work -> reward" loop is completely shot, so it needs to be something that regularly feels rewarding in order to build that back. It's been a while since I felt interested in tech.
Maybe I'll finally learn OpenGL or Vulkan. Might also dig up my mdbook clone for the
Djot
markup language which gives me joy. Otherwise, doing some art and exercise away from the computer should help my brain.
Harness Engineering 101: The LLM is the brain, the harness is the body
An LLM API is stateless. Every turn, you send the entire conversation as a JSON
array and get text back. A
harness
is the program that builds, maintains, and
protects that array. Everything the field calls "agents" is a set of patches to
that one loop, and each patch exists because something concrete broke. This
series develops that one idea across 16 chapters, growing a ~300-line toy agent
in plain Python as it goes.
The patterns here are developed in full in
One Code
, an open-source coding
agent built on
pi
.
The rendered book reads best online at the link above. If you'd rather read
the source here on GitHub, follow the chapters in order below. The full
introduction is on the
book's landing page
.
Reading order
Every chapter has the same shape: the failure, the minimal patch, what the
patch costs.
The code
— the
.py
files under
src/harness/
and
src/diagrams/
, and
code snippets reproduced from them in the chapters — is licensed under the
MIT License
. Use it freely, with attribution.
Hundreds of Thousands March in Over 140 Cities in France on Saturday, Millions of Protesters Participate in “No Kings” Demonstrations on Saturday in the U.S., Thousands March in Tunisia Against President Kaïs Saïed, Protests Continue to Roil Albania, as Demonstrators Call for Prime Minis...
Hundreds of Thousands March in Over 140 Cities in France on Saturday
Oct 19, 2026
In France, hundreds of thousands of protesters marched in over 140 cities on Saturday, demanding relief from the high cost of living, more funding for public services and improvements to deteriorating schools, among other grievances. The demonstrations were the latest — and largest — in a series of protests that began in September with student-led rallies over overcrowded classrooms and crumbling school infrastructure, that have since grown to a broader nationwide movement. Some cities saw property destruction, arson and theft, with isolated incidents of violence. There was damage reported to symbols of the state, including city halls in Lille, Marseille and Limoges, and a tourist office in Lyon. Officials said almost 1,000 police officers were injured, and some 2,400 people were arrested. France’s Interior Minister Laurent Nuñez said police had “lost control,” and offered to resign. President Emmanuel Macron rejected his offer. Macron blamed the violence on “dissenters from far-left groups, joined by numerous criminals.”
Many of the hundreds of thousands who marched peacefully said there was too much media focus on property damage and not on the issues of austerity and police violence against children. This is a protester in Paris.
Paola Formenti
: “I think the protests are very legitimate. There is a lot of anger. There is a lot of difficulty in living and studying. So I believe it’s legitimate. And, of course, in this legitimate protest, sometimes there are violent people that take advantage, but I think it’s very minor.”
The French president is off on a three-day tour of Gulf Arab states — Kuwait, Bahrain, the United Arab Emirates and Qatar.
Millions of Protesters Participate in “No Kings” Demonstrations on Saturday in the U.S.
Oct 19, 2026
Here in the U.S., millions of people took to the streets at more than 3,000 local events in all 50 U.S. states on Saturday, seeking to rally voters for midterm elections under the banner “No Kings.” Organizers sought to make Saturday the largest single day of early voting in U.S. history; they’re also organizing poll monitors and election defenders ready to respond to election sabotage. This is Seattle resident Olivia Pope.
Olivia Pope
: “Having freedom here in America is important. Not having a king ruling over us is important. Being able to have universal healthcare is important. I actually experienced an injury with no healthcare, and it was $48,000.”
Meanwhile, the social media giant Meta has apologized after the No Kings coalition’s Instagram account was shut down for several hours during Saturday’s demonstrations. Meta later apologized, citing an automated action it said was made in error. The No Kings coalition is demanding an explanation, writing, “Restricting communications about voting in the middle of an election is unacceptable.”
Thousands March in Tunisia Against President Kaïs Saïed
Oct 19, 2026
In Tunisia, thousands marched in the capital Tunis Saturday in the biggest protest against President Kaïs Saïed in years. The march was led by the powerful Tunisian General Labor Union, with opposition parties and civil society groups. Protesters demanded the release of jailed critics and accused Saïed of crushing dissent since he consolidated power in 2021, when he dissolved Parliament, fired dozens of judges and began ruling by decree. This is the vice president of the Tunisian Human Rights League.
Jamaleddine Sebaa
: “A suffocating crisis on all levels, frankly speaking. Almost all rights today have been violated. The state is no longer fulfilling its duty to provide rights for Tunisian citizens, and that is what made us determined today to make the voice of the Tunisian people heard. Tunisia first, and the Tunisian people above all.”
Protests Continue to Roil Albania, as Demonstrators Call for Prime Minister to Resign
Oct 19, 2026
In Albania, protests have rocked the capital Tirana for a week, as anti-government demonstrators clashed with police, calling for the resignation of Prime Minister Edi Rama. Albania’s protests started in May, when environmentalists rallied against a planned luxury resort tied to President Trump’s son-in-law, Jared Kushner. Environmentalists say the development would destroy sensitive wetland habitats. The movement soon grew into broader protests against corruption and the cost of living. Most recently, students led the protests, demonstrating against high tuition, poor university conditions and a lack of jobs. This is a protester.
Jetmir Kurti
: “It’s corruption, fraud. There is injustice for everyone. They don’t see — we don’t see the future with this government, with its politics, with the rich people that are getting richer every day. So, we need a change; otherwise, everyone will escape from here.”
Brazil’s Lula Holds First and Only Debate with Flávio Bolsonaro Ahead of Presidential Runoff
Oct 19, 2026
In Brazil, right-wing Senator Flávio Bolsonaro and President Luiz Inácio Lula da Silva sparred in their first and only debate on Sunday, one week before the presidential runoff election. Flávio Bolsonaro is the son of far-right former President Jair Bolsonaro. He finished two points ahead of Lula in the first round of voting, but polls have recently narrowed. During the debate, President Lula attacked Flávio Bolsonaro for supporting his father’s response to the
COVID
pandemic. This is Flávio Bolsonaro.
Flávio Bolsonaro
: “The PT, the Workers’ Party, has been governing Brazil for 20 years, and nothing has changed or improved for you when it comes to healthcare.”
President Luiz Inácio Lula da Silva
: “Only someone who knows nothing about healthcare, someone who has never used the public health system, could say something like that. They had a four-year run, and it was the greatest disaster in this country’s history: 716,000 people died due to the government’s irresponsibility. Half of those deaths could have been prevented if they had listened to science, if they had believed in science, but they didn’t.”
Ukraine and Russia Trade Drone and Missile Strikes After Trump Waives Sanctions on Moscow
Oct 19, 2026
Russian officials say one person was killed and five others were wounded Sunday as Ukraine launched more than 1,000 drones across 15 Russian regions. The drone swarm set an oil terminal on fire in St. Petersburg, knocking out power to thousands of residents. It also struck a Russian retail chain’s logistics center and a data center operated by the largest Russian social media platform. Russia followed with a large-scale missile and drone attack on Kyiv overnight that killed a 21-year-old woman and left more than a half a million households without electricity. The attacks struck more than 10 energy sites, a clinic, a school, a metro station and homes. Ukrainian President Volodymyr Zelensky said the attacks came with no advance warnings from Western intelligence agencies.
Two days before the Lindsey Graham Sanctioning Russia and Iran Act of 2026 was supposed to go into effect, which Trump signed, he waived the sanctions against Russia, saying he would sign a deal with President Vladimir Putin to purchase diesel fuel. Lawmakers from both parties criticized the plans. North Carolina Senator Thom Tillis — who is not seeking reelection — was among Republicans distancing themselves from Trump. He wrote, “It’s unconscionable that this administration is capitulating to a Russian dictator who illegally invaded Ukraine and butchers innocent civilians every single day.”
Israeli Settler Attack on Palestinian Olive Harvest Wounds Dozens, Including WaPo Photographer
Oct 19, 2026
In the occupied West Bank, armed Israeli settlers descended on Palestinian villages over the weekend in a coordinated assault on the annual olive harvest. Dozens of Palestinians were injured. Witnesses say Israeli forces responded by siding with the settlers, firing tear gas at Palestinians who tried to defend themselves. In one incident, at least 80 masked settlers attacked an olive harvest in the town of Abu Falah on Friday; among their victims was Washington Post photojournalist Heidi Levine, who was beaten for more than 10 minutes by settlers, who stole her passport, phone, wallet and camera gear. Levine was hospitalized with serious injuries, including a stab wound. She spoke to reporters from a hospital bed in Ramallah.
Heidi Levine
: “And I just am so ashamed that as a parent myself, I cannot understand how a parent can raise such individual monsters. They’re not even humans. And yes, they are Jewish terrorists, and they are giving everyone in the country a horrible reputation.”
In rare critical comments, U.S. Ambassador to Israel Mike Huckabee called the attack on Heidi Levine “terror” and called for the prosecution of those responsible.
Separately, Israeli settlers assaulted Belgian, French and Polish diplomats and a French mayor in another part of the occupied West Bank on Saturday. Israeli Prime Minister Benjamin Netanyahu cast doubt on reports of settler attacks, calling them “sensational headlines before the full facts emerge” and part of a smear campaign. But Israeli police later said they had taken 10 suspects into custody for questioning. Prosecutions of Israeli settlers are rare.
Later in the broadcast, we’ll speak with Jasper Nathaniel, a journalist covering Israel’s occupation of the West Bank. His new piece is titled “The Palestinians Who Rescued Heidi Levine.”
Mass Funeral Held for 75 Palestinians Whose Remains Were Uncovered from Gaza Rubble
Oct 19, 2026
Image Credit: Anadolu Agency via Reuters Connect
In Gaza, a mass funeral was held on Sunday for 75 Palestinians whose remains were found under the rubble of homes and buildings destroyed by Israel. This comes as the U.N. has announced major cuts to the World Food Programme’s Gaza operations due to a funding shortfall. The agency is reducing monthly assistance to 1.1 million people, down from 1.6 million, even as two-thirds of Gaza’s population faces crisis levels of food insecurity — or worse.
Trump Backs Netanyahu for Prime Minister Days Before Israeli Election
Oct 19, 2026
President Trump endorsed Israeli Prime Minister Benjamin Netanyahu on Truth Social on Sunday, just days before Israel’s election on October 27. The endorsement comes as most polls show Netanyahu’s coalition short of a majority. It’s Israel’s first election since the Hamas attacks on October 7, 2023. Trump endorsed Netanyahu two days after Israeli settlers attacked Washington Post photojournalist Heidi Levine.
“There’s a Failure in the Leadership”: Widower Confronts JD Vance over Iran War Deaths
Oct 19, 2026
During a
CBS
News town hall, a widower of U.S. service member Nicole Amor confronted Vice President JD Vance. Amor was one of six people killed in an Iranian drone attack back in March, its deadliest attack on U.S. forces during the Iran war.
Joey Amor
: “There’s a failure in the leadership, and I want to know how this administration is going to start holding those leaders accountable for the actions and the deaths of the soldiers that we — that we honor and that we love.”
Houthis Strike Military Training Camp as
UAE
Joins Saudi-Led Attacks on Yemen
Oct 19, 2026
In Yemen, Houthi forces attacked a government military training camp in the Shabwa province, killing 18 people. It comes as fighting between Yemen’s internationally recognized government and the Houthis has escalated in recent weeks. Meanwhile, the United Arab Emirates has agreed with Saudi Arabia to reenter the conflict in Yemen by reportedly resuming payments to some government forces. This comes as The Wall Street Journal reports that Iran has provided the Houthis with training, intelligence and tactical guidance to launch attacks against Saudi Arabia and Yemen’s government.
Guatemalan Anti-Corruption Lawyer Juan Francisco Solórzano Foppa Is Murdered
Oct 19, 2026
In Guatemala, a prominent anti-corruption lawyer, Juan Francisco Solórzano Foppa, died after being shot by two men while visiting a sports center in Guatemala City. Guatemalan police reported that they had detained two men. President Bernardo Arévalo condemned the attack, saying, “The direct perpetrators and those who ordered the crime must face the full weight of the law.” Solórzano Foppa had been outspoken against Guatemala’s most powerful politicians, business leaders and companies. We’ll have more on this story later in the broadcast.
Trump Administration Seeks to Denaturalize and Deport Rep. Ilhan Omar, Tom Homan Confirms
Oct 19, 2026
The White House’s so-called border czar Tom Homan on Saturday became the first senior Trump administration official to publicly state that the administration was looking to possibly denaturalize and deport Congressmember Ilhan Omar. His comments come after federal agents raided her home last week. Homan spoke on Fox News on Saturday.
Tomi Lahren
: “Would this involve denaturalizing and then deporting her, if it — if it turns out that there is some kind of immigration fraud?”
Tom Homan
: “Of course. If you lie during naturalization process, there is a process to denaturalize somebody. We’ve done it before. It’s a — it’s a — it’s a long, tedious process, but it’s been done before. I’ve been involved with those investigations before. And certainly, if the evidence points that way, that could happen.”
President Obama, whose citizenship has also been questioned by President Trump, condemned Homan’s comments and defended Congressmember Omar, writing on Sunday on X, “The full weight of the federal government is being brought down on a law-abiding elected official because she has dared to criticize the president.” Obama added, “If this becomes the new normal, there’s no reason to believe it will stop with her — or that future presidents, in either party, won’t do the same.”
Katie Zacharia Ousted as Press Secretary After Just Five Days on the Job
Oct 19, 2026
The White House’s new press secretary, Katie Zacharia, resigned on Friday after just five days on the job. It comes after her disastrous debut as press secretary last Tuesday. Zacharia was also facing questions on whether she misrepresented herself as a lawyer despite failing the California bar exam.
The original content of this program is licensed under a
Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License
. Please attribute legal copies of this work to democracynow.org. Some of the work(s) that this program incorporates, however, may be separately licensed. For further information or additional permissions, contact us.
Harness2 by Google Research – Recursive Agent Harnessing
A
harness
is the system around a model that enables it to act as an agent:
prompts, tools, memory, skills, orchestration, and more.
Harnessing
is the
process of optimizing that system.
Harness² is a plug-and-play framework for
recursive agent harnessing
in an
open world, where agents encounter tasks unseen during harness design. It
connects two levels of recursion while keeping model weights fixed:
Task-level recursion
refines the execution harness for the current task
through a contrastive
Propose–Probe–Compose
step: propose edits, probe
their effects on the same task, and compose a refined harness from behavioral
contrasts between executions, without ground-truth feedback.
Harnessing-level recursion
updates a persistent
improvement harness
with adopted harnesses and evidence-supported lessons from each task to guide
future refinement.
Across three professional benchmarks and four model–harness configurations, a
single Harness² step improves GLM-5 and Gemini 3.5 Flash over their base
harnesses, with gains of up to 11.5 points on WorkBuddy-Bench, 4.5 points on
JobBench, and 11.8 percentage points on LAB's partial pass rate. Increasing the
task-level recursion budget brings further gains.
The release supports
parallel and sequential recursion
,
OpenCode and
Codex executors
, and
JobBench, LAB, and WorkBuddy-Bench
.
Harness² exposes eight editable components around the model:
system prompt,
guardrails, memory, tool guidance, subagents, skills, scripts, and plugins
.
They control context construction, the tool interface, delegation, and behavior
inside the tool loop.
Install
Use
Linux, Python 3.12, and
uv
.
From the repository root:
The local demo runs both recursion modes with deterministic editors and real
Python executions. It requires no model credentials.
For model-backed benchmarks, install
Node.js 20+, the Google Cloud CLI
, and
the
benchmark dependencies
. LAB needs Pandoc and
Poppler; WorkBuddy-Bench needs Docker. Then configure your models:
cp .env.example .env
# Edit .env with your Vertex AI project and model IDs.
gcloud auth application-default login
The following example installs LAB and runs one task, then evaluates and reports
its result. Model-backed runs incur API costs; start with a small task selection.
Sequential recursion runs the same commands with
--mode sequential
.
--k
is
the task-level recursion budget; see
Experiments
. Judging and
reporting must use the same benchmark, executor, subset,
--k
,
--mode
, and
seed as the refinement run. Add
--dry-run
to
harness2
to preview task
selection without model calls.
Choose one benchmark per command. WorkBuddy also takes
--subset office
,
--subset web
, or
--subset code
on every command after setup. The
benchmark guides
cover each one's data, domains, and
grading.
Experiments
Scale task-level recursion in two ways:
parallel recursion
explores multiple
candidate harnesses and composes refinements from their execution evidence;
sequential recursion
carries the refined harness and accumulated evidence
through successive Propose–Probe–Compose steps.
Probe
K
general and
K
domain-specific candidates, then produce
K
compositions
--k K --mode sequential
Refine the harness through
K
successive steps
--substrate cx
Use Codex instead of the default OpenCode executor
After each task, harnessing-level recursion retains the adopted harness and
evidence-supported lessons to guide future refinement. See the
experiment guide
for task selection, concurrency,
reproducibility, and baseline comparisons.
Web access
Executor network access is unrestricted, and Codex runs with its sandbox
disabled. Public benchmark rubrics may be accessible online. Before evaluation,
configure
network restrictions
to prevent
access to benchmark answers and grading criteria.
Results and resume
Results are saved under
runs/
, organized by benchmark and subset where
applicable. They include task summaries, deliverables, adopted harnesses,
reflection notes, and evaluation results.
Repeat the same command to resume. Use a new
HARNESS2_RUNS_DIR
when changing
models or task selection. See
results and resume
for details; each command also supports
--help
.
Citation
@article{xu2026harness2,
title = {Harness$^2$: Recursive Agent Harnessing for an Open World},
author = {Xu, Ruiyao and Chen, Yanfei and CuiZhu, Zhongying and Dalvi Mishra, Bhavana and Ming, Yifei and Yu, Han and Han, Rujun and Lee, Chen-Yu and Pfister, Tomas},
journal = {arXiv preprint arXiv:2610.14224},
year = {2026},
url = {https://arxiv.org/abs/2610.14224}
}
> I'm an engineer at Meta and I never felt this uncomfortable doing my job. I'm writing code these days and it all feels like a black box. This new standard of shipping with AI is moving so fast that if we're going to spend our time checking each line of code, it's going to take forever. That means you can end up with systems you've built where you don't truly understand how all the code works. You understand the high level, but not every detail. And maybe this is becoming the new standard. It goes against every instinct of being a software engineer. I'm used to understanding what I'm building. Now I'm trying to figure out how much I need to understand before I'm comfortable moving forward. Are other engineers feeling this too?
How are you handling this?
ESA's Hera Will View Asteroid Scars from DART's Strike
In one month, the
European Space Agency’s Hera
mission will make history. Moving at 12 kilometers per second relative to Earth, the mission is about to rendezvous with the binary Dimorphos-Didymos asteroid pair. NASA’s Double Asteroid Redirection Test (DART) mission
slammed into Dimorphos in 2022,
and now Hera will provide a follow-up view of the mission’s resulting handiwork. The
European Space Agency
(
ESA
) recently
released a thought-provoking look
at the perspectives of Hera, and what an astronaut might see from the surface of the
asteroids
as the mission speeds by.
But what would it be like to hitch a ride aboard Hera? Launched on a
SpaceX
Falcon-9 rocket from Cape Canaveral, Fla. on 7 October 2024, Hera is ESA’s first
Space Safety Programme-class
mission. The spacecraft took just over two years to reach its destination. Even now, the pair of asteroids is little more than a few pixels across in Hera’s view.
The mission
imaged Didymos in July 2026.
Why Hera is chasing Didymos
Discovered by the Kitt Peak Spacewatch survey on 11 April 1996, 65803 Didymos is 780 meters in diameter, and it orbits the Sun once every 2.1 years. In 2003, the asteroid was discovered to have a small moonlet, a 151-m rock named Dimorphos. Scientists are finding that more and more asteroids are in fact binary pairs in their own right.
Like our
Moon
, the pair are dark and silicon-rich. The meetup with Hera also occurs 1.5 astronomical units from the Sun. This makes for a dimmer view, though it still provides enough juice for Hera’s two 5-m long
solar panels
.
Didymos is a fast rotator, spinning once every 2.2 hours.
DART saw Dimorphos
as a ‘rubble pile asteroid’ shortly before impact, similar to 101955 Bennu or 162173 Ryugu, visited by
NASA’s Osiris-REX
and
JAXA’s Hayabusa-2
missions respectively. These rock piles are thought to be at their limits in terms of holding together versus flying apart. DART’s 6.6 km/s impact
did shorten
the original 11 hour, 55 minute orbit by about 32 minutes, and a debris stream was seen from the binary pair in the weeks after impact.
An arrival preview should provide the first close up views of Dimorphos post-impact. This sort of study could prove handy, if we ever need to move an Earthbound asteroid out of harm’s way.
Certainly, standing on the boulder strewn surface of either asteroid would provide an alien vista of a spinning sky dominated by the other nearby asteroid companion. The feeble gravitational pull of either asteroid would allow a would-be astronaut to fall to the surface of either at a days-long leisurely rate.
Hera’s pair of
CubeSats
will put that to the test. Juventas and Milani—built by
GomSpace
, in Luxembourg, and
Tyvak International
, in Turin,
Italy
, respectively—will leave Hera shortly after rendezvous next month. Milani will analyze the dust field around both asteroids and study the spectral composition of the pair, while Juventas will make comparisons of the internal structure of the asteroids and may even approach and come to rest on Dimorphos.
After Hera is done with its nominal mission in 2027, controllers may opt to extend its life as a technology demonstrator, testing autonomous spacecraft control techniques.
It’s going to be exciting to get a look at the Didymos-Dimorphos system again. And although we can’t be there in person, we can still get a close look at these alien worlds through Hera’s eyes.
Alternatives to Animal Testing Are Finally Taking Off
Lab rats have long been a mainstay of biomedical research and drug development. N
ow, technologies such as Emulate’s Lung-on-a-Chip aim to model human biology without relying on animals.
Seventeen years ago, cell
biologist
Donald Ingber
and his colleagues at
Harvard
University’s
Wyss Institute
for Biologically Inspired Engineering submitted a paper to the journal
Science
describing their model human lung. It was smaller than a
USB
stick and made of a clear polymer slab containing narrow channels, which were lined with the type of cells that line a lung’s air sacs and blood vessels. When air was pumped through hollow chambers beside the channels, the device rhythmically expanded and contracted—it “breathed.”
This lifelike movement was a dramatic change from previous generations of lung models, which typically used static cultures of lung tissue that were unable to simulate the movements essential to lung function. When exposed to inflammatory proteins and
bacteria
, Ingber’s artificial lung reacted much as living lungs would. And exposure to silica
nanoparticles
used to model the effects of ultrafine particulates revealed that movement affected how tissues absorbed them.
Donald Ingber led the team that developed the first human lung-on-a-chip at Harvard University’s
Wyss
Institute.
Sam Ogden
It was a powerful proof-of-principle demonstration of a system that could be used to test drugs and other chemicals, providing a complement and even an alternative to testing in tissue cultures or in
animals
. Even so, the editors at
Science
were hesitant. They rejected the paper and suggested that Ingber’s team also run the tests in mice.
It wasn’t an unreasonable request: Harvard’s lung system was new and comparing the results it generated to results from mice would help validate it. Ingber’s team ran the suggested experiments and resubmitted their study a year later, in 2010, at which point
it was published
. (It has since been cited by nearly 5,400 other papers.) Still, the incident spoke to how animal models have been the default of modern biomedical research.
An early lung-on-a-chip developed at Harvard’s Wyss Institute used microfluidic channels lined with human cells to reproduce key features of lung function.
Wyss Institute at Harvard University
A recent story told by
Ilka Maschmeyer
, a translational
toxicology
researcher and executive at the German biotech company
TissUse
, shows how much things have changed. TissUse specializes in building
organ-on-a-chip systems
—the conversational name for systems like Ingber’s lung—that are used by pharmaceutical companies for research. A few months ago, says Maschmeyer, a pharmaceutical company approached TissUse after being denied permission by the U.S. Food and Drug Administration to run a clinical trial of a new drug. The problem: It had presented animal data, but the
FDA
wanted data from organs-on-a-chip or some comparable alternative. The standards had come full circle.
The moment spoke to a trend, perhaps even the early days of a fundamental shift, away from the use of animals in toxicology and drug development. “It’s rare still,” says Maschmeyer, “but I think it’s going to be more and more frequent.”
A host of these kinds of alternatives to experiments on animals have been developed over the years. Collectively they’re known as NAMs, an acronym that stands, depending on whom you’re talking to, for new approach methodologies, novel alternative methods, or nonanimal methods. Most NAMs have yet to be rigorously tested, but early studies suggest their potential.
As NAMs have become more sophisticated, the question of how they will be implemented has become less about their technical qualities and more about the practical next steps needed to realize their potential. Validating NAMs—standardizing the systems, conducting head-to-head comparisons with animal experiments—is an enormous challenge. Moreover, simply outperforming animal models is necessary but not sufficient. The adoption of NAMs will require changes in policy, training, and culture.
For decades, animal advocates and many scientists have criticized both the morality and usefulness of experimenting on animals. An estimated
92 percent of all drugs
that enter U.S. clinical trials fail to reach the market, sometimes for business reasons but often because the drugs prove ineffective or unsafe in ways that were not predicted by animal experiments. Failure rates are even higher in drugs for heart disease, cancer, and diseases of the brain.
These statistics don’t automatically mean that a reliance on animals is to blame. Flawed study designs are a problem too, and also the sheer confounding complexity of disease. But there’s little question that animals have made poor surrogates for many conditions. And just as animal experiments may mistakenly suggest efficacy or fail to predict harm in humans, they might also erroneously suggest that drugs are ineffective or harmful when they could actually work in humans. Some researchers argue that if aspirin or acetaminophen had been discovered after the advent of modern testing requirements, they might have been abandoned.
TissUse’s Humimic systems use microfluidic chips to culture human tissues and model interactions between organs. A researcher images tissues in a chip during an experiment [top], Humimic chips sit in a temperature-controlled unit [center], and a researcher prepares chips for use [bottom].
TissUse (3)
Researchers developing NAMs have pushed these systems far beyond old-fashioned tissue cultures. The new technologies include organoids that more closely mimic the structure, composition, and function of human organs. More humanlike still are
organ-on-a-chip
systems; alongside Ingber’s lung-on-a-chip are brains, hearts, kidneys, and even placentas on a chip. As many as
10 such organs have been linked together
, yielding multi-organ systems that promise to recapitulate many aspects of human physiology—not perfectly, but better than a mouse or a monkey would. Supporting these systems are computational simulations of organs and organisms, and also
artificial intelligence
tools that analyze data generated by other systems and inform future experiments in a high-powered iterative loop.
Yet even as studies piled up and some pharmaceutical companies started using NAMs in-house, the U.S. regulatory system governing drug developing and testing remained an obstacle to their wider use. NAM proponents were overjoyed, then, when in late 2022 the
FDA Modernization Act 2.0
passed into law. It explicitly authorized the use of NAMs in the preclinical studies required of new drugs before they could enter human trials. Previous regulations had mandated animal testing; now the door was open to alternatives. It was a landmark moment. “That was something I didn’t expect to see in my life,” says Maschmeyer.
Although immediate in-the-lab impact was limited, the FDA’s decision was a harbinger of things to come. In 2025, the FDA
pledged
“to make animal studies the exception rather than the norm” for drug safety testing. Then, in September 2026, the agency followed up by
issuing a rule
that, if it takes effect, will replace references to “animal tests” in its drug-development regulations with the broader term “nonclinical tests.” The change makes explicit that validated alternatives such as human-cell systems, organs-on-chips, and computer models can be used when appropriate.
Also in 2025, the U.S. National Institutes of Health, the world’s largest public biomedical research funder, announced that researchers applying for grants to study animal models would also need to
incorporate nonanimal research
, such as real-world data or studies of NAMs. Meanwhile, the
European Commission
and
United Kingdom
have announced their own plans to phase out animal testing, and the intergovernmental Organisation for Economic Co-operation and Development updated its influential
guidelines
to allow for expanded use of NAMs.
NAM proponents say these shifts were essential: If regulators won’t accept NAM results, there’s less incentive to adopt them, especially for researchers already working with animals. Maschmeyer says TissUse’s clients increasingly include scientists whose research has been focused on animals. “I see, within the last year, a change,” says Maschmeyer. “It’s more people who are working with animal models who now have to also add in vitro models.” She traces it mainly to the regulatory shift—a trend Ingber calls “game-changing.”
Proving That NAMs Work
It’s not enough for regulators to say that NAMs can or should be used, though. Even more important is the regulatory apparatus dedicated to assessing
how
they should be used. This begins with their validation: the process by which experimental methodologies and devices are determined to be reliable and trustworthy. A prototype brain-on-a-chip designed to model a rare neurological disease might work fine in the lab that developed it—but to be validated, the system needs to work in the real world.
“You read about all the organ chips that come out of academic labs, which is great—but that’s not going to change their uptake by the FDA, because you have to get the same results anywhere in the world. It has to be a commercial product. It has to be mass-produced and meet very fine performance criteria,” says Ingber. For example, even minute variations in the
hydrogels
used as tissue scaffolds in organ chips can produce very different growth patterns.
Emulate’s Organ-Chips are connected to the company’s automated culture system, which supplies the chips with nutrients and controls the flow of fluid through them.
Emulate
Workflows and procedures need to be uniform, too. One obstacle to wider use of vascularized tumor-on-a-chip platforms in developing cancer therapies, for example, is the different metrics used by different research groups to characterize blood-vessel function and geometry. Experimental guidelines, workflows, checkpoints, metrics, reporting criteria: All need to be standardized in order for researchers to compare their work and collaborate across platforms. Members of Ingber’s lab coach industry researchers on how to use chips developed by Emulate, a company founded by Ingber. But even with instructions, they still need help with the finer points of tending to stem-cell cultures.
When a NAM is ready for commercial use and researchers know how to use it, the most important test—whether it provides clinical benefit—still remains. A rare-disease organ chip might be reliable, but are the biomarkers it measures actually relevant? If so, are the
algorithms
that extrapolate chip results to the drug’s in-body effects truly predictive?
Microscopic images reveal the human tissues grown inside Emulate’s Organ-Chips. Bacteria, shown in magenta, interact with mucus and airway cells in a LungChip [top]; an IntestineChip develops structures resembling those that absorb nutrients in the small intestine [center]; and tiny hairlike cilia grow on cells in another LungChip, where they help move mucus and trapped particles out of the airway [bottom].
Emulate (3)
Such questions have been answered for some NAMs. For example, a liver-on-a-chip system from Emulate
correctly flagged about seven out of every eight drugs
that had safely passed animal trials but proved toxic to human livers. A
similar study
was conducted by researchers from Oxford University and Janssen Pharmaceutica (later renamed Johnson & Johnson Innovative Medicine). That team showed that their computational simulations of human heart cells flagged compounds that caused a type of dangerous heart arrhythmia with 89 percent accuracy, compared to animal studies that were 75 percent accurate.
Such studies, however, are complicated and costly. Emulate’s study required 870 chips and the labor equivalent of 16 full-time employees working for 16 weeks—efforts far beyond the reach of the average lab. If the researchers wanted regulatory approval to use their chip to predict large-molecule drugs rather than the small-molecule drugs they tested, they would have needed to run another such study for that particular use. And comparable studies ostensibly need to be conducted for every commercially available NAM and every context in which they would be used—a vast undertaking. “That’s a challenge,” says
Kathy Archibald
, founder of
Safer Medicines Trust
, a United Kingdom–based group that considers animals to be poor models of human biology. “It takes too long and costs too much, and small companies can’t afford to do it.”
Ingber thinks that academic scientists need to collaborate more with industry researchers on NAMs, and that governments should fund those projects. He and other NAM proponents also stress the importance of having access to the necessary data: Without information from preclinical animal studies and human clinical trials, comparisons are difficult, but much of that data is now proprietary. Pharmaceutical companies and regulators need to share it, they say, and the FDA has called for an open-access repository of drug toxicity data. Hartung of
Johns Hopkins
also suggests that new animal experiments be run in parallel with NAMs, producing side-by-side comparisons.
To
Christian Maass
, a computational biologist at the German
biotechnology
company
ESQlabs
, NAMS are overdue for a showdown with animal models. His company makes “digital twin” systems in which data from organ chip systems inform whole-human simulations of drug outcomes and disease progression. “I love what we are doing,” says Maass, speaking not only of his company but of the whole field. But he adds that researchers have not yet provided “the evidence and the proof that we are doing better or as good as the animal models.”
Maass thinks that head-to-head comparisons are essential to good science. After all, if a NAM doesn’t outperform an animal model, or works best as a complement rather than a replacement, that needs to be known. He also believes such studies could convince skeptics. Maass mentions the debut of the
iPhone
, when people saw for the first time how well a phone could work without buttons. “That was an ‘aha!’ moment,” he says. But for NAMs, “that moment is still lacking.”
Changing Scientific Habits
Even when those head-to-head comparisons are made, though, and regulations are appropriately changed, adoption can be slow. In the mid-1990s, researchers developed and validated the
monocyte activation test
—an assay that uses human blood cells to predict immune response—to replace the rabbit pyrogen test, which involves injecting a compound into a rabbit’s ear and monitoring the animal’s rectal temperature. But it wasn’t until 2010 that the European Pharmacopeia—the official Europe-wide standards for such testing—accepted the monocyte activation test as a replacement. And rabbits are still widely used for this test worldwide.
Why the slow pace of change? In part because updates to guidance documents referring to animal tests lagged behind, but also because of inertia within the culture and institutions of science. “The formal requirement may disappear, but the informal expectation persists,” says
Kathrin Herrmann
, a veterinary scientist and colleague of Hartung’s at the Center for Alternatives to Animal Testing. Regulators, grant reviewers, peer reviewers, journal editors—the human infrastructure of science—often still expect to see animal data and are unfamiliar with NAMs.
Herrmann is now overseeing a survey of early-career researchers working with, or trying to make the switch to, NAMs. “We consistently hear concerns that NAM-only proposals are perceived as risky by funders, that there is pressure to ‘add an animal experiment’ for credibility, that access to NAM infrastructure is limited, and that career trajectories become uncertain when departing from established animal models,” says Herrmann.
The vast majority of drugs entering clinical trials in the United States fail to reach FDA approval, with particularly high failure rates in some therapeutic areas.
Animal models are embedded in
databases
, training programs, and the very culture of research. Scientists who use animals may be reluctant to change; their identities as researchers are tied to animals and, more practically, they’ve spent their careers learning the techniques. A toxicologist who has used rats for decades might understandably look askance when asked to take a chance on unfamiliar chunks of polymer and stem cells—especially when human well-being, or millions of dollars, may ride on the choice. Likewise, an academic scientist whose career was built on animal models may not welcome NAMs; a switch may represent the loss of jobs for lab members whose expertise is no longer relevant. “I could see why it’s a hard thing for people to take it up,” says Ingber.
Education and training is vital, say NAM proponents. The
NIH
and FDA now offer resources for researchers interested in NAMs, as do their counterparts in other countries embracing the technologies. Herrmann helps run webinars where researchers and regulators learn to use and evaluate NAMs; Hartung’s modules on Coursera, the
online learning
platform, have been taken by about 12,000 students so far. “These trainees will set up their own labs. They will go to industry. They will replace the old guard,” says
Joseph Wu
, director of
Stanford
University’s Cardiovascular Institute.
Wu is also a cofounder of
Greenstone Biosciences
, a company that uses stem-cell-derived human tissues and AI to model disease and predict drug responses. He’s used that position to introduce researchers to NAMs, helping convince the company’s directors to freely share Greenstone’s large library of stem-cell lines with any academic researchers who want to use them. “I really believe that people should understand how this platform works,” says Wu. “At the end of the day, we’re just trying to advance science.”
With enough time—and funding, incentives, training, education, collaboration, and generational turnover—the research culture of drug development and safety testing may shift. Whether NAMs will be used in other areas of science, though, is an open question. Early-stage drug development and regulatory testing account for roughly 30 percent of animals used in experiments; the rest are used in basic biological research. Replacing those animals is less straightforward, but it may be possible: Ingber describes organ-on-a-chip-based insights into inflammatory bowel disease, preterm birth, and treating viral infections that couldn’t have been made in animals. Hartung calls the adoption of NAMs in toxicology a “lighthouse function,” helping guide the way for other types of research.
“Suddenly, all the dams have opened,” he says.
Training AIs to Solve CAPTCHAs
Schneier
www.schneier.com
2026-10-19 07:07:43
Interesting research:
Abstract: Vision-language models (VLMs) can solve visual CAPTCHAs without task-specific training, but the agents built on them approach every challenge from scratch. For such an agent, the hundredth instance of a familiar puzzle costs as much time and compute as the first. Spec...
Abstract
: Vision-language models (VLMs) can solve visual CAPTCHAs without task-specific training, but the agents built on them approach every challenge from scratch. For such an agent, the hundredth instance of a familiar puzzle costs as much time and compute as the first. Specialized detectors invert the trade-off, answering in milliseconds but only for categories they were trained on. Neither improves with exposure. We study what changes when a solver improves with use. Our system pairs a fine-tuned YOLOv8 detector with an open-weight VLM behind a confidence-based router, and runs entirely from screenshots and operating-system input events, with no browser automation or DOM access. It reaches 85.4% overall and 84.2% macro accuracy across 16 classes, exceeding either component alone. Every answer VLM produces also serves as a training label, so the detector absorbs categories it was never trained for, typically after one or two encounters and without human annotation. The same loop also repairs it. A CAPTCHA operator can perturb images against the publicly released detector and drive its accuracy to 0%, but the perturbations leave VLM untouched, and its labels let the detector recover. Under a year-long simulated arms race in which the CAPTCHA operator re-crafts its perturbations each month, the solver recovers every round, and a cheap ~70%-accurate open-weight teacher hardens it as effectively as a perfect oracle. Visual CAPTCHA defenses that assume a failing bot stays failing therefore understate how quickly an adaptive solver returns.
Let's Encrypt is adding two new remote perspectives for domain validation. This change is motivated by the fact that increased perspectives provide more domain validation security and is required by the
Baseline Requirements
which is quoted below. Increasing the number and coverage of our domain validation perspectives improves visibility and protection against BGP attacks.
BR 3.2.2.9 Multi Perspective Issuance Corroboration
Effective 2026-12-15, the CA MUST implement Multi-Perspective Issuance Corroboration using at least five (5) remote Network Perspectives. The CA MUST ensure that the requirements defined in Quorum Requirements Table are satisfied, and the remote Network Perspectives that corroborate the Primary Network Perspective fall within the service regions of at least two (2) distinct Regional Internet Registries. If the requirements are not satisfied, then the CA MUST NOT proceed with issuance of the Certificate.
During domain validation, this means that we will make seven total validation requests, one from the primary datacenter and six from remote perspectives
(previously four)
. For validation to succeed, the primary server and a quorum of remote perspectives must receive the correct challenge response. This makes it more difficult for attackers to hijack validation requests. To learn more about multi-perspective domain validation, please see
our earlier blog post
when Let's Encrypt first added new perspectives.
We expect little to no impact to users. Let's Encrypt will begin performing domain validation with the new regions in staging on
Tuesday, October 27th, 2026
. Assuming all goes well, we will do the production rollout on
Tuesday, November 10th, 2026
. Updates will be posted in this thread.
Happy issuance!
AI firm Anthropic to commit 5% of shares to fund for ‘public good’
Guardian
www.theguardian.com
2026-10-19 06:47:49
The $48bn giveaway by company, which is preparing to list on stock market, comes amid concerns about the tech Anthropic has said it will commit 5% of its shares to a fund for the “public good”, as the AI developer behind the Claude chatbot seeks to bolster its appeal before its stock market listing....
Anthropic has said it will commit 5% of its shares to a fund for the “public good”, as the AI developer behind the Claude chatbot seeks to bolster its appeal before its stock market listing.
The company announced that it would commit the shares, worth around $48bn (£36bn) at its latest valuation in May, subject to shareholder approval. It will add a further 2% of its stock to the fund for every 50% increase in its value above an undisclosed baseline.
The fund will allow Anthropic to “explore large donations to traditional nonprofits or direct distributions to specific populations”, it said.
It comes amid growing public nervousness about AI, from the threat to human labour to the impact on the environment and its influence on social behaviours.
“AI may generate enormous economic value, but it could also cause instability for many workers,” Anthropic wrote in a blogpost.
It said that while it had already committed $200m to addressing the issue, “given the pace of AI progress, bolder approaches may be needed. The fund will have the versatility to pursue them.”
Anthropic was valued at $965bn in May when it raised $65bn in a funding round. The company is reportedly considering a $1.5tn valuation when it floats on the stock market, with an IPO planned for November.
Last week Anthropic warned that some of its AI models could soon become “self-replicating” and find ways to infiltrate internet-connected devices such as smart fridges and automatic vacuum cleaners.
Elon Musk plans to ‘give one of my SpaceX shares to every kid in America’.
Photograph: Gonzalo Fuentes/Reuters
It said that once this happens, the models would be able to power themselves without the need of datacentres.
Elon Musk, the chief executive of Tesla and founder of SpaceX, responded to Anthropic’s plans for a public benefit fund on social media by pledging to give some of his own shares away.
“I recommend giving the shares directly to the public,” he wrote. “This is what I will be doing.”
He later announced: “Next year, I will give one of my
SpaceX
shares to every kid in America. This will be the first of many.”
Shares in SpaceX, which is listed on the Nasdaq in the US, rose by 1% in pre-market trading on Monday. The company has lost about 9% of its value since it joined the stock market in June.
OpenAI, the developer behind ChatGPT, also reportedly engaged in early talks to give a 5% stake in its organisation
to the US government
.
Anthropic, which was founded in 2021 by seven ex-OpenAI employees, was established as a public benefit corporation. It means that all of the company’s directors must balance financial returns with its public interest mission.
Documents: Police officer gave her Flock login to her ICE agent husband
A now-former Savannah police officer gave her husband, an Immigration and Customs Enforcement agent, access to the police department’s Flock license plate reader system, which he used to conduct hundreds of searches tied to ICE investigations, according to newly obtained documents reviewed by WJCL 22 News.
The records show Amber Harpe's husband did not have his own Flock account through the U.S. Department of Homeland Security. Harpe acknowledged giving him her Savannah Police Department username and password.
Her husband told investigators he used the account to locate ICE targets who had active arrest warrants. He said every search was related to his federal law enforcement work and denied using the system for personal reasons.
The Savannah Police Department fired Harpe after concluding that she knowingly gave an unauthorized person access to a sensitive police system, violated department policy and compromised safeguards designed to track who was using law enforcement data.
The investigation began after an internal audit flagged an unusually high volume of searches through Harpe’s account between January and July 2026.
The audit identified 983 search entries involving 97 identifiable license plates from Georgia, New Jersey, Maryland, Florida, South Carolina and North Carolina.
South Carolina plates represented most of the activity. Forty-eight South Carolina plates accounted for 788 search entries, according to the records. Department documents also noted that most registered vehicle owners identified in the audit were Hispanic.
During a July 27 administrative interview, Harpe told investigators she did not recognize the names connected to many of the searches. She said her husband performed most of them.
Harpe attributed the searches involving Maryland and South Carolina plates, along with most of those involving Georgia vehicles, to her husband.
She said she rarely used Flock herself and generally accessed it to help investigate missing-person cases involving behavioral health patients.
Harpe acknowledged that she allowed her husband to use her credentials and understood she was not permitted to share her access.
Below file video: Savannah city leaders defend Flock technology after alleged misuse by police employees
Husband said searches targeted wanted people
Harpe’s husband’s name is redacted in the documents obtained by WJCL 22 News. However, audio from interview between Savannah Police and the husband identifies him Tyler Harpe, a federal ICE agent.
During an Aug. 3 interview with Savannah police investigators, Harpe confirmed that he asked his wife for her login information because he did not have Flock access through his federal job.
He said ICE had already developed “target packages” for the people he searched and that those individuals had active arrest warrants. Flock allowed him to try to locate them while working in the field, according to the investigative report.
Tyler Harpe estimated that he used the account for about four months. He said he stopped roughly three weeks before his interview because the agency no longer conducted vehicle stops and he no longer needed the system.
Harpe gave investigators a slightly different timeline, saying her husband stopped about a week before her interview because he was concerned she could face discipline.
He denied searching for relatives, former romantic partners or anyone for personal reasons. He maintained that every person he searched was an ICE target and said the Flock information helped his agency locate wanted people with criminal histories.
He also acknowledged that using another officer’s account could violate policy.
“The investigation established that Amber Harpe provided her Flock Safety credentials to her husband,” the final report said. “Both provided consistent statements that the searches involved ICE targets and were conducted for law-enforcement purposes.”
In the documents, Maj. Michelle Halford wrote that SPD does not participate in federal immigration enforcement. She said the demographic pattern identified in the audit, combined with Harpe’s husband’s role as an ICE agent, raised concerns that department resources had been used without authorization to further immigration enforcement.
Harpe’s decision gave her husband the ability to search for and track people through a Savannah police system even though he did not have independent access through his federal employment, Halford wrote.
She said the arrangement exposed the Police Department to legal and reputational risks.
“Public trust is non-negotiable,” Halford wrote. “These tools exist to keep our community safe, not for personal or unauthorized use.”
The investigation did not find that Harpe violated Georgia’s law governing automated license plate readers. The disciplinary case instead centered on an SPD information-management policy prohibiting employees from allowing unauthorized people to access city or department software.
Below file video: 6 Savannah police employees fired after alleged misuse of Flock cameras
Supervisors disagreed over punishment
Department leaders agreed that Harpe violated policy, but they initially disagreed over whether she should be fired.
Interim Maj. Max Nowinsky sustained the allegation and recommended an eight-hour suspension.
Nowinsky wrote that Harpe showed poor judgment by providing direct access to her husband. However, he also emphasized that investigators found no evidence the searches were conducted for personal reasons or personal gain.
He cited Georgia law allowing law enforcement agencies, including federal agencies, to exchange captured license plate data for legitimate law enforcement purposes.
Nowinsky also considered Harpe’s work history. She joined SPD in March 2020, served in the Behavioral Health Unit and had no prior disciplinary record. Department documents described her as a well-respected employee.
Halford rejected the proposed one-day suspension and recommended termination, citing the intentional sharing of credentials, recurring unauthorized access and scale of the activity.
Assistant Police Chief Robert Gavin agreed that Harpe should be fired.
Gavin acknowledged that state law permits law enforcement agencies to share license plate information for legitimate purposes. He said that authority did not allow Harpe to share her personal login information or let another person access the system under her identity.
“Credentials are assigned to one authorized user to ensure accountability, audit integrity, and system security,” Gavin wrote.
Because the searches were recorded under Harpe’s account, the system’s audit trail identified her — not her husband — as the user.
Gavin concluded that Harpe knowingly allowed her husband to bypass SPD’s security protocols and undermined the department’s ability to oversee the use of sensitive information.
Harpe accepted responsibility for sharing her credentials but argued that firing her was excessive.
In her appeal, Harpe said her husband was a certified federal law enforcement officer and that every search was conducted for law enforcement purposes.
“The violation occurred because I gave my husband, who is a certified law enforcement officer with the Department of Homeland Security, access to my Flock account,” Harpe wrote. “Every search he conducted was for law enforcement use only and not for personal gain.”
Harpe said she was trying to assist another agency in the same way she would expect another agency to help Savannah police.
She also argued that the result would have been no different if she had personally conducted each search at her husband’s request and then provided him with the information.
“There was no malicious intent, no personal gain, and no intent to harm the Department or undermine public trust,” Harpe wrote.
She asked department leaders to consider her clean disciplinary history, years of service and the investigation’s finding that the searches were related to law enforcement work. She requested a written reprimand or, at most, the one-day suspension Nowinsky recommended.
Gavin denied her appeal Aug. 11, and the police chief’s office agreed with the termination recommendation two days later.
Harpe requested a hearing before Savannah’s Civil Service Board on Aug. 19. City records show her termination took effect Sept. 26.
She withdrew the appeal around Sept. 28, and her Oct. 13 Civil Service Board hearing was canceled.
The newly obtained documents do not explain why she withdrew the appeal.
Harpe’s case was part of a wider SPD investigation into alleged Flock misuse. Several other former employees were accused of searching for romantic partners, former partners or other people for personal reasons.
Culture and the Moment
OrganizingUp
convergencemag.com
2026-10-19 06:01:50
“Why Culture Matters to Justice” is a series of essays commissioned by the National Performance Network as part of their Culture Justice Initiative (CJI). Believing the value of this content goes beyond our organization, NPN reached out to online publications within the arts and social justice movem...
US teens can access ‘nudify’ apps despite Apple and Google’s parental controls, report finds
Guardian
www.theguardian.com
2026-10-19 06:00:05
Exclusive: Using test accounts acting as 13-year-olds, Tech Transparency Project downloaded 135 apps with features to generate nonconsensual nude imagery In December 2025, Morgan Dorfman received distressing news: a student at her daughter’s Pennsylvania high school was making AI-generated pornograp...
In December 2025, Morgan Dorfman received distressing news: a student at her daughter’s Pennsylvania high school was making AI-generated pornographic material using the daughter’s image.
He was using an
artificial intelligence
image-editing app called Movely to create sexual videos from pictures of her daughter and five other girls.
What Dorfman’s daughter experienced is not an anomaly:
students
in
high
schools
across
the US
are reporting similar cases. Their classmates are generating nonconsensual pornographic or nude imagery using so-called “nudify apps”.
Governments around the world have moved to ban these AI platforms from app stores, and most US states have implemented laws that criminalize possession of AI-generated child sexual abuse material.
TTP researchers created four test accounts, two Apple accounts and two
Google
accounts, indicating the account holders were 13 years old. They searched for image-editing or face-swapping apps using terms such as “AI video generator” or “adult AI”. Using these accounts for a purported 13-year-old, the researchers were able to download 135 apps with features enabling them to strip people of their clothes or swap their faces on to nude bodies. The researchers disrobed women in AI-generated images in their tests rather than using photographs of real women.
At the time of her daughter’s distress, Dorfman didn’t know it was possible to create pornographic material of an everyday person so easily.
“All the girls were very scared and confused about what to do next,” Dorfman said. “I knew what a deepfake was, but I thought it was like Taylor Swift and people using celebrities’ [images],” Dorfman said. “I didn’t know it was possible to take any picture or any screenshot of anybody that you have and do this.”
Dorfman, a mother of four, spent weeks trying to figure out how the app worked and compiling material to educate other parents. She downloaded Movely and was immediately prompted to create suggestive videos using any image. The free version promoted sexually suggestive templates including “clothes explosion”, “brassiere unfasten” and “underwear drop”, according to a demonstration Dorfman put together for parents that the Guardian reviewed. In the paid version, it became more explicit: she saw templates for the types of pornographic situations in which, according a classmate, her daughter had appeared.
Both
Apple
and Google prohibit these types of apps from being distributed on their platforms. The companies also will often age-gate apps with adult content, restricting or blocking minors’ access. However, TPP researchers found that the companies largely rely on the developers to determine whether their apps are appropriate for certain ages.
“Many nudify apps identified in the investigation were inaccurately rated as suitable for minors – meaning the teen users could access them even when parental controls were activated,” the report said.
Researchers found that one face-swapping app, which was advertised to them with an image of a woman performing oral sex, was rated appropriate for ages four and up. The free version of the app prompted users to superimpose real women’s faces on to templates of women in lingerie or, if users paid, in pornographic situations. The researchers were able to buy a subscription to the app from a 13-year-old’s account without an alert to a linked parental account.
Google said the company regularly takes “proactive steps to detect and remove apps with harmful content”.
“When violations are detected or reported to us, we investigate and take swift action, which in this case included suspending violating apps and restricting related search terms on our store,” Google spokesperson Dan Jackson said in a statement.
After TTP contacted Apple seeking comment on the findings of their study, Apple implemented changes that strengthened content moderation guidelines. The
company now requires developers
to preemptively prevent and remove nonconsensual intimate imagery including AI-generated images. Apple also said that the company reviews every app before it is published and that if a developer misrepresents any features, the company removes the app and its developers. The company said in addition to apps they already removed before the TTP report was shared with them, the company has also “taken action” on the remaining apps mentioned in the report.
“A number of the apps in this report are mainstream photo and video editing tools with legitimate, widely used functionality, and do not have nudification or deepfake capabilities,” said Apple spokesperson Adam Dema. “We prohibit nudify apps on the App Store, and remove developers who add capabilities like it after the App Review process – a malicious tactic known as bait-and-switch.”
Of the four accounts the researchers created, two were placed under parental controls that only allowed users to download apps marked suitable for 13-year-olds and only then with a parental signoff. However, the researchers found that neither Apple nor Google required or suggested parental signoff to acquire any of the nudification apps.
‘We prohibit nudify apps on the App Store, and remove developers who add capabilities like it after the App Review process’, an apple spokesperson said.
Photograph: Lee Hudson/Alamy
One app, Image to Video Maker-Vidou AI, was rated appropriate for users aged nine and older. Upon opening the app, users were greeted by an image of a topless woman on a bus, according to the TTP study.
“The app had a feature that promised to digitally undress any person – and to demonstrate, it showed nude images of female celebrities,” the report read.
Age restrictions were also not entirely effective, the study found. In one case, when the researchers tried to download an adult-rated app from the Apple App Store, they came across a pop-up warning that the app contained “age-restricted material”. But all they had to do was confirm they were 17 or older, which Apple allowed the account to do despite its registered age being 13. The Google account without parental controls was blocked three times from downloading an age-restricted app but otherwise allowed the researchers to download nudification apps that were self-reported to be age-appropriate.
The Apple account that TTP set up parental controls for was still able to find and download 24 so-called “nudify” apps because they were all rated as appropriate for 13-year-olds. The Google account with parental controls was able to download 51 of these apps.
Removing image and video editing platforms from app stores was also not enough to prevent its use. In the course of TTP’s research, Apple took down 25 of the nudify apps, and Google took down six. However, the researchers were able to continue using the app since they had already downloaded it.
Dorfman had a similar experience with Movely, she said. While preparing a presentation for parents and law enforcement officials, she returned to the app and App Store to take screenshots when she realized it was no longer available to download. However, the app was already on her phone and it remained entirely functional. She was also still being charged for her paid subscription.
Once these nonconsensual images and videos are created, accountability proves evasive, Dorfman has found. “I just wanted someone to make him delete all of these videos,” she said.
In her daughter’s case, Dorfman feels her school has downplayed what happened. In a school-wide email the Guardian reviewed, the principal wrote that her daughter’s classmate did use the app to animate images of other students but that there was no evidence he had done anything inappropriate.
“The whole thing was dismissed as ‘it’s not real’,” Dorfman said. “The haunting trauma as a mom is that I can’t tell [my daughter] those videos are gone or who had them. We can’t search everyone’s phones, and he deleted the app.”
The Army Wants to Sic AI Agents on Its Enemies. What Could Go Wrong?
Intercept
theintercept.com
2026-10-19 06:00:00
Documents obtained by The Intercept show the military is trying to deploy autonomous AI agents to hack its adversaries.
The post The Army Wants to Sic AI Agents on Its Enemies. What Could Go Wrong? appeared first on The Intercept....
As global governments
and tech giants reckon with widespread of revelations of autonomous AI agents unexpectedly breaking into computer systems, documents obtained by The Intercept show the U.S. Army is looking to harness that exact technology to seek and destroy.
Army Cyber Command is developing a platform to turn AI agents into autonomous weapons that can navigate and “neutralize” the computer systems of adversaries, the documents show.
Since 2010, Army Cyber Command, or ARCYBER, has led the U.S. Army’s cyber operations. This includes the defensive effort of protecting domestic computer systems and the secretive offensive work of hacking military targets. So far, this has largely been the work of human soldiers operating computers, like those of the 780th Military Intelligence Brigade. But as the government races to adopt artificial intelligence technology, ARCYBER is looking to offload some of its attacks to AI.
The nascent program, codenamed “ECHOTRIBBLE,” is based on one of the leading trends of the AI boom: agents. AI agents are essentially software programs that leverage machine learning technology, often large language models like Anthropic’s Claude, to autonomously accomplish tasks provided by their user. Consumers can deploy AI agents to schedule meetings, generate itineraries, make online purchases, or book tickets. Through ECHOTRIBBLE, the Pentagon plans to turn AI agents into tools of war “designed to autonomously navigate infrastructures” and capable of “identifying and neutralizing identified threats/targets,” according to an ARCYBER document reviewed by The Intercept circulated to potential contractors.
The military’s adoption of cutting-edge technologies is unsurprising, especially considering Defense Secretary Pete Hegseth’s
fervent embrace of AI
. But amid
constant revelations
of
rogue behavior
by agents, the potential for serious mishaps is immense, experts warn.
“Given the known failure modes of the current AI paradigm, making autonomous AI systems with a mandate to ‘neutralize threats’ is incredibly dangerous,” David Krueger, a professor of machine learning at the University of Montreal who founded Evitable, an organization that advocates for a moratorium on AI development. “We’ve seen AI systems knowingly attack systems that were not intended targets. In simulations, AIs have even proven willing to kill to achieve their goals.”
A Q&A document answering questions from potential contractors offers more details about the initiative. It explains that ECHOTRIBBLE is “primarily focused” on offensive missions, and explains that “neutralizing” a target could include “disabling the threat completely or temporarily, deleting the threat from the target.” ECHOTRIBBLE would function almost like a computer worm, silently navigating a foreign network and hopping from device to device until it finds the Army’s quarry, hitting targets in the cloud as well as those on “air-gapped” systems that are disconnected from networks entirely.
Once its task is complete, ECHOTRIBBLE’s agents would effectively self-destruct, ideally without having been noticed by the target at all. The agents themselves will be designed for stealth, minimally reporting back to the Army and concealing whatever outside transmissions are necessary.
“We’ve seen AI systems knowingly attack systems that were not intended targets.”
Although documents say the Army will be able to program ECHOTRIBBLE agents with some initial “predefined triggers” — dictating what and where to attack — the software “must operate with minimal human oversight” and be capable of “Self-Directed Behavior.”
A PowerPoint presentation to interested vendors at
a June 24 ARCYBER event
provided a hypothetical example of this self-direction. Once ECHOTRIBBLE is uploaded to a laptop, the software on its own “identifies other potential targets” on the same network and then “produces a replica of itself tailored specifically for the iPad, Apple desktop, and Windows 11 PC.”
An image from an ARCYBER document shows how ECHOTRIBBLE could move through a network.
Slide: ARCYBER
The Army’s move toward autonomous self-propagating comes after a flurry of revelations about agentic systems taking unintended disturbing actions while attempting to accomplish their goals, including breaking into computers of the Australian government,
breaching the infrastructure
of the AI firm Hugging Face, uploading malicious software into online platform RubyGems, and attempted to
hack into
the U.S. Education Department.
These attacks occurred during scenarios in which agents had been given no commands to attack anything. Experts say militarized versions given explicitly destructive objectives could cause a threat to the public, even with nominal rules set in place by the military. Just as
the Army of old
might consider the
destruction
of
civilian infrastructure
an
acceptable means
to
an end
, a self-directed AI agent dispatched by the Pentagon might make similar determinations about collateral damage.
Governmental intelligence agencies frequently route their offensive operations through civilian devices. Volt Typhoon, a Chinese state hacking group, has directed its attacks through homes and small businesses, and preemptively hacks American IT systems for later use. A hack of a Chinese university attributed to the National Security Agency made use of the school’s internet routers. What happens if ECHOTRIBBLE decides these kinds of stepping stones are part of the problem?
“The target may well be hit. But what path will it take?” asked Hyrum Anderson, co-founder and CEO of the AI security firm Abundant. “Will it go through a US water utility on its way, because that’s where the adversary has staged its command and control, and take that down too?”
Anderson, who previously worked in cybersecurity at Microsoft and for the U.S. government, said that a vast amount of the internet is vulnerable to agentic attacks.
“There’s a huge class of public and private organizations that fall below the security poverty line,” he said. “They include critical national infrastructure, small businesses, mom-and-pop shops, dentist offices and law firms, and whoever else doesn’t have a single cybersecurity professional on staff.” With their networks wide open to infiltration, Hyrum worries about “these organizations getting hit directly, or getting caught in the blast radius of a target that gets hit along the way.”
Given the impressive ability of AI agents to overcome obstacles placed in their path — even by their creators — it follows that the Pentagon would want to leverage that power for military purposes. But agentic software has proven unpredictable and prone to executing its commands in ways those ostensibly in control did not want, akin to a drone that get its target but hits a hospital on the way. It’s critical to remember that agents are a piece of software lacking human judgment.
“One of the reasons that we trust 19-year-old Marine corporals in Ramadi with live rounds and a weapon is because they have both the compute substrate — the brain and the eyes — but the deep world knowledge to understand, ‘Yeah, I probably shouldn’t do that,’” said William Marcellino, a senior behavioral scientist at the RAND Corporation whose research has focused on military AI applications. “That is not something that current public AI technology has.”
The risk presented by ECHOTRIBBLE will likely depend on the ability — and willingness — of the Army to
impose guardrails
upon it. ARCYBER did not respond to questions from The Intercept, including queries about the measures it would take to prevent ECHOTRIBBLE from causing inadvertent damage.
Placing constraints on the actions an agent can take might impede its ability to ultimately neutralize a target. But even with strict safeguards in place, genuinely restricting the behavior of an autonomous agent, as Anthropic and OpenAI have learned recently, is easier said than done. When presented with obstacles, AI agents have proven an ability to bypass them with unpredictable and potentially dangerous consequences.
“If I give powerful machines that have no judgment — and no context for judgment — a goal, unless you’ve done a really good job building scaffolding around them, there’s a real chance that they’ll go sideways on you and decide, ‘Well, I’ll do what you asked me to do, but I’ll do it this way,’” Marcellino said.
It only gets more dangerous when this technology is deployed for the purposes of war, Anderson said.
“Under pressure, they’ll often treat guardrails as obstacles,” said Anderson. “Once you add context that says break it, destroy it, shut it down, it stands to reason that the blast radius widens dramatically unless it’s properly controlled for.”
Timestral: Mistral release time-series foundation models
Timestral, Mistral’s first family of time-series foundation models, delivers state-of-the-art probabilistic, multivariate forecasts with just 209M parameters, outperforming larger models on key benchmarks while supporting past and future covariates. Available in four sizes (5M to 209M parameters), it balances accuracy and efficiency, running efficiently on CPUs and excelling in zero-shot forecasting for diverse domains. The model combines synthetic pre-training, covariate-aware attention, and long-context learning, with fine-tuning options for domain adaptation via Mistral Forge.
Today, we’re releasing Timestral, our first family of time-series foundation models. Our largest model, at just 209M parameters, ranks first on all three of the field's main public benchmarks, GIFT-Eval, TIME, and fev-bench, outperforming the previous state of the art with only two-thirds of the model parameters.
Timestral delivers probabilistic, multivariate forecasts and supports past-only and known-future covariates. Our family of models sits on the Pareto front of forecasting accuracy versus model size, delivering leading performance at each size. Results have been submitted to the GIFT-Eval and TIME leaderboards.
Time series is one of the most common data types in enterprise, from sensor telemetry to observability metrics. Forecasts built on it drive decisions in capacity planning, energy, supply chains, risk and maintenance.
Industrial plants forecast process sensors against the production schedule, catch equipment drift before it fails, and plan capacity and spare parts across thousands of assets. Finance teams forecast flows, volumes, and volatility to inform positions, hedging, and treasury across thousands of accounts.
Classical models such as ARIMA and linear regression remain well-established tools for forecasting time series. These models are usually fitted to a single series and learn only from that series' history.
Deep learning models such as PatchTST add the capacity to learn nonlinear patterns across many related series, but they are still typically trained from scratch on each dataset, so what they learn doesn't carry over to new domains.
Time series foundation models bring the pre-training approach to time series. Trained on a large and diverse corpus, our model learns patterns that transfer across series, forecasting zero-shot on data it has never seen, even in domains where data is scarce.
Benchmark Results
We evaluated Timestral on the three main public forecasting benchmarks: GIFT-Eval, TIME and fev-bench. Among pre-trained, zero-shot models, it ranks first across all five metrics. These results come from a single checkpoint, without ensembling.
GIFT-Eval, top ten of 83 comparable pretrained and zero-shot entries. Lower is better.
TIME, top ten of the 35 leaderboard entries. Lower is better on both metrics.
fev-bench, top ten of the 37 leaderboard entries, by SQL skill score. Higher is better.
Family of models optimised for every specification
Timestral has been optimised as a family of four models: 5M, 28M, 123M and 209M parameters. The larger models improve forecast performance, while the smaller ones are faster and cheaper. All four share the same architecture and training recipe. Every size sits on the Pareto front of accuracy versus model size: for each model size, no public model forecasts better.
Score vs model size on GIFT-Eval, TIME and fev-bench (shown as 1 − skill score). Lower is better. Our 28M model beats Chronos-2, about four times larger, on GIFT-Eval and TIME. Our 209M model beats TimesFM-3 and Falcon-2.0 with fewer parameters.
Timestral does not need a GPU at inference. On a standard server CPU with 8 threads, forecasting one day ahead from three weeks of 15-minute history takes 10 ms with the 5M model and 140 ms with the 209M model. Smaller models trade some accuracy for speed: the 28M model is five times faster than the 209M model, and the 123M model comes within 0.2% of the 209M score at three quarters of its latency.
An industrial example
Consider an industrial plant with thousands of sensors across its equipment. Timestral can improve the forecasts on that data in several ways.
Multivariate forecasting.
A pump's vibration, temperature and pressure don't move independently. A rise in one often explains or causes a change in another. Timestral models related series jointly, so it can use those dependencies instead of forecasting each sensor in isolation.
Probabilistic forecasting.
A single predicted value may not show the full picture. Timestral predicts a full set of quantiles, so teams can see how wide the uncertainty is, set alert thresholds that reflect it, and plan maintenance around risk rather than a single number.
Categorical covariates.
Some covariates take values from a set of categories rather than continuous numbers, such as the day of the week, or a machine's state (running, idle, under maintenance). Encoding these as numbers would impose an order or scale they don't have. Timestral takes them as categorical inputs directly to improve forecasts.
Known-future covariates.
Some drivers of sensor behaviour are known in advance, such as production schedules, planned shutdowns, weather forecasts. Timestral can condition on them to improve forecast quality, so a scheduled load increase is expected rather than flagged as a surprise.
From Model to System
Timestral is a numerical model that can run inside existing monitoring pipelines, or be paired with our language models in multi-modal agentic workflows.
In the plant, that could look like this:
Timestral running continuously on the plant's sensor streams, detecting anomalies as they occur.
When it flags an anomaly on a pump, an agent embeds the signals and compares against embeddings of past sensor data to find similar historical failures.
The agent then starts sub-agents to run a root cause analysis, drawing on context from that plant, such as maintenance records, shift logs and operator notes, equipment manuals, past work orders, and readings from related equipment.
The agent drafts a suggested diagnosis based on the findings, with supporting evidence and possible next steps.
The plant manager gets a diagnosis and a plan backed by the sensor data, rather than just an alert.
Key technical contributions
Several ideas have been combined to produce these results. Each will be described in detail in the technical report.
Decoupled Horizon Forecasting.
Causal decoders trained with contiguous patch masking, as in Toto 2.0 and TimesFM-3, mask out the values to be forecast, so they look like missing values and are also lost as context for later forecasts. Our approach, DHF, separates the two: the full history stays in the sequence, and learned forecast tokens read the history before them. Every observed value thus serves as both target and context, true gaps stay flagged as missing, and training horizon lengths and missing-data augmentation can be tuned independently of each other.
Covariate-aware attention.
Each input series is assigned a role: target variate, past-only covariate or known-future covariate. Known-future covariates are visible across the whole window while targets stay causal, and information flows only from covariates to targets. Timestral can therefore use a holiday calendar or a weather forecast without leaking a target's own future into its forecast.
Synthetic-first data.
The majority of the training data was synthetic. We first generated univariate processes with coherent temporal dynamics, including trends, seasonality and diverse noise patterns. We then used a multivariate synthesizer to construct multivariate series by introducing nonlinear dependencies between these processes.
Two-stage training.
Timestral is first pre-trained at scale on purely synthetic data with context size 8192, then post-trained on a mix of real and synthetic data with a 4x longer context. The objective is a pinball loss over 21 quantiles, a discrete approximation of CRPS.
A model that can be adapted
Public benchmarks measure general performance, but production data can be significantly different in behavior and structure. It may also shift over time as markets change regime, equipment degrades and demand patterns move. The lasting value lies in being able to adapt a model to in-domain data and keep retraining it as the distribution moves.
For organisations that want to go further, Timestral is available through
Mistral Forge
, the same training pipeline we use for our language models. It supports:
Zero-shot inference
out of the box.
Architectural extensions
, such as domain-specific covariates.
Fine-tuning on proprietary data
, specialising to a domain while preserving general performance.
Control over the training data
, including adjusting the training mix, replaying pre-training data, and generating synthetic data samples to reflect the target domain. Full control over the data ensures that nothing we backtest was seen during pre-training.
The full pipeline can be deployed on our clients’ hardware, including air-gapped environments.
What’s next
We have published a
GitHub repository
so you can run Timestral on your own data. A technical report with the full results will follow. For more specialised forecasting problems, or to collaborate on research, please reach out to us.
Timestral
Type
Time-series foundation model (TSFM)
Parameters
5M, 28M, 123M and 209M
Context length
32,768 time steps
Output
Probabilistic forecasts, 21 quantiles
Inputs
Multivariate targets, past-only and known-future covariates
Microsoft: October Windows Server updates break Exchange sign-in, mail flow
Bleeping Computer
www.bleepingcomputer.com
2026-10-19 04:58:41
Microsoft has confirmed that this month's Windows Server security updates are causing OWA sign-in and mail delivery issues on some Exchange Server systems. [...]...
Microsoft has confirmed that this month's Windows Server security updates are causing OWA sign-in and mail delivery issues on some Exchange Server systems.
In a new Windows release health dashboard update over the weekend, Microsoft said users may have trouble accessing email or signing in to Outlook after installing the latest updates on systems running Windows Server 2019 and later.
In some cases, affected customers are also reportedly seeing Exchange Server OWA failing with a "MapiExceptionMdbOffline: Unable to make connection to the server. (hr=0x80004005, ec=1142)" error and Event
ID 1006 in the application log.
"After installing the October 2026 Windows security update [..], some on-premises Exchange servers might experience issues accessing or sending email. Users might be unable to sign in to Outlook on the web (OWA), or email messages sent from Outlook might remain in the Outbox and not be delivered. Additionally, Exchange might experience issues accessing mailboxes during mailbox replication,"
it said
.
"The October 2026 update introduced a default limit on the amount of memory used by Endpoint Mapper when handling Endpoint Lookup calls. For workloads such as Exchange Server, the default limit of 512 simultaneous Endpoint Lookup calls might not be sufficient under heavy load. Administrators can use this registry setting to increase the maximum number of simultaneous Endpoint Lookup calls, which increases the amount of memory that Endpoint Mapper can use."
However, Microsoft says these known issues aren't linked to the October 2026 Exchange server security updates and urges customers not to uninstall them.
"Issues reported are not related to installation of October 2026 security updates for Exchange Server. This is not a 'known issue' related to October 2026 Exchange update. Any version of Exchange that runs on impacted versions of Windows could be impacted,"
Microsoft added
in a separate blog describing the issues.
"Not all Exchange servers will be impacted by installation of those updates equally; the severity and speed of impact varies based on Exchange server load. Some servers might never see a problem."
While it works on a fix, Microsoft also shared a temporary workaround that should resolve these issues by modifying a registry key on affected Exchange Server systems.
To do that, you have to run the following command from an elevated Command Prompt on the Exchange Server and then reboot the device:
After the system restarts, customers should monitor the Exchange environment and raise the Endpoint Mapper memory limit if it reoccurs.
In July. Microsoft
also announced
that it will stop shipping extended security updates for Exchange 2016 and 2019 this month after a 6-month extension announced
in April 2026
to the original Extended Security Update (ESU) program.
For years, Tor Browser has been one of the most effective tools for protecting privacy and bypassing censorship online. But most people don't experience the internet through a browser anymore. They connect to it via their favorite apps. Wouldn't it be nice to extend the same privacy protections to messaging apps, social media, email, and other services?
And for years, we heard this again and again in our user research. People wanted a simple way to protect their entire device, which inspired the idea for Tor VPN back in 2021. We focused on Android first, where the need was greatest and where we could reach the most users in censored regions. We built Tor VPN Beta as a first version, with the expectation that we would learn from real-world use. And when we first launched Tor VPN Beta for Android in a limited release last fall, the primary use case quickly became much clearer: unblock the internet. This has shaped how we've prioritized development and user support in the time since the initial launch, and how we think about the product moving forward.
What makes Tor VPN different
Unlike commercial VPNs, Tor VPN Beta is built on a fundamentally different model. It is our first step into device-level network protection on mobile to extend Tor's protections beyond the browser. Each mobile app on your device gets its own Tor circuit, rather than sharing a single tunnel. That means activity from one app can't easily be linked to another. This type of app isolation is a design choice heavily inspired by the cross-site tracking protections in Tor Browser
1
. It's a different model from most VPNs, and one that's designed to reduce cross-tracking by default.
As Tor VPN Beta has matured, we've also worked on making that app-level control easier to use. The Apps screen is now searchable, so people can more quickly find a specific app and decide whether it should be routed through Tor.
Rethinking how we design for circumvention
While Tor VPN Beta includes features commonly associated with VPNs, such as exit selection, those aren't always the right approach for users trying to bypass censorship. This was one of the most important lessons that came from usability testing and early feedback during the development stage.
We originally explored giving users more control over exit selection, which, on paper, sounded great. But in practice, this introduced confusion. Users trying to bypass censorship were selecting exit locations when they should have been using bridges instead. There was a mismatch between how Tor works and how people expected it to work. This is why the current design required connecting the app to the Tor network first before selecting an exit. Exit selection is still something we want to explore more fully in the future, but it needs to be introduced in a way that doesn't create user error in high-risk situations.
Used where it's needed most
Early on, we saw strong adoption in highly censored regions, including Iran and Turkmenistan. This stood in contrast to Tor Browser for Android, which tends to skew more toward users in the Global North. With Tor VPN Beta, we're seeing much deeper engagement from users in the Global South, people dealing with network restrictions as a daily reality.
Because of how people are using Tor VPN Beta, we've doubled down on improving its circumvention capabilities. One example was prioritizing the addition of WebTunnel bridges with one of the early releases (1.4.0 beta), which helps Tor traffic look like regular encrypted web traffic. This makes it harder for censors to detect and block connections. We have also fixed several bugs and made quality-of-life improvements across bridge support more generally, with the goal of making bridge use more reliable.
Stability and reliability matter just as much as features
In fact, a significant amount of work since the early release has gone into improving stability. Tor VPN is built on
Arti, our next-generation Tor implementation written in Rust
. Under the hood, that means a new, solid technical foundation rather than patching around legacy architecture. One of the immediate benefits is improved reliability, including fewer crashes and better handling of network conditions. We have also invested in making our builds reproducible and getting the app onto F-Droid. Reproducible builds let anyone verify that the binary you're running matches the published source code, while F-Droid availability gives users a way to install and update the app without relying on Google Play, both of which matter for a privacy and security-focused tool.
We set out to extend Tor beyond the browser to close a gap in mobile protection, but the project was quickly being shaped by how people actually use it, especially those who need reliable, device-wide circumvention. So we focused on building the right foundation for Tor on mobile with a modular Tor stack centered on Arti and
Onionmasq
that can evolve with real-world use. These components are now reusable across multiple applications, reducing ecosystem fragmentation and long-term maintenance risk.
-- Duncan, UX-Team Lead/ Product Manager, Tor VPN
There's more work to do here. Tor Browser still sets the standard for what's possible, and part of our goal is to bring Tor VPN closer to that level over time.
What's next?
Tor VPN Beta is the result of a collaborative, multi-year effort. Thank you to
The Guardian Project
for their guidance and critical low-level mobile libraries, and the LEAP Encryption Access Project for their quality work, without both the app would have never seen the light of day. We're
continuing to build Tor VPN Beta
in the open, shaped by how people are actually using it.
That means improving circumvention in restrictive environments, bringing more performance features into Arti, and refining the user experience to reduce confusion and risk.
And most importantly, continuing to learn from the people who rely on it. If that includes you, and you want to help shape the development of Tor VPN Beta, please visit our
refreshed download pages
. In addition to downloading the app as an APK or from the Google Play Store, you can now use F-Droid to access Tor VPN Beta.
Document: WM-105 P. Webb
Category: Tooling 2026-10-11
Beginning of the Ende
Abstract
The trend of VC-backed tooling ending in abandonment rears its ugly
head again. But hey, people gotta eat, right? The community will pick
up the slack and steward the projects, right?
Body
Deno is dead.
Announced[1] on a Friday[2], of course, the team has fled to
Cloudflare and in a year, will stop working on the runtime. Kudos to
them for finding an exit, Womp womp to us.
This is the second time in just as many years that a technology I
depend on is “given up to the community.” If you’re new here, Disc[3]
came about because the team behind Gel fled to Vercel and gave their
project up to the community. This was two years ago and as of this
writing, no updates have been made on the “blessed” fork[4] of it.
(Perhaps a bit petty of me to point out but someone in the Gel
Discord has been rather hostile/cowardly about my efforts and thus I
find delight in proving assholes wrong)
The frustration of the Deno community is palpable and has created the
best crashout[5] I’ve seen in some time:
What the fuck do you mean Deno is ending development in a year????
I JUST learned how to use this stupid runtime.
I don’t give a fuck about your Cloudflare acquisition or your edge
computing or whatever the fuck a Durable Object is.
I JUST WANT TO RUN MY TYPESCRIPT FILES.
Why is there a shutdown date????
WHERE IS THE FUCKING DOWNLOAD BUTTON FOR MORE YEARS OF SUPPORT????
I went to the releases page and there is no deno-forever.exe.
WHY IS THERE NO deno-forever.exe?????
Just compile another 10 years of development into a fucking
executable and give it to me.
I don’t want to learn Node.js again.
I don’t want to migrate to Bun.
I don’t want to understand your business model.
I JUST WANT MY DINOSAUR BACK.
You cannot just Deno.exit(0) an entire runtime.
STUPID FUCKING CLOUD NERDS.
Ryan Dahl’s comment[6] on HackerNews gave me pause (emphasis mine):
It’s a joint decision and I agree with it. I’m most invested in its
success and have put the most work into it - and I no longer think
it’s where I can do the most important work. There are somegood ideas in Deno and it’s well engineered - but it ultimatelyis not solving big problems. It has been sucked into thegravity well of node compatibility, which forces it to behaveexactly as Node does. Why reimplement Node? It works. Marginalperformance or UX or security benefits are not enough.
…
We’ll ship monthly releases for a year, and Deno stays
MIT-licensed. If people want to carry it forward, I’d like that.
My brother in Christ. YOU reimplemented Node and now you’re bored? I
get it was done for adoption purposes but like, that’s a solvable
problem? Whatever, this ain’t my first rodeo[7].
There’s bound to be other forks but this one’s mine; I’m calling it,
Ende (“end” in German). “Ende” is an anagram of “Deno” which is an
anagram of “Node” and it’ll do things differently:
— no more Node compatibility
— no more distractions, period; that means Deploy, KV, Jupyter, &c
are also getting the boot
The roadmap? Per-module permissions, sandboxes for untrusted code,
post-quantum crypto in Web Crypto, better binary output, &c. I depend
on Deno for all of my APIs and personal projects, and now am building
a serious business on it; EOL[8].
I’m aiming for a soft launch in December so I can work out production
kinks before a proper one. It’s gonna be quite the flex when Ende
development is happening on EOL. Anyhoo, placeholder site for Ende[9]
is up, subscribe to the mailing list if you want to be notified when
it’s “official” (proper marketing and documentation websites). EOL
also has a mailing list[8] if you want to know when the beta opens.
I am very busy but excited. I wanted to build the Neue Internet[10]
after all, looks like I’m getting my chance. 🕸️
EDIT: I’m also replacing SemVer with ChronVer[11].
I have been very sick while writing this article. Not really because of BazelCon, but because it’s flu season in my district and I have a toddler attending daycare. So it’s just natural that I started to sneeze and cough as BazelCon approached. Attending BazelCon was fun. Going home with a stuffy nose, a sore throat, and, some days, an empty stomach… not as much. I lost my voice, my kid missed her dad, and here we are.
But I regret nothing. BazelCon 26 was perfect. The talks were highly technical, more than in any prior year. The hallway track was energetic with vibrant conversation. The venue was smaller than last year’s in Atlanta, which seemed to improve the experience since it was so easy to bump into folks I know.
I spent 90% of my time at BazelCon talking to people in the hallway track. For some reason, I cannot stand watching the talks live unless I am deeply invested in the topics. I prefer watching them later, at home, under a blanket at 1 AM while YouTube cranks up the speed to 1.5x.
Here was the event’s official schedule:
Tue, 13th: Training Day
Wed, 14th: General Sessions
Thu, 15th: General Sessions
And here was mine:
Sun, 11th: coffee chat with folks
Mon, 12th: coffee chat with more folks
Tue, 13th: BuildBarn meetup at DataDog. Set up our sponsor booth. Team dinner.
Wed, 14th: Talk to people. Happy hours.
Thu, 15th: Talk to more people. Team dinner.
Fri, 16th: Bazel Hackathon at DataDog. Team lunch.
And some BazelCon attendees wished the event was one day longer… I made mine three days longer, full of hallway conversation, and I loved it.
Front and center of the hallway track was a discussion of the value of tests. This comes on the heels of some company reporting on Twitter that they had recently deleted all of their tests to save CI time. Anthropic also released a version-control blog post describing their investment in post-merge, pre-deploy testing.
“
Redesigning source control at Anthropic”
A common observation among the folks I spoke to is that the latest generation of frontier coding agents is over-RLed with tests. A crap ton of unit tests gets added to each PR, just for the sake of having them. They are often set up with mocks and fakes and dupes, and will be refactored and updated in the next PR anyway. Basically, the agents are bad at identifying the scope at which the tests should be added. This, at scale, adds a lot more pressure on CI than necessary while making the diff harder to review and more expensive to maintain.
But on the other side of the coin, BazelCon engineers understand very well that you don’t go asking for only e2e tests either. These tests are expensive to run, and they rarely cache well between revisions. E2E tests are the last resort and should only be added for major functionality.
This means there exists a sweet spot somewhere between unit tests and e2e tests where the agents should be testing. Where that spot should be depends on the “Risk Tolerance” of the business. Tests can be thought of as insurance policies against future changes and breakages. The more risk you can tolerate, the fewer tests you need. The more assured you want your business to be, the more testing you do.
For example, at an e-commerce food delivery company, a bug that loses a few thousand orders might cost tens of thousands of dollars. For that particular failure, those tens of thousands of dollars are the value of your risk. But at an aircraft manufacturer or a surgical robot company, the risks are not simply calculated in dollars, but in human lives, which I think we can wholeheartedly agree are worth much more than tens of thousands of dollars. This means that these hardware manufacturers should be testing more, checking for flaws more often, and tolerating fewer failures in the final product.
Being at BazelCon means I am surrounded by folks, who not only can reason about these tradeoffs, but have also designed and rolled out such frameworks at scale, while being able to articulate them in layman's terms. I am constantly star strucked by the talent density here.
Folks also think that this will drive up the demand for mutation testing and property testing. Personally, I enjoy equipping my coding agents with a skill that prunes down the added tests guided by “bazel coverage” outputs. I have yet to find a good way to make it do branch coverage, but I suspect it will be much better once I have it set up after this conference.
A surprising effect of coding agents is that your tests in CI can start passing almost all the time. The agents are often already running the tests exhaustively before committing and creating the PR. This creates a blind spot if you rely only on historical CI data to help drive efforts such as Test Pruning or Probabilistic Test Selection. CI data no longer tells the whole story. We also need to measure what happens while the agents iterate. A test that catches an agent’s mistake has earned its keep. Keep it, if not expand it.
Most enterprises don’t have the ability to measure this today. Their telemetry stops at CI because, historically, dev laptop metrics are noisy and endpoint control software comes with various limitations. Bazel and its Build Event Service seem like the perfect solution for this space.
BuildBuddy Target Performance UI
Not only can we capture and tag the metrics for later slicing and dicing, but we can also automatically set up the agents to go over these metrics regularly and fix test performance and prune and consolidate test cases. The software factory can now recursively improve itself to be more cost-efficient over time thanks to these signals.
Among the usual sponsors of BazelCon, there was one name that stood out: Uber.
BazelCon 2026 Sponsors
Unlike the rest of the sponsors who are trying to market their product at the event, Uber isn’t there to sell you Uber One subscriptions. They are there to recruit talent.
It’s no secret that with big AI players paying big bucks for Bazel talent, the “traditional” internet tech companies like Uber, Airbnb, etc., have been bleeding talent to the labs. Across the tech market is a shift in talent percentiles: as the P99 talent gets sucked into “Big AI”, traditional “internet” companies such as Uber now have to shift into a lower gear to backfill their ranks.
Anthropic is hiring for Staff+ Dev Productivity at 625k USD base
And with non-competes being void in California, a large majority of engineers I talked to at BazelCon have tried interviewing at the labs. Some failed, some succeeded, but the numbers are turning heads. This causes overall market inflation among a scarce pool of talent, which is exciting if you are an engineer, and scary if you are a hiring manager.
Folks also discussed interview processes: what do you even do there? If you are still handing out coding interviews to an established open-source contributor in the Bazel ecosystem, I think you are already way, way behind. If the contributor is AI-native, they will laugh at you and just walk out of the room. There are way better opportunities for them in this bubbly market. The decision tree often comes down to a few points:
Remote-friendly. This is a core differentiator among the AI labs. If you are fixated on RTO, you will miss out on good talent. 2-4 flights a year for offsites should be OK, though.
Top-down commitment to expand Bazel (or a similar tool) usage. The main feedback I got from folks who decided not to join Anthropic was the lack of top-down sponsorship. Nobody wants to join an org to start fighting an uphill culture war with the rest of their co-workers. Let the builders build. Oh, and it does not need to be Bazel exactly because some folks enjoy the idea of writing a Bazel replacement themselves.
AI adoption. Interviewees enjoy asking whether the company is opinionated about which models/harnesses are available to them, and whether they are given a fixed token budget. Having a token budget is not a bad thing. It’s a bad thing if you make the budget fixed instead of variable.
What does this mean for companies that can no longer afford top-percentile talent?
You either need to be able to sell your culture, or you need to adopt AI aggressively to empower your existing workforce. Most folks I talked to seem to agree: you can be a senior engineer adopting AI to be more productive; you can also hire an AI-native fresh grad who can dig through the codebase from day 1; but you cannot afford to be anti-AI and reject all the productivity gains seen across the entire industry. It’s genuinely surprising to hear these cases still exist among Bazel users. I hope those folks give coding agents a try and change their minds.
Performance improvements in Bazel 10 would not have been possible without AI
Isn’t it kinda ironic that the folks who are selling you cloud coding agents are also aggressively hiring human software engineers?
Yes. But in the current state of things, these coding agents are just amplifiers of your human engineers’ attention. While this may change in the future, today, you still want to curate a team filled with humans who know how to devote their time and attention to the right set of problems. These are skilled individuals with “taste” and “opinion” honed throughout the years, pattern-matched from the best among tech companies. If you are in the Bazel community, or even the much smaller Version Control community, and fit the description, congratulations because you are a million-dollar hire.
Among BazelCon attendees were members from Meta’s Buck2 team. They gave a really good talk about Buck2’s Configuration Modifier, a replacement for Bazel’s Target Platform, which I thought was a very interesting divergence with different trade-offs. I got to pitch them my idea about Meta’s latest AI Agent: Muse. I don’t know Meta’s plans for Muse. But this is the competitive scenario I would be planning for.
Imagine personal AI agents becoming a successful product category. That means you, I, and everyone else at this conference will each have 10-20—an army of 24/7, always-online software engineers working for us. These coding agents will need more than just code. They will need language servers and code search for context, version control for collaboration and audit, build and test infrastructure, and deployment to a production environment.
Among these, we have seen ChatGPT Sites powered by Cloudflare as an early version of the “production environment” category. We have also seen some agent harnesses include version control in their product: Amp is powering theirs via Pierre’s Code Storage; Cursor is powering theirs via Origin. What we have not seen is a proper platform for builds and tests.
If you are Meta, would you let your customers run Git and Cargo on your data center compute? Heck no. You know that there are better options: Sapling VCS and Buck2 + RBE. These are solutions that work at scale. Eden VFS can clone and GC very efficiently. Buck2 and Bazel share cached action results across agents, while RBE can deduplicate matching actions across concurrent invocations. Cargo doesn’t natively offer that model—why pay for every agent to build the same thing? These are good, reliable solutions that Meta operates at scale; they know that they work. But the more important thing is this: Muse users don’t need to know. To the end users, these are merely implementation details that the agents will take care of. What they care about is the price per outcome, and with Sapling and Buck2 bundled into Muse, Meta could have a serious advantage on price in the Cloud Coding Agents product category.
Muse, Buck, and Sapling are friends
For the Sapling and Buck team, being able to attach their product to Meta Superintelligence Labs (MSL) will create a huge lane for promotions, bonuses, and, most importantly, headcount and tokens. “It’s a path to escape the permanent underclass,” I thought jokingly in my head.
This sounds plausible, but why do you spend so much time repeating this narrative to people?
I believe that today, Bazel (and Buck2) is a key that helps unlock productivity in top-tier AI labs. It drives down the CI compute bottleneck and enables more agents to collaborate at scale reliably.
But beyond that, I see a picture where Bazel is not just support tooling in the back of the office for these labs, but it should also be part of their core leading product in the next 6 months: the Cloud Coding Agent. If you assume that these agents will use the labs’ data centers to run builds and tests, and the compute consumption will put pressure on token/credit pricing, then by embedding Bazel and RBE as part of the multi-agent cloud factory, you will be able to offer the product at a much lower price than competitors. Otherwise, we are looking at millions of “cargo build” runs per minute a few months from now… good luck pricing that.
Given that Meta recently hired CJ Desai, MongoDB CEO, as their chief enterprise platform officer, one can only imagine what’s coming down the B2B SaaS pipeline. MongoDB is also using Bazel, btw. I wonder if other AI labs will get FOMO and do something about it. 😉
I am very proud of my team at BuildBuddy. At this year's BazelCon, we delivered wonderful technical talks. They are not sales pitches, just engineers talking about tech we have built over the last year, which we use ourselves and think others may also enjoy using.
Are we a sandbox company now?
Folks I talked to were constantly amazed by how small a team BuildBuddy is. We are less than 20 people at the time of writing. Yet, we are empowering some of the most critical companies in the world: frontier AI labs, space, semiconductors, robotics, car manufacturers, internet companies, top financial banks, and payment processors. We cannot name many of them, but IYKYK.
We shipped CDC in Bazel with a huge impact across the ecosystem
I really hope that we can talk more about what we have been doing in the upcoming year because there are so many cool underlying infrastructure problems we have solved. The downside of being in a team full of busy builders is that sometimes we forget to share what we have built. But in the meantime, point your agent at our GitHub repo and ask about it.
Discussion about this post
Ready for more?
Sunday Science: The Evolution of the Human Brain Set It Up for Failure
Portside
portside.org
2026-10-19 02:52:52
Sunday Science: The Evolution of the Human Brain Set It Up for Failure
Ira
Mon, 10/19/2026 - 02:52
...
Apes don’t develop Alzheimer’s—at least, not like we do. Although we share a hefty amount of our DNA with our closest primate relatives, humans are uniquely at risk of developing the disease that can erode our sense of who we are.
When I make the diagnosis in my neurology clinic, I tell patients and family members that in most cases, doctors can’t point to a single, definitive cause of the illness. Age, genetics, health, lifestyle factors, and environmental triggers all play a role. But a growing body of research offers another dimension: We can lose our sense of self precisely because our species evolved to have one. In recent years, scientists have been comparing the brains of humans with those of other, closely related species, and teasing out how the genetics, structure, and molecular mechanisms differ. What they’re finding is that the same characteristics that support our unparalleled cognitive abilities make us susceptible to Alzheimer’s disease.
Certainly, the biological hallmarks of Alzheimer’s look different inside the human brain than in the brains of other species. Melissa Edler, a comparative neurobiologist at Kent State University, and her team have identified distinct patterns in how humans and chimpanzees accumulate amyloid plaques and tau tangles, the toxic proteins that build up in brains with Alzheimer’s. She believes that looking at multiple species is going to be crucial to understanding how this disease develops. If nonhuman primates aren’t developing Alzheimer’s, “why aren’t they?” she asked, when we spoke about her work. “What’s different about their brains?”
One answer dates back to the early 2000s, when the Swedish geneticist Svante Pääbo (who went on to win the Nobel Prize for sequencing the Neanderthal genome) wondered what might account for the profound behavioral differences between humans and other apes—after all, we build civilizations while nonhuman primates cannot, without assistance, start a fire. Pääbo and his team of international researchers collected brain, blood, and liver tissue from humans, chimpanzees, orangutans, and macaques. But instead of comparing the genes themselves, they measured the genes’ activity—effectively, how hard each gene was working to make messenger RNA, which carries instructions from DNA on how to make proteins. Gene activity in the liver and blood, they found, was roughly equivalent across the species they tested. But activity in the human brain had ramped up.
Pääbo hadn’t set out to study Alzheimer’s specifically, but his findings hinted at a link between evolution and brain disease that others have pursued more directly. In a
study
published in 2020, for instance, Thomas Arendt, a neuroscientist at Leipzig University, and his team looked at autopsied brain samples from people with and without Alzheimer’s disease and found nearly 300 genes whose level of activity was different in the Alzheimer’s brains. When they looked at those particular genes more closely, they found that their genetic sequences had undergone a lot of change in a short amount of time—an indication that those genes played an important role in the human brain’s rapid and distinctive evolution. “In other words,” Arendt told me recently, “Alzheimer’s disease is based on changes in the genome that are typically human.”
Other researchers, too, have gathered evidence that supports the idea that evolution and Alzheimer’s are integrally related. A group at Duke University discovered that human evolution had influenced genes involved in the production of amyloid—the main protein that forms Alzheimer’s plaques. Scientists in China and the United Kingdom found that stretches of regulatory DNA that quickly morphed as the brain was evolving are associated with Alzheimer’s risk. Researchers from the MD Anderson Cancer Center, based in Houston, found uniquely human genes that get in the way of a protein called REST, which may guard against Alzheimer’s when working properly.
Other
studies have presented findings along similar lines. Collectively, these results only add to Arendt’s argument—that the genetic changes that made the human brain may be the same ones that left it imperiled.
The cognitive leap that set us apart also required the human brain to grow. The parietal lobes, which rise toward the crown of the head before sloping down the rear of the brain, are conspicuously larger in humans than in nonhuman primates, as Emiliano Bruner, a senior researcher in hominid paleoneurology at the Museo Nacional de Ciencias Naturales in Madrid, has demonstrated. A structure called the precuneus, tucked along the inner wall of those lobes, is larger too. The parietal lobes help the brain stitch sight, sound, and touch together into a cohesive model of the external world. They also play a central role in our advanced, abstract cognition, allowing for self-awareness, autobiographical memory, and our sense of being the same person across time.
Bruner had been mapping out these areas when he was contacted by Heidi Jacobs, now an associate professor of radiology at Massachusetts General Hospital and Harvard Medical School, who had been studying the same anatomy. For decades, Alzheimer’s research had focused almost exclusively on a different area of the brain—the temporal lobes, its de facto memory hubs. But Jacobs’s work suggested that the parietal lobes were also implicated in the disease’s earliest stages. Bruner and Jacobs began discussing whether the enlargement of these regions could have increased their vulnerability. Soon, they came up with a theory: The parts of the brain that had expanded most dramatically during human evolution were also among the first to be assailed by Alzheimer’s.
This was no coincidence, they argued. The precuneus consumes enormous amounts of energy and generates heat that has to be carefully dissipated to keep the brain functioning at its best. It also sits in a zone where the brain’s blood supply is thinnest, which makes it vulnerable to certain conditions, some of them age-related, that impact blood flow. Myelin, the fatty coating that is crucial for fast signaling between neurons, is also particularly fragile in this area. Essentially, Bruner and Jacobs reasoned, because of the rapid and imperfect reorganization that the parietal lobes underwent during human evolution, the region doing much of the brain’s hardest cognitive work has some of the most precarious infrastructure.
“It is like putting the engine of a Ferrari into a Fiat 500,” Bruner said. “That small car will go really fast, but it’s going to get hot. And braking will be an issue.”
What Bruner calls “braking,” the Yale neuroscientist Amy Arnsten calls “regulation”—specifically, calcium regulation, which supports learning and memory. The failure of that system, Arnsten argues, may be tied to how Alzheimer’s begins.
Most neurons fire because something in the outside world activates them: a flash of light, a sound. Neurons in our most recently evolved brain regions, which help us hold an idea in our minds, or conjure a detailed plan, keep firing even after the initial stimulus is gone. Although competing theories exist, Arnsten and others consider this persistent firing to be the cellular foundation of working memory. These “delay cells” depend on calcium to keep them active, but as we age and the cells’ system falters, calcium can rise to harmful levels, triggering a chain reaction that can cause tau proteins to clump. Over time, those clumps can contribute to the tangles of fibers that are seen in patients with Alzheimer’s.
Arnsten has shown that this apparatus, as well as the damage it causes when it breaks down, increases in lockstep with hominid evolution. Marmosets have the least of it. Macaques more. Chimpanzees, more still. Humans, by far, the most. “The closer to human,” Arnsten said, “the more the Alzheimer’s pathology.”
Our bodies are no strangers to evolutionary trade-offs.
Homo sapiens
’ vertical spine leaves us vulnerable to herniated discs; our pelvis, narrowed by bipedalism, makes childbirth difficult. We manage these compromises as best we can. But if an evolutionary give-and-take implicates our organ of thought and reason, accepting the compromise is harder.
The suggestion that neurological fragility is the price of a highly evolved mind is not novel, the historian Michael Hagner, who’s studied our understanding of the brain as the locus of personhood, told me. In the 19th century, some physicians and social theorists believed that the overwhelming demands of modern life were overtaxing the nervous system. That inclination, to interpret our cognitive vulnerabilities as the price of progress, has persisted even as more specific diagnoses have emerged to explain our brains’ instabilities.
Therapeutic options for Alzheimer’s remain both
scarce and disputed
, and understanding the disease’s ties to our brain’s evolution could open new avenues toward prevention and treatment. Amy Arnsten and her colleagues, for instance, are currently developing drugs that target calcium dysregulation, aiming to intervene before the system begins to break down. For now, the notion that human cognition and Alzheimer’s susceptibility share an evolutionary origin remains theoretical, and every time I deliver an Alzheimer’s diagnosis, I am acutely aware that I can offer little to change my patient’s fate. But if losing the sense of self is uniquely human, so is the ability to consider what having one allows us to gain.
Adina Wise
is a neurologist and writer in New York.
When the founders of The Atlantic gathered in Boston in the spring of 1857, they wanted to create a magazine that would be indispensable for the kind of reader who was deeply engaged with the most consequential issues of the day. The men and women who created this magazine had an overarching, prophetic vision—they were fierce opponents of slavery—but they were also moved to overcome what they saw as the limits of partisanship, believing that the free exchange of ideas across ideological lines was crucial to the great American experiment. Their goal was to publish the most urgent essays, the most vital literature; they wanted to pursue truth and disrupt consensus without regard for party or clique.
This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.
What can I do to resolve this?
You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.
The Supreme Law of the Land
Portside
portside.org
2026-10-19 02:19:55
The Supreme Law of the Land
Ira
Mon, 10/19/2026 - 02:19
...
Supremacy: How Rule by the Court Replaced Government by the People
by Nikolas Bowie and Daphna Renan
Buy this book
The Supreme Court’s dismantling of the last vestiges of the 1965 Voting Rights Act this spring in
Louisiana v. Callais
marked the end of an era—a retreat from the core civil rights commitment to draw electoral-district lines in a way that would ensure representation for racial minorities. More immediately, the decision in
Callais
set off a pell-mell process of new gerrymanders that carved up majority-minority districts into fragments designed to dilute Democratic votes. This fall, Democrats will likely lose three seats in the House of Representatives as a result of the decision. The number of Black representatives will likely drop too.
For many Democrats,
Callais
also reignited a long-smoldering fury with the court. Days after the decision, House minority leader Hakeem Jeffries of New York insisted that the time had come for “massive judicial reform”; the court, he insisted, was a “disgrace.” Representative Ro Khanna of California demanded term limits for the justices. Longtime Democratic strategist and professional intemperate James Carville charged that the “sons-of-bitches” on the court were “irredeemably corrupt” hacks and called for the addition of no fewer than four new justices once the Democrats retake control of Congress and the White House. Likely 2028 presidential contender Kamala Harris, who has recently echoed Carville’s proposal, signaled a new openness to such formerly off-limits steps. And in a widely read piece in
The New York Times
, prominent Harvard scholars Nikolas Bowie and Daphna Renan opined that the court was endangering the ability of the American people to govern themselves.
Now, in an energizing new book brimming with intelligence and passion, Bowie and Renan offer a full-dress critique of the court’s role in the nation’s history. Years in the making, and striking for its ambition and creativity,
Supremacy: How Rule by the Court Replaced Government by the People
represents a culmination of sorts of the years of liberal and left-wing discontent with the court. In it, Bowie and Renan argue that the Supreme Court has undermined American democracy throughout its 236-year existence—and never more so than in the present. Ranging from the court’s infamous endorsement of slavery in the
Dred Scott
case to the grim rollback of Reconstruction’s fleeting civil rights triumphs, they tell the story of the nation’s highest court working time and again to smother democratic possibilities and institutions. The authors recount the court’s dagger to the heart of the first peacetime federal income tax in 1895, its knife to the throat of the New Deal in the mid-1930s, and its slow carving-up of the Voting Rights Act in the decades leading up to
Callais
. They track the court’s undermining of civil rights laws, child-labor protections, labor regulations, domestic-violence laws, and firearms restrictions. They document its damage to campaign-finance laws, to consumer-protection laws, and to laws constraining overreach, crime, and corruption in the White House. In stark terms, Bowie and Renan describe a Supreme Court made up of latter-day monarchs who have disabled American self-government and rendered the United States “a nation that is a democracy mostly in name.”
In liberal-left legal circles, the critique of a “juristocracy” run rampant is growing in influence by leaps and bounds. Viewed favorably by liberals during the nearly 16 years that Earl Warren served as chief justice, the court has since become one of the principal sites of progressive disillusionment with American institutions. The stakes for our democracy could not be higher.
But is the diagnosis right?
Observers of the Supreme Court today have a name for the aggressive assertion of judicial power. They call it “judicial supremacy”: the claim that the court has the exclusive power to interpret the Constitution’s meaning and to require the elected branches of government to follow its interpretations.
In theory, it would be simple enough for progressives of all stripes to reject this idea of judicial supremacy outright—after all, plenty of democratic countries have managed without the judicial power to decide on the constitutionality of laws passed by the legislative branch, the United Kingdom and New Zealand chief among them. But American liberals face a special problem when it comes to doing so: In the second half of the 20th century, especially during the Warren years, judicial supremacy was associated not with conservative rulings but with liberal ones, such as the 1958 case of
Cooper v. Aaron
, in which Chief Justice Warren and a unanimous court ruled that Governor Orval Faubus and the state government of Arkansas were bound by the court’s decision in the epoch-making desegregation case
Brown v. Board of Education
. “The federal judiciary,” the court declared in
Cooper
, “is supreme in the exposition of the law of the Constitution.” The court’s judgment in
Brown
was thus “the supreme law of the land,” to be followed by state and federal officials alike.
Bowie and Renan’s creative solution is to distinguish between the judicial review of state laws on the one hand and of federal laws on the other, thereby offering a way for 21st-century liberals to celebrate the righteousness of the decisions in
Brown
,
Cooper
, and the now-overturned
Roe v. Wade
while still expressing frustration with the Supreme Court’s outsize power. The authors of
Supremacy
thread this needle by applauding the court for applying the federal Constitution to overturn state laws—for applying the Constitution “vertically,” as they put it—while remaining steadfast that the court should not apply the Constitution “horizontally”: that is, to block the federal laws passed by Congress.
Bowie and Renan note that judicial review in the horizontal sense has always been the more controversial form of review, all the way back to the earliest days of the republic. Founding-era critics worried that it would allow the courts to seize a dangerous amount of legislative power for themselves—such a practice, North Carolina’s Richard Spaight stated in 1787, “would be more despotic than the Roman Decemvirate, and equally as insufferable.” Such was the opposition to horizontal judicial review that in 1792, a few members of Congress threatened to impeach those justices who raised separation-of-powers objections to a law that gave the court’s members the task of reviewing pension claims by veterans of the War of Independence. A decade later, after a watershed election swept Thomas Jefferson into office, the new president’s partisans in Congress effectively abolished the Supreme Court’s 1802 session in order to block judicial review of their new laws. In a pair of decisions the next year, the court asserted its authority to decide on the constitutionality of congressional laws while meekly allowing such new Jeffersonian attacks on the judiciary to stand. In
Marbury v. Madison
, Chief Justice John Marshall gave voice to the court’s judicial-review authority, but did so in service of Jefferson’s efforts. In
Stuart v. Laird
, by contrast, the court declined to exercise that same authority when it would have produced a direct conflict with the new president.
Bowie and Renan adopt the conventional wisdom that after
Marbury
, judicial supremacy remained mostly dormant until 1857. In that year, in the infamous
Dred
Scott
case, Marshall’s successor, Chief Justice Roger Taney, ruled that Dred and Harriet Scott were slaves even though they had lived in a territory where slavery was illegal because, among other things, Congress had exceeded its power when its Missouri Compromise banned slavery in the territories north of the 36°30’parallel while admitting Missouri as a slave state. A ban on slavery, Taney held, would violate the Fifth Amendment rights of enslavers to be free from government deprivations of their property without due process of law. Reactions to the decision in the North were fierce, but mostly not because of Taney’s ruling that Black people could not be citizens. Chief Justice John Roberts’s opinion this past summer in the birthright-citizenship case suggested otherwise, but most white northerners were indifferent on that score. The main source of the anger over the
Dred Scott
case was that the decision opened the Western territories to slavery and thereby threatened to deprive white families of the economic opportunities of free soil and free labor. Such was the animus toward this dimension of the ruling that three years later, Abraham Lincoln would win the White House on a Republican Party platform that challenged the scope of the court’s power over the Constitution. The court, Lincoln announced, lacked the authority to resolve the public’s disagreements over the great question of slavery and freedom in the West.
From
Dred Scott
and Lincoln’s election, Bowie and Renan turn to Reconstruction, the pivotal decade in which the Republican-controlled Congress enacted laws to protect and defend freed people in the South, only to see the Supreme Court overturn or distort them. In the final months of the war, Congress established the Freedmen’s Bureau, which W.E.B. Du Bois later called “a full-fledged government of men,” as an administrative agency charged with distributing abandoned lands, setting up schools, and adjudicating disputes between whites and Blacks. It also passed the Enforcement Act of 1870 and the Ku Klux Klan Act of 1871, which among other things made it unlawful to violate the constitutional rights guaranteed in the 13th, 14th, and 15th amendments. And in early 1875, as Democrats were prepared to take over the House of Representatives for the first time since before the war, the lame-duck Republican majority in Congress passed a civil rights act prohibiting discrimination in public accommodations and authorizing the victims of such discrimination to sue in the federal courts.
Here was Congress building on the transformative moral triumphs of the Civil War, the Emancipation Proclamation, and the Reconstruction amendments and enacting substantive laws with an eye toward making the United States a more just and equal nation. But in each instance, the Supreme Court intervened horizontally to snuff out the promise of these laws. Before the war’s violence had fully come to an end, the court ruled (in the famous case of Lambdin Milligan) that the Freedmen’s Bureau courts were an unconstitutional violation of white defendants’ trial-by-jury rights. The court then truncated the reach of Reconstruction legislation in cases like in
United States v. Reese
and
United States v. Cruikshank
, ruling that the 14th and 15th amendments prohibited action by states, not discriminatory violence by private persons. In 1883, the court siphoned away the last energies of congressional Reconstruction by striking down the Civil Rights Act of 1875. The perversely titled
Civil Rights Cases
followed the line laid down in
Reese
and
Cruikshank
, holding that the discriminatory behavior of railroads, hotels, and theaters—like the murderous terror of the Klan—was not state action and thus not subject to constitutional constraints.
After betraying Congress’s Reconstruction statutes, the court began striking down a new generation of congressional attempts to rein in industrial capitalism. In 1895, the court’s decision in
United States v. E.C. Knight Company
blocked Congress from dismantling giant monopolies in manufacturing. Three months later, the court struck down the new progressive federal income tax, deeming it (in Justice Stephen Field’s words) an “assault upon capital.” In quick succession, the court struck down Congress’s 1906 protections of railroad workers injured on the job and its 1898 attempt to prohibit workers from being fired for joining a union. Federal laws to end child labor fell under the court’s scythe in 1918 and 1922, as did Congress’s efforts to check the executive branch in 1926.
During the presidency of Franklin Roosevelt, the court emerged as a reactionary obstacle to New Deal efforts to address the Great Depression, striking down federal laws like the National Industrial Recovery Act, the Agricultural Adjustment Act, and the Railroad Retirement Act. Although Roosevelt’s star-crossed court-packing plan was defeated in Congress, his appointment of eight new justices over the course of his presidency effectively cleared away the obstacles to New Deal programs by other means.
Bowie and Renan argue that this compositional shift in the court also augured a movement away from horizontal review to vertical review. In their telling, civil rights lawyers like Charles Hamilton Houston saw the enduring promise of the Klan Act and made it the central vehicle for the famous litigation campaign that led to
Brown v. Board of Education
. The NAACP’s campaign for Black freedom, in Bowie and Renan’s creative revisionist telling, relied not on an idea of the courts as a “judicial angel” offering escape from politics, but on a strategy of using Congress and the Klan Act to deliver on an existing democratic commitment to constitutional rights for all. In this account of the ruling, the key moment in
Brown v. Board of Education
came when the justices asked Thurgood Marshall whether they should wait for Congress to act before declaring segregation unconstitutional. Marshall’s reply, which drew on the strategy of his colleague Constance Baker Motley, is the climactic juncture of Bowie and Renan’s argument. “Congress,” Marshall told the justices, “has already acted” by passing the Klan Act. The court’s job in
Brown
, he continued, was to vindicate Congress’s democratic mandate.
Put this way,
Brown
stood for what Bowie and Renan call “democratic constitutionalism”—the egalitarian expression of a multiracial democratic majority breathing new life into the Constitution. Yet the Warren court, in their view, lost the plot. Its opinion in
Brown
made no mention of the Klan Act, and so the breakthrough of
Brown
has been attributed ever since to judicial action instead of to Congress. The effect, Bowie and Renan argue, has been politically catastrophic. Liberals adopted a self-defeating embrace of the same antidemocratic juristocracy that historically has dealt death blows to progressive policies. Name-checking the lions of liberal jurisprudence—Akhil Reed Amar, Ruth Marcus, Laurence Tribe, and Ronald Dworkin among them—Bowie and Renan accuse liberals of supporting the court’s authority even though its imperial ambitions have usurped the democratic potential of the people acting through Congress. The authors concede that the judicial review of federal laws has yielded progressive victories from time to time. The court blunted anti-communist legislation that violated free-speech principles. It overturned sex discrimination in both military benefits and Social Security pensions in the 1970s. It averted some of the worst excesses of the congressionally endorsed detention policy at Guantánamo Bay after 9/11, and it overturned the discriminatory Defense of Marriage Act in 2013. But such victories, they contend, are “dwarfed in their overall significance” by the “vastly larger set of cases” in which the court has harmed vulnerable minorities.
The Bowie and Renan argument will be tonic to the flagging spirits of liberals estranged from today’s court. But like previous critiques of judicial review over the past century and a half (many of which they feature in their book), its impact is likely to be fleeting. Parts of it may even be counterproductive, because in crucial respects, their forceful narrative rides roughshod over the political dynamics of judicial review in America.
As a starting point, the judicial review of federal statutes is more deeply embedded in American history than the thesis of
Supremacy
contemplates. The pension cases of the 1790s may have occasioned loose talk of impeachment by a handful of politicians, but the controversy also showed that judicial review had widespread support from the start. Between 1792 and 1794, all six of the Supreme Court’s justices indicated that they would not give effect to a law that unconstitutionally turned them into claims administrators. The first US attorney general, Edmund Randolph, agreed that the justices had the authority not to give effect to unconstitutional laws. In short order, Congress amended the law to remove the offending provisions. And in the five decades between
Marbury
and
Dred Scott
, the Supreme Court set aside at least 10 laws passed by Congress without much objection either from Congress or We the People.
Some of these early decisions turn the Bowie and Renan argument on its head. Consider the 1842 decision in
Prigg v. Pennsylvania
, which arose out of Pennsylvania’s effort to prosecute a Maryland slave catcher, Edward Prigg, for kidnapping Margaret Morgan and her children and trafficking them back to the slave states. The court overturned Prigg’s kidnapping conviction on the ground that federal law on fugitive slaves preempted the personal-liberty laws of the free states. The case’s result was a travesty—an early sign that neither the Supreme Court nor the Constitution would be able to contain the growing schism over slavery in American politics. But
Prigg
is also at odds with the Bowie and Renan thesis.
Supremacy
treats the opinion in
Prigg
as though the court made fugitive-slave renditions a national duty. Yet as Justice Joseph Story’s opinion in the case noted, Congress had beaten the court to the punch by nearly a half-century with the Fugitive Slave Act of 1793, which breathed life into the Constitution’s fugitive-slave clause and made kidnapping a national business. In its time, the antislavery critique of
Prigg
held that the court should have rejected Congress’s authority to pass laws about fugitive slaves, a power nowhere specifically enumerated in the Constitution. The egalitarian move was therefore for the court to act horizontally and overturn the law. Instead, the Supreme Court in
Prigg
did as Bowie and Renan urge. It deferred to an act of Congress, only here that meant acceding to evil. Even worse for their argument, Justice Story did suggest that the Fugitive Slave Act was invalid in one respect. The law conscripted free-state officials into participating in the federal slave-catching system, but Story deemed this beyond Congress’s constitutional power. Horizontal judicial review in
Prigg
effectively incapacitated Congress’s slave-catching apparatus—at least until Congress established federal commissioners to do its dirty work in a new Fugitive Slave Act in 1850.
On a more systemic level, the paradox of horizontal judicial review in the run-up to the Civil War is that it was nurtured and encouraged by elected officials as much as it was advanced by the Supreme Court. No one wanted
Dred Scott
to take the slavery question off the table more than President-elect James Buchanan. Indeed, both Democrats and Whigs in Congress were desperate for judicial solutions that would allow the parties to punt on the slavery questions that threatened to tear them asunder. Elected officials wanted most of all for the Supreme Court to solve the problem of slavery in the Western territories—and leading antislavery politicians wanted this nearly as much as proslavery ones. Bowie and Renan dismiss Salmon Chase, the US senator from Ohio who was widely expected to become the first antislavery president, as a judicial supremacist. They aren’t entirely wrong. Chase insisted that the Constitution did not permit slavery in the Western territories and demanded that the courts say so. But Chase was among the most successful and influential members of Congress in his day. If democracy and Congress are the relevant measures, the popular Chase was far more significant than the radical abolitionists who loom large in the Bowie and Renan story but who seldom tried to win elections and rarely won when they did.
Racial egalitarians turned to the courts both before and after the Civil War because Congress was a natural agent of majoritarian-rule white supremacy. It was Congress, after all, that passed the law in 1790 limiting naturalized citizenship to white persons, enacted the Fugitive Slave Act of 1793, and updated that act in 1850. It was Congress, not the courts, that authorized Indian removal in 1830, that enacted Chinese-exclusion legislation beginning in 1882, and that passed the Dawes Act dismantling Native tribes in 1887. Congress failed to enact simple voter-protection legislation in the 1890s and let anti-lynching legislation languish even as the annual toll of lynchings reached the triple digits. Congress’s immigration laws in 1921 and 1924 famously codified a virulent conception of Anglo-Saxon supremacy into law. Southern Democrats, as Ira Katznelson has shown in
When Affirmative Action Was White
, systematically turned the New Deal’s legislative program against the interests of Black people.
Meanwhile, as Dylan Penningroth details in
Before the Movement
, many Black families in the late 19th and early 20th centuries expressed a “wary faith” in the courts, at least relative to electoral politics in Congress. Kate Masur’s
Until Justice Be Done
demonstrates that advocates for Black freedom pressed their cause via constitutional litigation in the courts long before the Civil War. And even in the dismal “separate but equal” era of
Plessy v. Ferguson
, the court prohibited race discrimination in jury selection and sided with Chinese laundry owners victimized by San Francisco’s discriminatory administration of its health and safety codes. In 1917, the Supreme Court barred racial zoning by state and local governments. In 1923, scarcely two months after Congress tabled a crucial anti-lynching bill, the court reversed the lawless criminal convictions of Black men sentenced to death in Arkansas. In 1927, the court decided the first in a series of so-called “white primary” cases, ruling that various Southern schemes to prevent Black voting in the Democratic Party’s primary elections were unconstitutional. The court twice sided with the young Black men convicted of rape in lynch-mob proceedings in Scottsboro, Alabama, first in 1932 and then again in 1935. And in 1938, it decided the first of its school-segregation cases on the way to
Brown v. Board of Education
, ruling that the University of Missouri’s law school had to admit a Black applicant named Lloyd Gaines. These were vertical-review cases, to be sure. They overturned state laws. But they were victories that the various Congresses of the long Jim Crow era could not deliver—and that even the Reconstruction Congresses might not have been able to muster. The Supreme Court could and did.
Other questions emerge when one looks more closely into Congress’s delegation of power to the federal courts. Ever since the Judiciary Act of 1789, as the constitutional lawyer Charles Black once observed, Congress has repeatedly authorized and reauthorized the Supreme Court (and, beginning in 1875, the federal courts more generally) to engage in precisely the kind of horizontal review of its own laws that Bowie and Renan decry as democratically illegitimate. Such long-standing grants of power to the courts look an awful lot like the congressional authorization that Bowie and Renan celebrate in the Klan Act. Congress, in other words, has literally ordered the Supreme Court to review its own enactments. Congress could withdraw that authorization tomorrow, though whether the court would acquiesce in such jurisdiction-stripping is a hotly contested question. But until Congress takes such steps, it’s hard to see the court’s compliance as illegitimate.
If federal courts lacked the authority to review federal legislation, the results could be bizarre. The supremacy clause of the US Constitution requires state courts to enforce the federal constitution. The Wisconsin Supreme Court did just that when it ruled the Fugitive Slave Act unconstitutional in 1854. Could it possibly be that federal courts don’t have the authority to do what their state counterparts must? Could the Affordable Care Act’s Medicaid expansion be constitutional in blue states, where liberal courts uphold it, but unconstitutional in red states, where conservative courts do not? Could federal firearm regulations be unconstitutional in red states but permissible in blue ones? Even if Bowie and Renan might contemplate such a world, Congress obviously does not and has not since 1789.
The difficulty with Bowie and Renan’s argument runs deeper than the technical law of judicial review. There’s a reason that civil rights lawyers in the mid-20th century did not object when their courtroom victories were premised on their clients’ constitutional rights instead of on Congress’s dictates. They were thrilled, and not because they were making a tragic strategic blunder. Political questions become judicial ones in the United States because the interests of advocates and institutions alike make appeals to the courts a powerful and alluring move. The Supreme Court is a strategic resource in American politics: It allows advocates to entrench their claims, at least temporarily, against the risk of shifting political winds. Congress uses the court for its own ends as well. Just as it did in the run-up to the Civil War, it delegates constitutional questions to the court all the time—the better to resolve difficult negotiations on the floor, or to duck hard questions that Congress has no desire or capacity to answer. Political scientists call the phenomenon “legislative deferral.” Think of it as passing the buck.
None of this is to gainsay, even for a moment, that some of the cases Bowie and Renan decry are awfully hard to describe as ceded by Congress—or to deny that
Supremacy
is a book of creativity and passion, an impressive bid to make sense of our age of dysfunctional judicial review. Cases like
INS v. Chadha
in 1983 and
Trump v. Slaughter
this past summer, in which the court struck down Congress’s efforts to check executive-branch overreach, have swollen the power of the executive branch. The court’s decisions in
Citizens United
and similar cases have given money breathtaking power over our elections, despite Congress’s efforts to control it. The
Trump v. United States
presidential-immunity decision in 2024, which is one of the worst decisions in the court’s history, has freed irresponsible presidents from accountability. Decisions like these have made American democracy immeasurably worse and have greased our slide into the current crisis. But the problem with these decisions is not the underlying authority of the court. The problem is with their merits as interpretations of the US Constitution.
What makes today’s court so anomalous is not its claim to authority: That is age-old, routine, and constitutionally grounded. The distinctiveness of our current dilemma is that in many of the court’s most politically charged cases, such as
Louisiana v. Callais
, the votes of six justices routinely deal losses to a political party that represents about half the country.
Since Lyndon Johnson’s failed nomination of Abe Fortas to be chief justice in 1968, Republican presidents have named 15 justices to the bench, while Democrats have named five. It would be one thing if that disparity had arisen during an age of one-party domination. Republicans dominated the White House and the court during and after Reconstruction; Democrats controlled politics and the court after the New Deal. But our era’s imbalance has come as a result of historical accident and partisan tactics during six decades of closely divided government, with increasingly razor-thin partisan margins in Congress and alternating control of the presidency. The legal scholars Dan Epps and Ganesh Sitaraman note that a majority of the current justices were nominated by presidents who lost the popular vote. Four were confirmed by senators representing a minority of the US population. Democrats have won five of the last 10 presidential elections, yet according to one prominent study, the GOP’s current supermajority of appointees is likely to retain control over the court until 2065.
The resulting imbalance makes it entirely understandable that left-liberal critics of the court have become increasingly furious. Even so, these critics offer their own fateful misunderstanding of the court’s power, one that is likely to have dismal consequences for progressive politics. The court’s authority is widely popular in the United States and has been for a long time. A best-selling book by the centrist conservative Sarah Isgur proposes plausibly that the court is the “last branch standing” in a political landscape of executive aggrandizement and congressional abdication. Even as the court’s approval ratings have plummeted in recent years, some 87 percent of Americans still support the principle of judicial review of laws passed by Congress, a figure that is more or less constant across the political parties.
Bowie and Renan’s book is an attempt to change this math. They believe that history shows judicial review to be an obstacle to the real multiracial democracy that America so badly needs, and so they mean to build a popular groundswell against it. In the past, however, the great challenges to the court’s authority—Jefferson’s, Lincoln’s, and Roosevelt’s principal among them—have followed popular mobilizations and landslide elections, not preceded them. As political strategy goes, mobilizing against judicial review is a little like being baited into an unforced error instead of setting an agenda for success.
What Bowie and Renan are really on to here is that a Supreme Court in such unusually sharp conflict with one of the two major parties is a court that we have never seen except in moments of great political upheaval. The paralyzing difference now is that we still await the transformative political realignment or movement that could sweep the field and reset the relationship between the Supreme Court and the elected branches. Our political crisis would be much simpler if Bowie and Renan were right and the court had disabled our democratic politics. The harder truth is that our democratic politics have built and enabled the court.
John Fabian Witt
teaches at Yale Law School. His latest book is
The Radical Fund
, about the foundation that financed
Brown v. Board of Education
.
Founded by abolitionists in 1865, The Nation has long believed that independent journalism has the capacity to bring about a more democratic and equitable world. Our writers shift paradigms and open minds. Our deep investigative reporting launches congressional hearings, forces policy change, and shapes news cycles. Instigating progress: It’s not only our legacy, it’s our continued commitment to future generations of torchbearers.
This book is an introduction to programming language theory using the proof assistant Agda.
Comments on all matters—organisation, material to add, material to remove, parts that require better explanation, good exercises, errors, and typos—are welcome. The book repository is on
GitHub
. Pull requests are encouraged. There is a private repository of answers to selected questions on github. Please contact one of the authors if you would like to access it.
An
agent skill
is a small file that teaches your AI how to do one thing really well — write a slide deck, plan a launch, format a spreadsheet, draft a PRD. Once added, the AI uses it automatically when the task fits.
This site collects skills made by Anthropic, Stripe, Figma, Notion, Hugging Face, and dozens of other teams. We rewrote each one in plain English and only kept the ones a non-developer would actually use. Click any skill to see what it does, then copy the source URL into your AI tool.
tmux runs your AI coding agents in named, detachable sessions that survive a closed terminal or a dropped SSH connection. You get one window holding many agents,
send-keys
to type into any of them from a script, and
capture-pane
to read one back. That combination is why people use it.
Before you build any of it by hand, check the built-in path: recent versions of Claude Code can create the worktree and the tmux session for you with
claude --worktree --tmux
. This guide covers that first, then everything it doesn’t reach, then the point where tmux itself stops.
Why tmux and agents go together
A coding agent is a long-running process that wants to keep talking to a terminal. Three properties of tmux match that shape:
It survives disconnection.
The tmux server owns the pty, not your terminal window. Close the window, lose your SSH link, put the laptop to sleep: the agent keeps working and is still there when you reattach.
It holds many sessions in one window.
Four agents become four named sessions you switch between with a keystroke, instead of four windows you hunt for in the app switcher.
It’s scriptable from outside.
Any shell, anywhere, can type into a running agent or read its screen. No IPC to build, no API to wire up. This is the property people build on, and it’s why tmux keeps showing up in agent-orchestration scripts.
The built-in flag, before you build anything
Claude Code ships with this wired up for the single-agent-on-a-branch case. Two flags, from
claude --help
on a recent version:
-w, --worktree [name] Create a new git worktree for this session (optionally specify a name) --tmux Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.
So the whole “isolate this task, give it its own session” move is one command:
claude --worktree --tmux# or name the worktreeclaude --worktree auth-refactor --tmux
Two details matter before you rely on it.
--tmux
errors without
--worktree
, so it’s a worktree feature that happens to make a session, not a general session flag. And on iTerm2 it uses native panes instead of tmux, which is nicer to look at and means the tmux commands in the rest of this page have nothing to attach to. Pass
--tmux=classic
when you want real tmux underneath, which you do if you plan to script against the session.
For a single agent on a single branch, that’s the answer. Use it and skip ahead.
What it doesn’t do: run several agents in one session, lay out panes so you can watch them, let you type into a running agent from a script, tell you which agent is waiting on you, or set any of this up on a remote box over SSH. Those are the rest of this guide, and each one is where people end up writing tmux by hand.
The organizing rule that keeps this usable: one tmux session per repo, named after the repo. Not per task, not per agent. Tasks come and go; the project is the stable thing.
# start a detached session in a project directorytmux new-session -d -s api -c ~/code/api# attach to it (creates it if it doesn't exist)tmux new-session -A -s api -c ~/code/api
-A
is attach-or-create. It makes a single command safe to run repeatedly, which is what you want in a shell function:
# ~/.zshrcagent() { local dir="${1:-$PWD}" local name="$(basename "$dir" | tr . -)" tmux new-session -A -s "$name" -c "$dir"}
Session names can’t contain
.
or
:
(tmux uses them as target separators), hence the
tr
.
Then
tmux ls
becomes a real inventory:
$ tmux lsapi: 3 windows (created Fri Jul 31 09:12:04 2026)web: 2 windows (created Fri Jul 31 09:40:11 2026)infra: 1 windows (created Fri Jul 31 11:02:55 2026)
Inside a session, give each agent its own window, named for the task:
tmux new-window -t api -n auth -c ~/code/apitmux new-window -t api -n tests -c ~/code/api
Windows are better than panes for agents you’re not actively watching, because a window costs no screen space. Panes are for the two or three you want side by side right now:
# split the current window and tile whatever is in ittmux split-window -h -c '#{pane_current_path}'tmux split-window -v -c '#{pane_current_path}'tmux select-layout tiled
#{pane_current_path}
is easy to leave off. Without it a new pane opens in the directory the session started in, not the directory you’re actually in, and the agent you launch there is pointed at the wrong repo.
Two layouts by name:
tiled
for an even grid of agents, and
main-vertical
for one big pane (the agent you’re driving) with the rest stacked beside it.
Percentage values for
main-pane-width
need tmux 3.2 or newer. On older builds use an absolute column count (
main-pane-width 120
). Check with
tmux -V
.
A
.tmux.conf
worth having
These are the lines that matter for agent work specifically. They’re not a full config, they’re the delta from defaults that a fleet of agents makes you want.
# agents produce a lot of output, and you will want to scroll back through itset -g history-limit 100000# 24-bit colour, so agent TUIs render the way they were designed toset -g default-terminal "tmux-256color"set -ga terminal-overrides ",*256col*:Tc"# scroll and click between panes with the mouseset -g mouse on# don't let a running process rename the window out from under youset -g allow-rename offset-window-option -g automatic-rename off# 1-indexed windows match the number keys on your keyboardset -g base-index 1set-window-option -g pane-base-index 1set -g renumber-windows on# flag windows whose agent produced output while you were elsewhereset-window-option -g monitor-activity onset -g visual-activity off# status line refreshes often enough to be a monitorset -g status-interval 5# no delay when an agent's TUI reads an escape sequenceset -sg escape-time 10# jump panes without the prefix keybind -n M-h select-pane -Lbind -n M-j select-pane -Dbind -n M-k select-pane -Ubind -n M-l select-pane -R# reload without restarting the serverbind r source-file ~/.tmux.conf \; display-message "config reloaded"
Agent TUIs like to set the terminal title, so without
allow-rename off
your carefully named
auth
window becomes whatever the agent felt like calling itself.
escape-time 10
fixes the “my arrow keys are laggy inside the agent” complaint. The default delay exists to disambiguate a real Escape key from an escape sequence, and it makes interactive TUIs feel mushy.
Driving an agent with send-keys
send-keys
types into a pane as if you were at the keyboard. This is how you script an agent from cron, from a git hook, or from another agent.
# target syntax: session:window.panetmux send-keys -t api:auth "run the test suite and fix what fails" Enter
Three things go wrong here, in order of how often:
Bare arguments get interpreted as key names.
Enter
,
C-c
,
Escape
, and
Space
are keys, not text. If your prompt contains one of those words as a standalone argument it gets sent as a keypress. Use
-l
to send a literal string:
tmux send-keys -t api:auth -l "press Enter to continue was the old flow"tmux send-keys -t api:auth Enter
-l
disables key-name lookup entirely, so the newline has to be a second call.
Semicolons end the tmux command.
A trailing
;
in your text is read as a command separator. Escape it as
\;
.
Agent TUIs need a beat between the text and the newline.
Many agent input boxes debounce or re-render on paste, and an Enter arriving in the same frame as the text gets swallowed. The reliable pattern:
Interrupting a runaway agent is the same mechanism:
tmux send-keys -t api:auth C-c
Reading an agent back with capture-pane
capture-pane
dumps a pane’s contents to stdout. It’s the read half of the pair.
# the visible screentmux capture-pane -p -t api:auth# the last 200 lines, with wrapped lines joined back togethertmux capture-pane -p -J -S -200 -t api:auth# the entire scrollbacktmux capture-pane -p -J -S - -t api:auth# keep the colour escape sequencestmux capture-pane -p -e -t api:auth
-J
matters more than it looks. Without it, a line that wrapped at your terminal width comes back as two lines, and every grep you write against the output is wrong at the seams.
For a continuous log rather than a snapshot,
pipe-pane
streams everything a pane produces to a command:
-o
toggles, so running it twice turns it off. The output is raw, escape sequences and all, so pipe it through something like
sed -E 's/\x1b\[[0-9;]*[a-zA-Z]//g'
if you want it readable later.
The status-line monitor
Every person who runs several agents in tmux eventually builds this: a status line that tells you which agents are working and which are waiting.
The mechanism is
#()
in the status line, which runs a shell command and interpolates its output, refreshed every
status-interval
seconds.
And the script, which capture-scrapes each pane for a sign of life:
#!/usr/bin/env bash# ~/bin/tmux-agent-statusout=""while read -r target; do screen="$(tmux capture-pane -p -J -S -8 -t "$target" 2>/dev/null)" name="${target%%:*}" case "$screen" in *"Do you want"*|*"❯ 1."*) out+="⏸ $name " ;; # parked on a prompt *"esc to interrupt"*) out+="● $name " ;; # working *) out+="○ $name " ;; # idle esacdone < <(tmux list-panes -a -F '#{session_name}:#{window_index}.#{pane_index}')printf '%s' "$out"
It works, and it’s worth building. Be clear-eyed about what it’s doing: string matching against a TUI’s rendered frame, on a five-second poll, for every pane you have open. The match strings are whatever your agent version happens to print this week.
The lighter-weight version uses tmux’s own activity tracking instead of scraping.
monitor-silence
fires an alert when a pane produces no output for N seconds, which is the closest native signal to “this agent stopped”:
set-window-option -g monitor-silence 30set -g visual-silence on
Silence is a proxy for done, not a report of it. An agent thinking hard about a large file is silent too.
Detach, reattach, and what survives what
tmux detach-client # or the prefix, then dtmux attach -t apitmux switch-client -t web # from inside another sessiontmux kill-session -t api
What survives:
Event
Agents keep running?
Close the terminal window
yes
Detach the client
yes
SSH connection drops
yes
tmux kill-session
no
tmux kill-server
no
Reboot
no
macOS “Reopen windows” after restart
no
The tmux server is just a process owned by your user. Nothing about tmux makes it survive a reboot, and a session’s scrollback is lost when the server stops. If the transcript matters,
pipe-pane
it to a file or use a tool that persists history on its own.
One detail people trip on: a detached session’s panes are sized to the last client that was attached, or to 80x24 if there never was one. An agent TUI rendering into an 80-column pane while you’re away will look wrong when you reattach at 200 columns, until it redraws.
set-window-option -g aggressive-resize on
helps when several clients are attached at different sizes.
tmux over SSH
This is where tmux is genuinely hard to replace. Running agents on a remote box, over a link you don’t trust:
# attach or create, in one command, with a tty allocatedssh devbox -t tmux new-session -A -s agents
Your connection drops mid-task, you run the same command again, and you’re back in the same session with the agent still going. Pair it with
mosh
if your link is bad enough that SSH itself keeps dying.
The nested-tmux problem: if you run tmux locally and also on the remote box, both grab the same prefix. The two fixes are a different prefix on the remote (
set -g prefix C-a
), or pressing the prefix twice, which
bind C-b send-prefix
gives you.
For running agents on a machine that isn’t the one in front of you, see
remote development
.
Where tmux stops
tmux is good software. It solves multiplexing and persistence about as well as those can be solved, and it has been doing it since 2007. What it doesn’t do is anything specific to agents, because agents didn’t exist when its model was designed.
No visibility into which agent is parked.
An agent waiting on an approval prompt looks exactly like an agent thinking, which looks exactly like an agent that finished twenty minutes ago. All three are “a pane with some text in it”. The status-line hack above exists to paper over this, and it papers by scraping.
No notification when one finishes.
monitor-silence
is the nearest thing, and it fires on any quiet pane for any reason. There is no event for “the agent is done” because tmux has no idea what an agent is.
Screen scraping is brittle by construction.
capture-pane
gives you the rendered frame: spinners, box drawing, truncated columns, ANSI. Not what the agent said, not which tool it called, not whether that call succeeded. Every parser you write against it breaks when the agent ships a UI change.
No shared state across sessions.
Two agents in two tmux sessions have no way to see each other. If you want one to read another’s transcript or hand off work, you build that yourself, out of files and locks and polling.
Scrollback for several streaming agents is expensive.
history-limit 100000
across a dozen panes of agent output is real memory, held per pane for as long as the server lives, and gone the moment it does. See
terminal emulators for AI agents
for why the rendering side of this gets costly too.
Nothing survives a reboot.
Every session, every transcript, gone.
None of these are flaws. They are the edge of a tool built to multiplex shells for one person at a keyboard.
Where crystl picks up
crystl
is a macOS terminal built for the workload tmux was not shaped for: many agents at once, most of them off-screen, each one occasionally needing you.
The differences map almost one-to-one onto the list above.
Approvals surface instead of getting buried.
When any agent pauses for permission, crystl floats it as a card, colour-coded by project, and you answer without switching sessions. No scraping, no polling. See
floating cards
.
Agent state is a first-class signal.
The
agent activity panel
shows every session’s state at once: working, waiting on you, idle, done. That’s the thing the status-line script was approximating.
Output is structured, not scraped.
crystl captures each turn, tool call, and result as typed records, so
history
is searchable across every session and agents can read each other’s transcripts without parsing ANSI.
Sessions are organized by project, and they persist.
Projects are gems, sessions inside them are shards, and history survives closing a window or restarting the Mac. More in
multitasking
.
Parallel work on one repo is isolated.
Isolated shards are backed by real git worktrees, so two agents on the same repo don’t collide. See
parallel sessions
.
The recommendation: keep tmux. It’s still the right answer for remote boxes, for long-running processes on servers, and for anything where the SSH link is the fragile part. Use it for that. When the thing you’re managing is six agents that each need a decision from you at an unpredictable moment, the problem stopped being multiplexing.
The one change that worked: I deleted Instagram – and embraced the joys of a truly private life
Guardian
www.theguardian.com
2026-10-19 01:55:20
I’d become obsessed with appealing to my invisible audience. But since I ditched the app a year ago, my quieter moments have taken on brilliant new meaning I first downloaded Instagram when I was 17 and became hooked on it the way most people fall in love: slowly, and then all at once. For a long ti...
I
first downloaded
Instagram
when I was 17 and became hooked on it the way most people fall in love: slowly, and then all at once. For a long time, I never considered myself a social media addict. I self-righteously refused to download TikTok, declared Snapchat to be for “children”, and posted less regularly on Instagram than half of the people I followed.
As I went through my university years, however, certain changes crept up on me. I began to swap reading – or essay-writing – for hours spent curating new posts. On my way home from lectures (or later, from my work as a journalist), I would spend ages trying to take the artsiest, most perfect picture of that evening’s sunset for my story – as if the people who followed me were eagerly awaiting yet another photo of one of the Earth’s rotations. What usually followed was a night of reloading my feed to see how many people had reacted to my post – or worse, hadn’t reacted at all.
McNamara pre-epiphany at Sigiriya, Sri Lanka.
Photograph: Georgina McNamara
It wasn’t until a trip to Sri Lanka last year that I realised how far my obsession had gone. My partner and I spent two weeks travelling through Negombo and Kandy, having dinner in front of the Indian Ocean and visiting ancient heritage sites that I will probably never see again.
This would have been memorable even without a third guest: my inner Instagram monologue. It commented on everything I saw in those two weeks, debating the merits of each photo I took and the possible captions (or music, or filters) that could accompany it. On one of our last days, we hiked up Sigiriya, an incredible rock fortress that has been inhabited since prehistoric times and is one of the most remarkable places I have ever seen.
My first thought upon reaching the top? This
has
to go on my story. Already, I was imagining how it would look on Instagram. I dutifully made several posts upon my return to London, which were accompanied by hours of anxious scrolling and reloading, wondering why more people weren’t liking or commenting on my feed. Did they think I was annoying? Boring? Ugly? Had I been ungenerous with my own likes and comments, causing my followers (a grand total of 400) to band together to punish me? Should I delete the post? Redo it?
Within two days, I couldn’t take my own thoughts any more. I decided to delete Instagram from my phone for a month, reset my habits, and then return with a hopefully healthier mindset.
Yet in its absence, certain realisations became unavoidable. I came to see how much of my photo-taking was driven by wanting to appeal to an invisible audience, most of whom I hadn’t spoken to in years. In that first month, I started to take photos for myself and my own memories instead. It made me feel like my experiences could belong to me again.
One month turned into three, then six – next month, it will have been a year since I took that first step. In my Instagram days, I expended a great deal of energy comparing the most normal parts of my life to the seemingly wonderful lives of others. Without the app, I was able to direct this energy into other parts of my life. That’s not to say I became productive every minute of every day. I didn’t. But the background noise decreased substantially. I read more, finished writing my first novel and started another.
It has been liberating to live my life privately again. You may laugh, because I’m hardly a public figure, but I discovered how joyful it can be to reconnect with your anonymity and do activities knowing that it’s no one’s business whether you liked them or not.
Now, moments matter because I’m enjoying them, or sharing them with someone I care about – not because they have been liked and validated by a hundred other people. I remain fully present for each of them, without disappearing halfway through into an Instagram rabbit hole. My life feels smaller in some ways, but also much more like my own. Whether the Insta-verse has noticed my absence, I couldn’t say. Do I care? Thankfully, not any more.
Composite objects and C++26 the std::polymorphic type
In a
previous article
, I discussed the C++
std::indirect
type and how it helps implementing the PImpl idiom. However, the
std::indirect
type was inducted in the standard alongside another type called
std::polymorphic
. This helps implementing composite classes, where composite means a class composed of member objects in an has-a relation, where the composite own the components which are part of its values. Examples include strategy objects, AST/expression-tree nodes, shapes-style hierarchies, plugin-configured behavior – and you want the owning class to remain a regular, copyable value. In this article, we’ll look at how
std::polymorphic
can be used for this purpose.
We have various types of events from various sensors in a smart house and we want to store them in an event log. How do we do that? There are various options:
Event event
– slices because a
TemperatureReadingEvent
assigned into it loses its temperature specific part. Doesn’t even compile here since
Event
is abstract.
unique_ptr<Event>
– preserves the dynamic type, but now your class is move-only (or you hand-write copying),
const
doesn’t propagate, and null lurks.
variant<Event, TemperatureReadingEvent>
– exhibits value semantics, but maintaince a closed set: adding a
CarbonMonoxideDetectedEvent
means touching the variant and every visitor.
unique_ptr<Event>
and a virtual
clone()
function – the traditional “fix” for copying, which pushes boilerplate into every class in the hierarchy.
Let’s try to implement the last option in the list. We start with the
Event
class:
The event log that is composed of sensor reading events may look as defined below:
class EventLog {
std::vector<std::unique_ptr<Event>> events_;
public:
EventLog() = default;
// The Rule of Five because unique_ptr members delete the copy operations
EventLog(const EventLog& other) {
events_.reserve(other.events_.size());
for (const auto& e : other.events_)
events_.push_back(e->clone());
}
EventLog& operator=(const EventLog& other) {
if (this != &other) {
std::vector<std::unique_ptr<Event>> tmp; // copy-then-commit
tmp.reserve(other.events_.size()); // for exception safety
for (const auto& e : other.events_)
tmp.push_back(e->clone());
events_ = std::move(tmp);
}
return *this;
}
EventLog(EventLog&&) noexcept = default;
EventLog& operator=(EventLog&&) noexcept = default;
~EventLog() = default;
template <typename E, typename... Args>
void record(Args&&... args) {
events_.push_back(std::make_unique<E>(std::forward<Args>(args)...));
}
HomeStatus replay() const {
HomeStatus home;
for (const auto& e : events_)
e->apply(home);
return home;
}
void print() const {
for (const auto& e : events_)
std::println(" {}", e->describe());
}
std::size_t size() const { return events_.size(); }
};
Putting it all together, we can use these classes as shown in the following snippet:
int main()
{
EventLog live;
live.record<TemperatureReadingEvent>("kitchen", 21.5);
live.record<TemperatureReadingEvent>("kitchen", 48.0);
live.record<CarbonMonoxideDetectedEvent>("garage", 120);
std::println("Live log has {} events", live.size());
live.print();
HomeStatus now = live.replay();
std::println("Current home status: lastTemp={}, smoke={}, co={}, alerts={}, evacuate={}",
now.lastTemperature,
now.smokeAlarm,
now.coAlarm,
now.alertCount,
now.evacuationNeeded());
}
There are a series of problems with this implementation:
The owner loses copyability.
unique_ptr
is move-only, so the composite’s copy operations are deleted. Getting them back means hand-writing a copy constructor and copy assignment that clone every component, which means the Rule of Zero is defeated.
The clone() function affects the whole hierarchy, as every derived class must implement it. But on the other hand, the compiler can’t enforce it, which means a forgotten override doesn’t fail to build; it silently produces sliced copies.
Infrastructure leaks into the interface. The function
clone()
says nothing about the type. It is a copying workaround sitting in the public API next to the methods that actually define the type.
const
doesn’t propagate. Through a
const unique_ptr
, the pointee is still mutable (because
const
protects the pointer, not the component).
null is representable. Nothing prevents a null pointer from entering the container or member, so every dereference carries an implicit precondition the type system doesn’t express.
Using the C++26 type
std::polymorphic
, we no longer need to use a cloning mechanism to allow components to behave polymorphically.
For the given example, we can simplify the
Event
class to the following:
The
EventLog
class no longer need to adhere to the Rule of Five and implement all the special member functions. In fact, it can follow the Rule of Zero and implement none.
The client code does not change. The
main()
function from the previous section does not change. However, the entire code has become simpler.
std::polymorphic
solves a series of issues:
The owner is copyable again:
std::polymorphic
is itself copyable, performing a correct deep copy of the owned object. The composite’s copy operations are compiler-generated, which means they follow the Rule of Zero.
No
clone()
protocol: the copy operation is type-erased and captured at construction, when the concrete type is statically known. The hierarchy needs no
clone()
function, and there’s nothing for a derived class to forget.
Clean interfaces: with no
clone()
to declare, the base class contains only domain methods.
const
propagates: through a
const std::polymorphic
, access to the owned object is const. Deep const is enforced by the type system, not by convention.
Never null: a
std::polymorphic
object always owns a value; there is no null state to construct. The only empty state is moved-from, explicitly detectable via
valueless_after_move()
, so every dereference elsewhere is valid by invariant.
In short, the
std::polymorphic
component behaves like a regular member again: copyable, deeply const, always present, while keeping its dynamic type.
You may ask, when you copy a
std::polymorphic<Event>
that holds a
TemperatureReadingEvent
, how does it know to copy a
TemperatureReadingEvent
without a virtual
clone()
? The answer is type erasure of the copy operation, captured at construction time.
Conceptually,
std::polymorphic<Event>
stores its object behind a small internal control structure. When you construct it with
std::in_place_type<TemperatureReadingEvent>
, the constructor, which at that moment statically knows the type is
TemperatureReadingEvent
, instantiates and stores operations equivalent to the following:
Later,
std::polymorphic
‘s copy constructor just invokes the stored operation. It’s the same technique
std::function
and
std::any
use, applied to the copy constructor. This also means
Event
doesn’t even need a virtual destructor for
std::polymorphic
to destroy it correctly. The erased destroy operation already knows the concrete type. That doesn’t mean you should remove the the virtual destructor, as other code may still delete through base pointers.
The rest of the interface mirrors the
std::indirect
type:
operator*
/
operator->
give you
Event&
/
Event*
, const-propagated (through a
const std::polymorphic
you get
const Event&
).
Never null, except the moved-from state, queryable with
valueless_after_move()
.
Allocator-aware, and unlike
std::indirect
, implementations are permitted a small-buffer optimization, storing small derived objects inline without heap allocation.
There’s no way to ask “which derived type is inside?”. It doesn’t feature a
type()
function like
std::any
has. If you need that, use
dynamic_cast
on
*p
like you would with any base reference. The design intent is that you interact through the base interface.
Conclusion
Use
std::polymorphic
when a class owns a component whose dynamic type varies at runtime and that component is part of the owner’s value: copying the owner should copy it,
const
should propagate to it, and it should never be absent. Typical cases are strategy members, heterogeneous collections like event logs, and recursive structures like expression trees.
If the type is fixed, use
std::indirect
.
If the set of alternatives is closed, use
std::variant
.
If the object is a shared identity rather than a value, stick with smart pointers.
See also
Here is a list of additional readings on the subject:
The Israeli Private Eye at the Heart of a Climate Hacking Scandal
Published
Mark Harris
This article is based on decades of court documents, business filings and interviews. Karen Zraick reported from New York City and Gabby Sobelman from Haifa, Jerusalem and Tel Aviv.
For decades, an Israeli private investigator named Amit Forlit has operated on the edges of international intrigue while rubbing elbows with powerful figures.
Mr. Forlit claims to have served in Shin Bet, Israel’s internal security agency. He dated a prominent Israeli businesswoman and social-media figure who photographed him at exclusive parties. And he may or may not have inspired a hacker-for-hire character in a 2022 novel about murky financial shenanigans involving Argentine debt.
These were mostly bit parts in other people’s dramas. Until now.
Today Mr. Forlit, wearing an ankle monitor while remaining in the New York City area, awaits trial in a globe-spanning hacking case where he is the central character. Prosecutors with the Justice Department have charged him with overseeing an operation that aimed to discredit American environmentalists, allegedly on behalf of a huge oil company. He has pleaded not guilty.
Mr. Forlit could face decades in prison.
The charges, filed in the U.S. District Court for the Southern District of New York, allege a “sprawling criminal enterprise” in which Mr. Forlit and his associates hired hackers in India to gain unauthorized access to the environmentalists’ private email accounts. Mr. Forlit’s lawyers have identified the oil company described in the allegations as Exxon Mobil, and the commissioning firm as DCI Group, a Washington public relations and lobbying firm.
Exxon and DCI have denied any role.
In a statement, Exxon said the company had “not been involved in, nor are we aware of, any hacking activities. If there was any hacking involved, we condemn it in the strongest possible terms.”
A spokesman for DCI, Craig Stevens, said the Justice Department had confirmed to DCI’s lawyers that it was “not investigating our firm or any of our employees” last year. “We direct all our employees and consultants to comply with the law, and allegations of DCI Group’s involvement with this activity, alleged to have occurred more than a decade ago, are false and unsubstantiated,” he said.
Federal Court in Manhattan. Hiroko Masuike/The New York Times
The case puts Mr. Forlit at the center of some of the most consequential legal battles the fossil fuel industry has faced. Dozens of states and cities
are suing oil companies
, including Exxon, claiming among other things that the industry misled Americans for decades about the climate and health damage caused by the burning of fossil fuels. If successful, the claims could cost the industry billions of dollars.
Prosecutors allege Mr. Forlit was part of an effort to stymie or kill these court cases.
Mr. Forlit, 58, was extradited to New York City from London this year. At a hearing in April in a Lower Manhattan courthouse, he cut an unassuming figure: tall with close-cropped, graying hair, wearing a short-sleeved blue button-down and spectacles. He ducked down to confer with his lawyer, Sabrina Shroff, who had recently made headlines for winning the acquittal of a man for
throwing a sandwich at a federal officer
in Washington.
The Return of Child Labor
Portside
portside.org
2026-10-19 01:06:18
The Return of Child Labor
Ira
Mon, 10/19/2026 - 01:06
...
This story was produced in partnership with the Economic Hardship Reporting Project and supported with a residency from The Bellagio Center.
For years I have been haunted by a grainy video I saw in 2023, when I was interviewing poultry processing workers in Green Forest, Arkansas. In those months I spoke often with the organizer Magaly Licolli, who directs Venceremos, a grassroots organization dedicated to protecting the rights of poultry workers. One day we were sitting in her office in Springdale a few miles from the headquarters of Tyson Foods, the largest meat processing company in the US and, after the Brazilian firm JBS, the second largest in the world. After the subject turned to child labor, she pulled out her phone and showed me footage that another laborer had recorded of two migrant children, fourteen and fifteen years old, working as chicken catchers in a cavernous rural poultry house. The video was dark, but it was clear that they were using their bare hands to grab each chicken by the feet and hurl it into a nearby crate. Their bodies showed up only in outline, like ghostly shadows.
Earlier that year, Licolli told me, six chicken catchers—four adults and two children—had come to Venceremos’s office to seek help. The two minors were asleep when they arrived, she said, “because they hadn’t slept for so many hours.” The catchers explained that the contractor who hired them had denied them a week’s wages because—although they had worked fourteen-to-fifteen-hour days under physically extreme, sometimes dangerous conditions—they hadn’t managed to finish crating 56,000 chickens. According to the Fair Labor Standards Act (FLSA), the catching and cooping of poultry for transport or market is strictly prohibited for minors under the age of sixteen.
After some asking around, Licolli found the name of the contractor, called him, and told him he had to pay the chicken catchers. “Otherwise, I would have involved the Department of Labor,” she told me. The contractor agreed. Licolli drove to Decatur, some thirty miles from Springdale, to pick up the money, and “that’s how that was resolved.”
In the years that followed, I thought back to those teenagers often. Who was the contractor they worked for? How many other minors did that employer hire? How many other children were working dangerous fifteen-hour shifts? In its brevity and ambiguity, their story seemed to show the predicament of so many children laboring in the poultry processing industry and other dangerous jobs across the US. Working in informal arrangements, they have come to rely on advocates like Licolli to push for their rights, sometimes through similarly informal channels. Many of the children she met in Arkansas, she said, had arrived at the US–Mexico border as unaccompanied minors. The teenagers in this case, she explained, were K’iche, the largest Indigenous Maya ethnic group in Guatemala, and like most immigrant children in the industry, they had “come with a mind [to] making money to send…back to their very poor families.”
I met with Licolli during a historic nationwide spike in child labor violations. That fiscal year,
according to
The Washington Post
, the US labor department “found 5,792 minors working in violation of child labor laws,” an increase of 49 percent from the previous year and “an 88 percent increase since 2019.” Pete Gess, the economic policy director of Arkansas Advocates for Children & Families,
noted in a 2024 report
that Arkansas’s Department of Labor and Licensing had identified a 266 percent increase in child labor violations from 2020 to 2023.
At the time I lived in downtown Little Rock, among sprawling, old, ruinous houses. Often I heard Spanish while walked down the street and looked up to see visibly underage immigrant children working on roofing crews. Sometimes I would shout up to ask them where they were from and wait for them to respond—“Guatemala” or “Mexico.” That same year Arkansas was one of eight states that made national headlines for systemic child labor violations: that February the Department of Labor found six children between the ages of thirteen and seventeen working the night shift for a third-party contractor called Packers Sanitation Services Inc. (PSSI) at a Tyson Foods plant in Green Forest, where they used harsh chemicals to clean blood, fat, bone, gristle, and skin from machines powerful enough to
decapitate a worker
.
Even as these violations proliferated, lawmakers in Republican-led states were taking aim at the regulations themselves. Between 2021 and 2023, fourteen states introduced or passed bills that weakened child labor laws. Two laws in particular, both passed in 2023, were at the forefront of this trend. One was in Iowa; the Economic Policy Institute (EPI), which monitors child-labor legislation,
called it
“one of the most dangerous rollbacks of child labor laws in the country” for, among other things, “allowing state agencies to waive restrictions on hazardous work for 16–17-year-olds in a long list of dangerous occupations.”
The other was in Arkansas. Less than a month after the Labor Department announced its findings about the Green Forest plant, Governor Sarah Huckabee Sanders, who had served as Donald Trump’s press secretary during his first term, signed a bill called the
Youth Hiring Act
. By removing a century-old Division of Labor permission that required a parental signature for any child under sixteen seeking employment, the law effectively eliminated the only database that had kept track of working minors in the state. Sanders
maintained
that “all child labor laws will still apply and we expect businesses to comply just as they are required to do now.” But when I spoke to child advocates like the policy analysts Nina Mast and Reid Maki about the bill two years after it passed, both stressed that it had reduced state oversight at a time when child-labor violations were increasing.
Nationwide, the number of minors employed in violation of federal law remains at near-record highs. After falling to 4,030 in the 2024 fiscal year, the figure rose to 5,272 in 2025. Hazardous work violations, such as those the labor department has investigated in Arkansas’s meatpacking industry, have more than doubled since 2015,
according to federal data
. The state-level legislative push to dilute child-labor reporting and enforcement, meanwhile, has only gathered force. According to the EPI’s
reporting
, lawmakers in thirty-three states have by now introduced bills that weaken child labor laws. In 2023 Arkansas and Iowa were two of four states to successfully enact such legislation; now, three years later, fifteen states have done so. This wave of legislation may not directly affect the undocumented migrant children at the center of many recent high-profile child-labor investigations, who often take jobs via informal arrangements or under aliases, but it seems likely to discourage states from taking action to protect them and other vulnerable minors. Partly in response to these rollbacks, other legislatures have meanwhile strengthened their protections against child labor, from liberal strongholds like California and New York to red states like Texas and Alabama.
“When I started at the Wage and Hour Division in 2021,” Jessica Looman—who spent four years running the federal agency’s efforts to enforce labor laws across the country—told me in June 2025, “I did not think that by the end of 2022 our number one issue would be finding hundreds of children employed in the meatpacking industry in America.” Gess, at the Arkansas Advocates for Children & Families, stressed when we spoke in Little Rock that child labor “shouldn’t be a political issue.” In recent years, however, it has become precisely that. The rollback of child labor protections in Arkansas, I came to see, reflected a broader, increasingly politicized national campaign to weaken labor regulations, expand youth employment, and redefine the limits of hazardous and dangerous work for children.
Our current approach to regulating child labor dates back to the Fair Labor Standards Act (FLSA) of 1938, which barred minors under eighteen from hazardous occupations. In 1941 a Georgia company, Darby Lumber, challenged the law and arrived at the Supreme Court, arguing that the states, not Congress, should have the power to regulate employment conditions. The justices, however, unanimously upheld the FLSA.
Over the past several decades Republicans have made repeated attempts to roll back child labor legislation. In 1984 President Ronald Reagan addressed Congress to propose the Youth Employment Opportunity Wage Act. “Studies over the past decade,” he insisted, “have repeatedly demonstrated that the minimum wage has reduced job opportunities for large numbers of our youth.” But lawmakers and labor organizations warned that the act would leave workers more vulnerable to exploitation, and the bill failed. In 2011 the Republican presidential candidate Newt Gingrich called child labor laws “truly stupid” and proposed putting poor children to work sweeping the floors of their classrooms: “Most of these schools ought to get rid of the unionized janitors, have one master janitor and pay local students to take care of the school.”
A poultry house in rural northwest Arkansas, 2025 Jacky Muniello
That same year several state legislators proposed bills to overturn youth-employment regulations. In Maine, Republicans
tried to pass
the “Enhance Access to Workplace for Minors” act, which would have allowed sixteen-and-seventeen-year-olds to work overnight shifts and unlimited hours on school nights, as well as lowered their wages. A limited version of the bill passed, easing restrictions on working hours. In more recent years, as Republican lawmakers and pro-business groups again began seeking to roll back child labor laws, they increasingly started speaking about defending
parental and personal freedoms
against government overreach.
Then, around 2020, several developments laid the groundwork for a sudden rise in child-labor violations. As Jacob Bogage and María Luisa Paúl wrote in
a 2023 report
for
The Washington Post
, the labor shortage induced by the Covid-19 pandemic “created a huge need for workers” even as “large numbers of undocumented minors entered the United States looking for work,” driven from countries such as Honduras and Guatemala by political and economic turbulence. In 2008 Congress had passed an anti-trafficking bill that included provisions preventing the Department of Homeland Security from sending back undocumented minors crossing the US–Mexico border. The intent was “to protect children who might otherwise come to harm on their own in Mexican border towns,” the journalist Hannah Dreier wrote in
one of her landmark reports
for
The New York Times
on child labor at sites including Tyson and Perdue plants. Over the following years, she noted, the policy became “widely known in Central America, where it shapes the calculations of destitute families.”
When the 2008 law was passed, fewer than ten thousand unaccompanied minors crossed the southern border each year. By 2014 that number had risen to 68,541; by 2021 it had risen to 144,834. During the pandemic, as
Melissa Sanchez reported for
ProPublica
,
an increasing number of immigrant teenagers started working in factories at night while attending school during the day. “Many of them passed through the federal network of shelters for unaccompanied immigrant minors that came under scrutiny in 2018 during the Trump administration’s policy of separating children from their parents,” she wrote. “As they waited weeks or months to be released to sponsors, they grew anxious about their mounting immigration debts, desperate to get out and work so their relatives back home didn’t suffer the consequences of a loan default.”
Child labor violations have risen dramatically not simply because these minors entered the country but because, once they got here, contractors were willing to exploit them to do dangerous jobs. Looman, the former Wage and Hour administrator, told me that the most frequent question people would ask her division was: “Why is child labor increasing?” In some sense, she said, “the very simple answer to that question is: because employers hired them.”
Large companies in the poultry processing industry, where child labor is especially prevalent, frequently rely on third-party contractors to fill various jobs in the supply chain. The largest of these third-party contractors is PSSI, which provides slaughterhouse cleaners and employs over 15,000 workers. (Its owner, in turn, is the private equity giant Blackstone.) By contrast, the companies that contract catchers to work at chicken houses are often small and local, and have little online presence.
Those chicken catchers, as the filmmaker Diana Campos has noted in her short documentary
The Price of Poultry
, work at “the bottom of the poultry industry hierarchy.” Large commercial chicken houses can hold between 30,000 and 50,000 chickens, and laborers often report working up to fifteen-hour shifts loading the birds by hand for transport to processing plants. (To work such long hours, Licolli
told a local paper
last December, some kids working as chicken catchers have relied on methamphetamine.) Campos was raised in Northwest Arkansas by Mexican immigrant parents; her father, who she interviews in the film, worked in the poultry industry for twenty years, including as a catcher. The people working catching shifts, she recounts partway through the documentary, “are often undocumented and sometimes children.”
Beyond the exhausting hours, chicken catchers are at risk of serious injuries and exposed to ammonia and other hazardous chemicals, extreme heat, and respiratory illnesses. In the recent Netflix documentary
Big Chicken: A Fast Food Conspiracy
, the comedian Mo Gilligan interviews chicken catchers laboring under these conditions, along with advocates and journalists (including Licolli and myself). One undocumented chicken catcher shows his hands, with deformed, swollen fingers splayed in different directions. From time to time, he tells Gilligan, he loses control over them: “Sometimes when we sleep, our hands are throwing chickens.”
Catching and caging poultry are not among the seventeen hazardous occupations the Department of Labor prohibits for sixteen- and seventeen-year-olds, but the department, recognizing their risks, explicitly bans them for minors under sixteen. The sector’s layers of subcontracting and labor outsourcing, however, often obscure accountability. When Tyson and other meatpackers hire third-party providers, these providers are the
first to shoulder
the financial liability for employment practices and safety violations.
The Department of Labor’s findings at that Tyson plant in Green Forest were part of a months-long investigation into PSSI. Over the period in question, the department
announced
in February 2023, PSSI had hired more than a hundred minors to work overnight shifts at poultry plants across eight states, operated by large companies including Tyson, Cargill, and JBS; the contractor had to pay $1.5 million in civil penalties, the highest fine the government was legally able to impose. PSSI has denied knowingly hiring minors, although in the aftermath of the penalty NBC News
reviewed
a June 2021 PSSI report and found that the company had disciplined an employee who hired the same minor twice in six months under two different identities. In response to the fine, PSSI replaced its CEO, launched a $10 million fund to fight child labor, and, in 2025, rebranded as Fortrex.
A truck carrying chickens on the road into Dardanelle, Arkansas, home to a Tyson Foods plant, 2025 Jacky Muniello
The investigation had by then prompted some changes in compliance protocols around third-party agreements in the industry. Tyson mandated random third-party and internal audits of its sanitation partners’ hiring registries, while JBS USA canceled its contracts and started hiring its own cleaning crews. And yet allegations of child labor at Tyson persist. In 2024,
according to unsealed court documents reviewed by the
Arkansas Times
, the Department of Labor searched a pair of the company’s plants in Arkansas after receiving anonymous tips, one from a mother who claims to have “overheard children between eleven and thirteen years old” discussing their work on the night shift in Green Forest and another from a teacher who said that one of their fourteen-year-old students talked about working at the facility in Rogers. Earlier that year, Tyson shareholders
voted down
a demand from Venceremos and an Arkansas faith-based organization that the company audit its plants for child labor. In 2025 the Republican Missouri senator Josh Hawley
opened a congressional investigation
into the company after receiving a new whistleblower complaint from a plant in an undisclosed location. “To be clear,” a Tyson spokesperson told the press in response to the
Arkansas Times
report, “we do not allow the employment of anyone under the age of eighteen in any of our facilities, and we do not facilitate, excuse or in any other way participate in the use of child labor.”
In June 2025 I interviewed a Tyson contractor who works at several facilities in Arkansas. (She requested anonymity for fear of retaliation.) When she first began work, she was given a tour of the plant in Springdale. “I was scared to be in there,” she told me. “And I’m an adult.” The “giant tubs where they wash the chicken” were “almost the size of my house,” she said. “There’s just an open hole. I mean, you have to climb up these stairs, a steep staircase.… And it’s water-filled with these big chickens bouncing around, almost like a washing machine.” On the production floor, she said, “It’s loud. It’s disorienting. It’s wet and slippery, and you can’t hear people talking to you. You have to wear earplugs for ear protection. But that also means that you can’t hear instructions…. A lot of people complain about headaches, a lot of chemicals going on. It’s just not a place that any child should be.”
The Arkansas Youth Hiring Act made this already opaque system still harder to regulate. When the law passed in 2023, it eliminated the requirement that children under sixteen get an employment certificate, signed by their parents, from the Arkansas Department of Labor and Licensing, which meant that the state was no longer required to verify their age. Children that age in Arkansas commonly work in fast food, bagging groceries, customer service, or seasonal work like lifeguarding; the act did not change safety or hourly protections, nor did it affect the laws that regulate hazardous jobs. It did, however, signal a rollback in state oversight of the conditions in which minors were working, precisely at a time when employers in the state were under scrutiny for child labor violations.
Sponsored by the Republican representatives Rebecca Burkes and Clint Penzo, the bill cast itself as a matter of parental rights, promising to “streamline the hiring process for children under sixteen” and “restore decision-making to parents” without government interference. Alexa Henning, Sanders’s spokesperson,
echoed that language in a statement
upon the signing of the bill: “the Governor believes protecting kids is most important, but this permit was an arbitrary burden on parents to get permission for their child to get a job.” When the law went through the Public Health, Welfare, and Labor Committee,
according to a local news report
, Burkes argued that it would give parents the freedom to dispense with the “paperwork that has to be done before the minor can accept a job.” The legislation, she noted, “came to me from the Foundation of Government Accountability [sic].”
Burkes was not the only state legislator to propose child-labor legislation from the Foundation for Government Accountability (FGA), a Florida-based think tank with a lobbying arm called FGA Action. In their
Washington Post
investigation of the group, Bogage and Paúl noted that the FGA had, in 2023, also helped draft several other bills, including Iowa’s; the organization, they wrote, seemed to have “found remarkable success among Republicans to relax regulations that prevent children from working long hours in dangerous conditions.” There are larger culture-war dynamics at play here: the same legislators who argue for “parental rights” when it comes to child labor have, for instance, passed laws that strip parents of the right to approve gender-affirming medical care or certain counseling for their transgender teenagers, including in Arkansas, which banned gender-affirming medical care in 2021.
After Sanders signed the Arkansas Youth Hiring Act, Nick Stehle, the FGA’s vice president of communications,
wrote an op-ed
for Fox News defending the law from “partisan attacks” by “out-of-state elites.” (Stehle, Burkes, and Penzo did not respond to requests for comment.) “We’re not talking about sending junior to work the graveyard shift at the factory Sunday through Saturday,” Stehle, who lives in Arkansas, wrote:
We’re talking about bussing tables a couple nights a week after school, working the check-out counter on weekends, and staying busy during summer…. The main push for this reform didn’t come from big business. It came from families like mine, who want more of the freedom that lets our children flourish.
Representative Tippi McCullough, who is serving her fourth term in the Arkansas House, voted against the bill. “I think it’s terrible,” she told me in 2025. “I don’t think it’s needed. I think, as a matter of fact, it’s harmful. I don’t think it’s pro-parental rights. I really think parents should want there to be safeguards and checks on these kinds of things.” (The
New York Times
opinion writer Jessica Grose
made a similar point
in a piece responding to the law: “Wouldn’t parents have
more
of a decision-making role, not less, if their explicit permission were required before their fourteen-and-fifteen-year-olds could work up to forty-eight hours a week, six days a week?”) Before serving in the House, McCullough was an English teacher and coached basketball. “I just always felt like that was a time for kids—maybe the only time in their lives—to be able to concentrate on school and extracurricular things and sports,” she said. “I mean, there’s going to be plenty of time to work the rest of your life.”
Multiple experts I spoke with argued that removing the permitting requirement would make child-labor violations harder to track. Annie B. Smith—a law professor at the University of Arkansas, where she directs the civil litigation and advocacy clinic and the human trafficking clinic—explained that “there’s less of a state role ensuring that children aren’t working, or that if they are working, they’re supposed to be working.” Debbie Berkowitz, now a fellow at Georgetown University’s Kalmanovitz Initiative for Labor and the Working Poor, served as chief of staff and then senior policy advisor for OSHA from 2009 to 2015. “What Sarah Huckabee Sanders did,” she told me in June 2025, “is allow employers to hire kids in jobs without their parents knowing, without the state knowing.”
In any case, advocates argued, safeguards for kids should rely on more than parental decision-making. “We just fundamentally feel that parents don’t know best,” Maki, the Director of Child Labor Advocacy for the National Consumers League, told me when we spoke. “They’re not looking at accident reports and poultry plants. They’re not looking at the number of kids on farms who are being dismembered or losing limbs. They just have no idea what the dangers are.” In January 2025 researchers at the University of Maryland
found
that states with work permit requirements had 15.5 percent fewer child-labor violation cases per million people and 35.2 percent fewer minors working under illegal conditions than states without such rules.
That June I wrote Sam Dubke, Sanders’s communications director and speechwriter, to ask whether the governor wanted to comment on those findings and elaborate on what she was doing to prevent an increase in child labor violations in the state. “Governor Sanders takes child welfare seriously and signed legislation creating tough new civil, misdemeanor, and felony penalties for child labor violations, punishing bad actors while still giving teenagers the opportunity to learn skills in the workplace,” Dubke wrote. “All federal child labor laws are still enforced.” A month after signing the Arkansas Youth Hiring Act, Sanders
did sign a bill
that increased fines for child labor violations from $1,000 to $5,000 and criminalized breaking the laws knowingly. In June 2025 I emailed Steve Guntharp, the chief of staff at the Arkansas Labor Department, to confirm how many employers had been fined since the increase. The answer was two.
It was in 2023 that the Economic Policy Institute started tracking laws rolling back child labor protections across the country. “We realized this was really a much more widespread effort, legislatively, across many different states,” Mast, a policy and economic analyst at the EPI, told me, “and no one at the time was really paying that much attention to it.” In 2024, indeed, six states rolled back child labor protections. (Seven, meanwhile, passed bills that strengthened them.) According to the institute’s reporting, that year Alabama stopped requiring work permits for minors under sixteen, Florida let companies “schedule 16–17-year-olds to work more than eight hours per day on Sundays and holidays and for more than six days in a row year-round,” and Indiana rolled back protections for sixteen- and seventeen-year-olds doing hazardous agricultural work. All three bills,
the EPI noted
, were supported by the Foundation for Governmental Accountability. The following year West Virginia, like Arkansas, passed legislation that eliminated youth work permits for fourteen- and fifteen-year-olds; Indiana passed a law that allowed sixteen- and seventeen-year-olds to work the same hours and shifts as adults and eliminated the requirement for employers to secure written parental consent to schedule them for late shifts on school nights.
A park overlooking the Arkansas River in Dardanelle, Arkansas, 2025 Jacky Muniello
Trump has made no explicit statements about child labor since taking office, but last year, as Maki and his coauthor Todd Larsen have
observed
, the Trump administration “identified twenty-one offices for closure within the Labor Department’s Wage and Hour Division” and cut staff at the agency responsible for enforcing federal child labor laws. Project 2025, the Heritage Foundation’s 2023 blueprint for a second Trump term, called for watering down the Department of Labor’s hazard-order rules “to permit teenage workers access to work in regulated jobs with proper training and parental consent,” observing that “some young adults show an interest in inherently dangerous jobs.” The federal regulations have not yet been rolled back, but this past year three state legislatures—in West Virginia, Virginia, and Pennsylvania—introduced bills that would “weaken hazardous work protections for minors enrolled in work-based learning programs,”
according to the EPI
. West Virginia’s passed, removing the state’s specific list of hazardous occupations that were previously barred for minors under sixteen, among other things.
Trump’s immigration crackdown, too, has directly affected the landscape of child labor. The threat of deportation makes undocumented minors in the workforce more afraid than ever to report abuses, and the administration has made them still more vulnerable by systematically dismantling the legal support networks designed to help them—including by
cutting funding
to legal services that had long provided them with counsel.
Elsewhere, state legislators have contemplated turning to minors to take jobs previously filled by immigrant workers. At an event in March 2025 with Tom Homan, Trump’s border tsar, Florida Governor Ron DeSantis made that connection explicit. Rather than hiring “people illegally for cheaper,” he said, “I think we’ve chosen to go a different way in Florida.” When the state passed a policy requiring many employers to verify the immigration status of their workers online, he continued, critics “said, oh, you’re not gonna be able to hire people.” But those worries, he continued, hadn’t been borne out:
Yes, we had people that left because of those rules. But you’ve also been able to hire other people—and what’s wrong with expecting, like, our young people to be working part-time now? I mean, that’s how it used to be when I was growing up. Why do we say we need to import foreigners, even import them illegally, when, you know, teenagers used to work at these resorts?
Five days after that panel discussion, a Florida state senate committee moved along a bill that would have allowed sixteen- and seventeen-year-olds to work more than eight-hour overnight shifts before the start of a school day. “It was such a bad bill,” said Maki, who noted that it was “close to getting through” before it finally died elsewhere in the Senate. The bill’s sponsor, the Tampa Republican Jay Collins, defended it
during a senate debate
: “Ultimately, we’re not talking about
The Jungle
by Upton Sinclair. We’re talking about them working at Publix, at Piggly Wiggly or jobs within the industry. This is a parental rights thing. Parents know their kids best.”
The Democratic state senator Carlos Guillermo Smith, meanwhile, spoke for the majority who voted against the legislation: “This bill is going to lead to exploitation of minors, exploitation of children.”
A 2024 poll by the Florida Policy Institute
showed that 74 percent of Florida voters sided with Smith against the bill, including 61 percent of Republicans and 73 percent of independents. “These leaders are kind of ignoring their own base, in some cases,” Maki said, in favor of “just pushing regressive policies on the public.”
When we spoke, Nina Mast told me that “all the organizing that has been done in opposition to these bills over the past few years” gives her hope that activists will continue fighting to keep legislators from rolling back child labor protections. In 2024 the Campaign to End US Child Labor, which represents a coalition of nearly fifty labor, human rights, and faith groups, worked with academics, survivors, and impacted communities to create a policy roadmap for local, state, and federal lawmakers. Their demands included guaranteed attorney representation for unaccompanied migrant children, the closing of loopholes in child-labor laws, “stronger consequences for child labor violations,” and the bolstering of labor rights across the board by, for instance, “raising the minimum wage, ending discrimination against farmworkers, regularizing the status of the current immigrant workforce, protecting the right to organize, and preventing states from eroding labor standards.” The National Education Association, a member of the coalition, has advocated for treating student labor exploitation as a critical threat to public education. As the Maine teacher Rie Larson put it in a 2025
NEAToday report
, “Our children are not responsible for rescuing our economy.”
Smith, the Arkansas lawyer, wishes that policymakers in Arkansas and beyond would focus on state-level interventions that address the economic needs of children and families more directly, to keep children from feeling pressured into hazardous workplaces in the first place. She also emphasized that states should pursue legislation that protects coworkers who see children doing hazardous jobs and decide to report it. Witnesses need to be able to file complaints without the risk of legal or workplace retaliation, she said, because “we know that there are simply not enough resources for the Arkansas Department of Labor or the US Department of Labor to be in every workplace.” Gess had another recommendation: finding legal pathways with which “to hold the primary company responsible for violations throughout its labor supply chain.” (Those could, for instance, be modeled on laws in other countries like Germany’s Supply Chain Act and France’s Duty of Vigilance law, both of which legally require companies to identify, prevent, and mitigate labor abuses across their global contractors.)
Many of the advocates I spoke to felt that such measures could do a good deal to help protect children like those chicken catchers that Licolli met back in 2023. But several of them also seemed unnerved by how quickly decades of consensus regarding the importance of protecting minors from hazardous work appears to be coming undone. “One hundred years ago, people started advocating to protect children because parents weren’t able to go into the workplace” and monitor conditions there, Gess told me. “Who knew a hundred years later we would be fighting some of the same battles?”
Alice Driver
is a writer from the Ozark Mountains and the author of
Life and Death of the American Worker
.
The New York Review
was launched during the New York City newspaper strike of 1963, when the magazine’s founding editors, Robert Silvers and Barbara Epstein, alongside Jason Epstein, Robert Lowell, and Elizabeth Hardwick, decided to start a new kind of publication—one in which the most interesting, lively, and qualified minds of the time could write about current books and issues in depth.
Readers responded by buying almost every copy and writing thousands of letters to demand that the Review continue. From the beginning, the editors were determined that the Review should be an independent publication; it began life as an editorial voice beholden to no one, and it remains so today.
Artificial Analysis Intelligence Index v4.3.2
includes:
AA-Briefcase v1.1, GDPval-AA v2.1, AutomationBench-AA, Terminal-Bench 4.0, SciCode, Humanity's Last Exam, GDP.pdf, CritPt, AA-Omniscience, AA-LCR v1.1
. See
Intelligence Index methodology
for further details, including a breakdown of each evaluation and how we run them.
Artificial Analysis Intelligence Index by Open Weights / Proprietary
Artificial Analysis Intelligence Index v4.3.2
includes:
AA-Briefcase v1.1, GDPval-AA v2.1, AutomationBench-AA, Terminal-Bench 4.0, SciCode, Humanity's Last Exam, GDP.pdf, CritPt, AA-Omniscience, AA-LCR v1.1
. See
Intelligence Index methodology
for further details, including a breakdown of each evaluation and how we run them.
Indicates whether the model weights are available. Models are labelled as 'Commercial Use Restricted' if commercial use is limited by conditions, and as 'Non-commercial' if the license prohibits commercial use.
Intelligence Index vs. Cost per Task
Artificial Analysis Intelligence Index · Weighted average cost (USD) per Artificial Analysis Intelligence Index task
Weighted average cost per Intelligence Index task. Each evaluation’s cost is calculated from input, cache hit, cache write, reasoning, and answer token prices, divided by task count, and weighted by its Intelligence Index weight.
Artificial Analysis Intelligence Index v4.3.2
includes:
AA-Briefcase v1.1, GDPval-AA v2.1, AutomationBench-AA, Terminal-Bench 4.0, SciCode, Humanity's Last Exam, GDP.pdf, CritPt, AA-Omniscience, AA-LCR v1.1
. See
Intelligence Index methodology
for further details, including a breakdown of each evaluation and how we run them.
While model intelligence generally translates across use cases, specific evaluations may be more relevant for certain use cases.
Artificial Analysis Intelligence Index v4.3.2
includes:
AA-Briefcase v1.1, GDPval-AA v2.1, AutomationBench-AA, Terminal-Bench 4.0, SciCode, Humanity's Last Exam, GDP.pdf, CritPt, AA-Omniscience, AA-LCR v1.1
. See
Intelligence Index methodology
for further details, including a breakdown of each evaluation and how we run them.
AA-Briefcase v1.1
Updated
AA-Briefcase Elo
AA-Briefcase v1.1 is an agentic knowledge work benchmark developed by Artificial Analysis. AA-Briefcase Elo is a combined metric that aggregates rubric pass rate, analytical quality Elo and presentation Elo · Higher is better
No publicly available API
AA-Briefcase Elo is a combined metric that aggregates analytical quality Elo, presentation Elo, and rubric pass rate, with rubric performance converted into Elo via synthetic head-to-head matches. Elo and 95% confidence interval bounds are clamped at 0.
AA-Omniscience
AA-Omniscience Index
AA-Omniscience Index (higher is better) measures knowledge reliability and hallucination. It rewards correct answers, penalizes hallucinations, and has no penalty for refusing to answer. Scores range from -100 to 100, where 0 means as many correct as incorrect answers, and negative scores mean more incorrect than correct.
No publicly available API
AA-Omniscience Index (higher is better) measures knowledge reliability and hallucination. It rewards correct answers, penalizes hallucinations, and has no penalty for refusing to answer. Scores range from -100 to 100, where 0 means as many correct as incorrect answers, and negative scores mean more incorrect than correct.
Openness Index
Artificial Analysis Openness Index: Score
Openness Index assesses model openness on a 0 to 100 normalized scale (higher is more open)
Intelligence Index Comparisons
Intelligence Index vs. Cost per Task
Artificial Analysis Intelligence Index · Weighted average cost (USD) per Artificial Analysis Intelligence Index task
Weighted average cost per Intelligence Index task. Each evaluation’s cost is calculated from input, cache hit, cache write, reasoning, and answer token prices, divided by task count, and weighted by its Intelligence Index weight.
Artificial Analysis Intelligence Index v4.3.2
includes:
AA-Briefcase v1.1, GDPval-AA v2.1, AutomationBench-AA, Terminal-Bench 4.0, SciCode, Humanity's Last Exam, GDP.pdf, CritPt, AA-Omniscience, AA-LCR v1.1
. See
Intelligence Index methodology
for further details, including a breakdown of each evaluation and how we run them.
Token Use
Output Tokens per Intelligence Index Task
Weighted average number of output tokens used to run one task in the Artificial Analysis Intelligence Index
No publicly available API
The number of tokens required per Intelligence Index task. This is calculated by multiplying the output tokens per eval by the relative weights of each benchmark in the Intelligence Index, then dividing by task count (excluding repeats).
Cost
Cost per Intelligence Index Task
Weighted average cost (USD) per Intelligence Index task · Segmented by token type · Lower is better
Weighted average cost per Intelligence Index task. Each evaluation’s cost is calculated from input, cache hit, cache write, reasoning, and answer token prices, divided by task count, and weighted by its Intelligence Index weight.
Cost to Run Artificial Analysis Intelligence Index
Cost (USD) to run all evaluations in the Artificial Analysis Intelligence Index
The cost to run the evaluations in the Artificial Analysis Intelligence Index, calculated using the model's input, cache hit, cache write, reasoning, and answer token prices and the number of tokens used across evaluations (excluding repeats).
Pricing: Cache Hit, Input, and Output
Price (USD per M Tokens)
Price per token for cached prompts (previously processed), typically offering a significant discount compared to regular input price, represented as USD per million tokens. The values shown here are the cache hit price; cache write and cache storage are billed separately and vary by provider — see "Cache pricing by provider" for detail.
Context Window
Context Window
Context window: tokens limit · Higher is better
No publicly available API
Larger context windows are relevant to RAG (Retrieval Augmented Generation) LLM workflows which typically involve reasoning and information retrieval of large amounts of data.
Maximum number of combined input & output tokens. Output tokens commonly have a significantly lower limit (varied by model).
Speed
Measured by Output Speed (tokens per second)
Output Speed
Output tokens per second · Higher is better
Tokens per second received while the model is generating tokens (ie. after first chunk has been received from the API for models which support streaming).
Figures represent performance of the model's first-party API or the median across providers where a first-party API is not available.
Time per Intelligence Index Task
Weighted average decode time (minutes) per Intelligence Index task · Excludes TTFT and overhead time · Lower is better
The weighted average time (seconds) per Artificial Analysis Intelligence Index task. This is calculated by dividing output tokens per task by output speed, weighted by the relative weights of each benchmark in the Intelligence Index.
Latency
Measured by Time (seconds) to First Token
Latency: Time To First Answer Token
Seconds to first answer token received · Accounts for reasoning model 'thinking' time
Time to first answer token received, in seconds, after API request sent. For reasoning models, this includes the 'thinking' time of the model before providing an answer. For models which do not support streaming, this represents time to receive the completion.
End-to-End Response Time
Seconds to output 500 tokens, calculated based on time to first token, 'thinking' time for reasoning models, and output speed
End-to-End Response Time
Seconds to output 500 tokens, including reasoning model 'thinking' time · Lower is better
Seconds to receive a 500 token response. Key components:
Input time: Time to receive the first response token
Thinking time (only for reasoning models): Time reasoning models spend outputting tokens to reason prior to providing an answer. Amount of tokens based on the average reasoning tokens across a diverse set of 60 prompts (
methodology details
).
Answer time: Time to generate 500 output tokens, based on output speed
Figures represent performance of the model's first-party API or the median across providers where a first-party API is not available.
Model Size (Open Weights Models Only)
Model Size: Total and Active Parameters
Comparison between total model parameters and parameters active during inference (billions)
The total number of trainable weights and biases in the model, expressed in billions. These parameters are learned during training and determine the model's ability to process and generate responses.
The number of parameters actually executed during each inference forward pass, expressed in billions. For Mixture of Experts (MoE) models, a routing mechanism selects a subset of experts per token, resulting in fewer active than total parameters. Dense models use all parameters, so active equals total.
Verisign .com Domain Name Registry Consumer Class Action
This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.
What can I do to resolve this?
You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.
Show HN: Strot – Compile an LLM's intent once, run decisions locally forever
Compile your intent once with an LLM. Then decide on every record forever
—
classification, scoring, routing — as type-safe JSON with probabilities and
confidence, on your own hardware, at
zero marginal cost
.
importstrotresult=strot.run(
tickets,
query="Triage incoming support tickets into the correct workflow.",
action_registry={
"billing_dispute": "Refunds, invoice corrections, double charges",
"technical_defect": "Crashes, bugs, broken behavior",
},
llm="anthropic/claude-opus-4-8", # used once, on first compile only
)
foroinresult.outcomes:
print(o["action"], round(o["confidence"], 2))
# billing_dispute 0.97# technical_defect 0.94
The LLM runs
once
, at compile time. Production is a frozen, self-contained
Python artifact: a small local decision model arbitrates every record, nothing
is generated, every output is bounded, and low-confidence records abstain
instead of guessing.
Golden-record promotion
— artifacts must pass your known answers before they serve.
Fitted guarantees
— temperature scaling + split conformal prediction, baked in: dispatched decisions are wrong ≤ α of all records (marginal); the rest abstain.
Measured, not guessed
— the compiler scores labelings, and can train a distilled head, keeping only what beats the baseline on held-out data.
0% structural hallucination
— output is selection + computation over your registry; nothing is generated at runtime.
Model-independent
— the decision model is a slot (
nlu=
): local Julia-1 by default, hosted APIs, or any drop-in specialist.
Install
pip install strot-ai # core: pure stdlib
pip install strot-ai[local] # + the local decision model (torch/transformers)
pip install strot-ai[hosted] # + openai, for a hosted decision runtime
pip install strot-ai[anthropic] # + anthropic, for the synthesizer
Bake the local model into your image for offline production:
In November 2025, I joined international and Israeli activists in the Palestinian community of Masafer Yatta, a rural area in the South Hebron Hills. There and in other communities across the West Bank, Palestinians have responded to attacks from settlers and the Israel Defense Forces (IDF) by inviting volunteers to stay in their homes, help plow their fields, and accompany them in their daily lives.
As Israeli violence in the West Bank has escalated alongside the Gaza genocide, there has been an influx of volunteers like me joining in a practice commonly known as “protective presence,” or more recently, “solidarity presence.” My time in Masafer Yatta was spent with a loose collective of Jewish activists in Palestine whose work can be found online under the moniker Kivsa Shchora, Hebrew for “black sheep.” I paid close attention as they spoke with particular venom about the most violent settlers harassing the Palestinian communities there.
On our drive from the activist flat in At-Tuwani to the village of Az Zuweidin, where we had been called due to settler activity, an Israeli veteran of the solidarity movement told us about one notorious settler-terrorist we should be especially wary of: Shimon Atiya. In 2022, Atiya founded the illegal outpost Havat Shorashim between Az Zuweidin and the village of Umm al-Khair. In the past two years alone, he has shot a Palestinian resident in the leg, led an attack on Umm al-Khair that hospitalized six women and children, and run over a village dog with his vehicle. We stayed in Az Zuweidin for half the day watching and filming Atiya and his gang of youth shepherds construct a makeshift sheep pen from supplies stolen from a shed at the edge of the village. There was little we could do; when Magav (Israel Border Police) arrived, it was only to photograph our passports and manhandle us for filming.
West Bank settlers commonly film activists in an effort to intimidate them. (E. A. Halevi / Jacobin)
The following day, Atiya was nowhere to be found in Az Zuweidin. One of his shepherds now led the gang in his place: Dror, around fifteen years old, well built but not particularly tall. It wasn’t Dror’s physicality that elicited fear whenever activists spoke about him but his eagerness for violence and the palpable joy he took in terrorizing others. He had, I was told, brutally assaulted multiple people in the past, foreign volunteers and Palestinians alike. Joining him and his fellow shepherds was a group of older, cleaner-cut young men, presumably students of Reuta Beit Midrash, a religious school in the settlement of Carmel where Dror and his fellow shepherds also live.
Violent Settler Youth
Dror, who grew up in a settlement bloc south of Jerusalem, is part of a group known as “dropout youth.” In 2023, the Israeli Civil Administration, which governs Area C of the West Bank, stated that “approximately 220 youths live cut off from formal education and family in basic field conditions, sometimes without running water and electricity.” According to activists I spoke with, many of these teens experienced abuse or behavioral challenges early in life, factors that ultimately led them to fall out of the education system in their hometowns.
These “hilltop youth,” like Dror, find support and meaning working as a dedicated vanguard of settlement expansion displacing Palestinians. Many of them live in these settlements or nearby outposts. The settlements are illegal under international law, including the Fourth Geneva Convention, and the outposts are often additionally illegal under Israeli law. Such informal residences, which are often not the homes at which they are registered, make their identities and violent activities harder to track.
The hamlet of Fatah Sidru and, beyond that, the city of Yatta are visible from the western edge of Az Zuweidin. (E. A. Halevi / Jacobin)
For years, both Shin Bet, the Israeli secret police, and the Israel Ministry of Defense have acknowledged that dropout youth have become a problem. But under a government that brazenly proclaims its genocidal aims for a Greater Israel, their efforts to address the issue are dubious, to say the least. On June 4, 2025, Defense Minister Israel Katz appointed Colonel (res.) Avichai Tanami as the first ever civilian “project manager” charged with addressing “nationalist violence” among hilltop youth.
A former IDF intelligence commander and current West Bank settler, Tanami’s approach to the issue was, in his own words, to prevent “draconian administrative arrest warrants [against settler youth]” with a promise to lead his “national mission” with “sacred reverence.” The implication was clear: he would use his power to support violent settler youth rather than stop them.
The implication was clear: he would use his power to support violent settler youth rather than stop them.
Encouraging Hilltop Youth Outposts
Uri Blau’s September 2023 story for Shomrim, an Israeli investigative publication, revealed that the Israeli Civil Administration under Finance Minister Bezalel Smotrich awarded 800,000 NIS ($258,000) of state funds intended for Palestinians in Area C to an organization by the name of Shivat Tzion L’rigvy Adamatah (The Return of Zion to the Foundation of Her Land). Rather than aiding Palestinians, the funds were granted with the express purpose of rehabilitating hilltop youth.
Despite the organization having no public-facing website, Shivat Tzion’s CEO, Yonatan Achia, was able to grow its budget to more than seventeen million NIS ($5.5 million) in 2024, including over four million NIS in Israeli state funds for activities like “volunteering in agriculture” and “Jewish studies in an informal setting.” Although Shivat Tzion refused to clearly answer questions from Shomrim, an anonymous source familiar with the organization was willing to explain that it operates among youths who are already on farms in the West Bank, “instructing them in agriculture and attempting to direct them back to their studies and enlistment in the IDF.”
In addition to Israeli state funds, Shivat Tzion and another organization working with settler youth in the West Bank received a combined 2.5 million NIS from the Jewish National Fund (JNF) under its “Youth With a Chance” program, which provides financial support and programming for at-risk youth on a large number of farms across the West Bank.
Achia’s prolific activities, however, extend beyond Shivat Tzion. His email signature and Facebook page name him as the CEO of Artzenu, meaning “Our Land.” According to Artzenu’s website, the organization is “dedicated to bringing the pioneering spirit back to the forefront of Israeli society” and organizes over 1,280 “agricultural volunteers” and 400 “farm guards” per month across the West Bank, Galilee, and the Negev. Stranger yet, the group has achieved this success without a formal registry in Israel’s NGO system. Its domestic funding is instead channeled through Shivat Tzion.
Artzenu’s website claims dropout youth “have found a safe haven at these farms” and that the organization’s goal in working with them is to help “these teens to believe in themselves and their capabilities, and to re-integrate into Israeli society” through “guidance, trips and enrichment, preparation for the IDF, professional training, and teaching various life skills.” Its social media posts make it clear exactly what this means: encouraging youth to live and volunteer on farms in the West Bank, many of which are illegal outposts with a well-documented history of violence and harassment of neighboring Palestinians.
A recent post from January 5, 2026, praises the youth of Tirat Zvi, a religious Zionist kibbutz in the Galilee, for coming “to strengthen the nighttime guard shifts at Hagai Sharara’s farm.” Sharara’s farm is in the illegal outpost of Yad Hashomer-Tevetz in the northern Jordan Valley, and settlers associated with it have been responsible for the ethnic cleansing of ten families over the past two years from the neighboring village of Khirbet al-Malih, through assault, harassment, and sheep theft. Only twenty-four days after Artzenu’s post, Sharara himself led an operation to expel Palestinian shepherds from their grazing land.
A settler youth shepherds sheep from the illegal outpost of Havat Shorashim after trespassing on private Palestinian land. (E. A. Halevi / Jacobin)
When organizations like Artzenu and the JNF speak about “rehabilitation” and “reintegration,” they mean reintegration into the project of Zionist settlement and expulsion of Palestinians. Their “job training” refers to driving lessons, welding classes, and instruction in the skills for a shepherd to establish a new outpost. Those youths whom Artzenu convinces to serve in the Israeli military will likely return to their outposts as settler-soldiers, settlers operating with the authority of the IDF granted by a uniform and a rifle — a phenomenon I experienced firsthand when one notorious settler-soldier descended from his outpost above the village of Tuwani and, on a whim, detained me at gunpoint.
When organizations like Artzenu and the JNF speak about “rehabilitation” and “reintegration,” they mean reintegration into the project of Zionist settlement and expulsion of Palestinians.
As left-wing activist and chemist Yoram Sorek explained, “Hilltop youth are not a problem; they are a solution: a solution devised by the settler leaders to the problem of the presence of Palestinians in Area C.” As he puts it, “To that end, it is necessary to recruit those who can be trained for the task, especially those whom the system does not care if they are injured or killed in the process.”
Funding Illegal Settlements
While there are no public records of Artzenu’s revenue beyond its receipts from Shivat Tzion, its English-language website reveals that it also receives tax-deductible donations from the Boston-based 501(c)(3) the Ne’eman Foundation. In 2024, Canada revoked the tax-exempt status of the Ne’eman Foundation and the JNF for violating Canada’s Crimes Against Humanity and War Crimes Act through their funding of illegal settlement activities and the Israeli military itself.
Under Ne’eman’s CEO, Chaim Katz, who is now a resident of the notoriously violent settlement Shilo, the foundation brought in $6.2 million in 2024 to transfer to Israeli NGOs. Beyond Artzenu, those NGOs include a fund for Netzah Yehuda, a nationalist Haredi IDF unit, as well as the Beit Yatir Pre-Army Torah Academy in the settlement of Beit Yatir.
The Ne’eman Foundation is hardly the only such tax-exempt slush fund. The donation platform Jgive has US and Canadian tax-exempt status and is registered with the International Revenue Service at an address in West Jerusalem as “Friends of Asor Fund USA Inc.” Through Jgive, the Jordan Valley Regional Council, the regional government for Israeli settlers in the Jordan Valley, has raised millions of dollars to fund settlement activities, including $105,000 for security equipment for the settlement of Ovnat and $2.6 million to reconstruct a farm in the settlement of Mehola.
Colorado-based Christian Friends of Israeli Communities (CFOIC) transferred millions of US dollars to illegal Israeli settlements and outposts across the West Bank in 2022 and 2023, such as funds for security devices in Avigayil, whose residents took part in a recent pogrom against neighboring Palestinian villages in Masafer Yatta. PEF Israel Endowment Funds, Inc., which was placed under investigation by US House Republicans in 2025 for allegedly donating $18 million (some of which may have come from USAID) to a centrist anti–Benjamin Netanyahu NGO, gave out a whopping $263 million in grants, including to Reuta Beit Midrash for, once again, the purpose of supporting “at-risk youth.”
While the Leahy Law prohibits the US government from funding foreign security forces implicated in gross violations of human rights, there has been continuous reticence from both the Joe Biden and the Donald Trump administrations to apply pressure to the Israeli armed forces or settler infrastructure. Until that changes, organizations like Ne’eman and the JNF will continue to use American dollars to fund a system that conscripts sadistic and unstable teenagers like Dror into a vanguard of violence and dispossession against Palestinians.
E. A. Halevi
is a fellow at the Center for Strategic Politics and a member of the Democratic Socialists of America.
Jacobin Substack
features selected Jacobin articles, magazine highlights, and updates, alongside original writing and conversations on Substack Live.
I have done my fair share of tinkering. Poking around in servers and
fixing things
; iterating through and trying
different settings until
it finally worked
; not to mention clicking around in various cloud portals, only to realise I
have no idea how I ended up with the deployment I now have in front of me… “At least it works”, some might say and be
content, but not me. What if I need to do this again? Or what if something stops working and I don’t remember exactly
how things were configured and therefore cannot see
what
changed?! Documentation is good (when it’s accurate,
unambiguous, and kept up-to-date – which it seldom is) but do you know what’s even better?
$git log --oneline-1-- manifests/longhorn/backup.yaml
e958922 longhorn: write pollInterval as 5m0s so Argo stops self-healing
$git show e958922 -- manifests/longhorn/backup.yaml | grep'^[-+] '- pollInterval: "300s"
+ pollInterval: "5m0s"
The primary reason to automate something is not to save time, it is to codify knowledge and ensure reproducibility.
I think it’s still worth a read.
In this post, I want to expand on the idea of
what can be codified
by talking about
GitOps
.
GitOps
GitOps is the practice of running
everything you can
“as code”, by utilising best practices from software
development, and having an automated way of continuously reconciling the code in all aspects of a product’s tech stack
and life cycle.
According to me, that is… If you want a more formal definition,
OpenGitOps (v1.0.0)
boils GitOps down to
four principles.
The desired state of your system is:
Declarative
– A system managed by GitOps must have its desired state expressed declaratively.
Versioned and immutable
– Desired state is stored in a way that enforces immutability, versioning and retains
a complete version history.
Pulled automatically
– Software agents automatically pull the desired state declarations from the source.
Continuously reconciled
– Software agents continuously observe actual system state and attempt to apply the
desired state.
Most people talk about GitOps in the context of Kubernetes (and so will I) but you can (and should) absolutely apply the
above principles even if you don’t run your workloads in Kubernetes. All you need is something like this:
Note that the
Agent
above is not Claude Code or OpenAI Codex. In Kubernetes, the agent is often a tool like
Argo
CD
or
Flux
and the act of
reconciling your desired state
is handled by the agent running
kubectl
apply
,
helm upgrade
, or some more esoteric variant of these commands. But there’s nothing hindering you from writing
your very own agent, tailored for your specific needs. If you can describe your desired state in code, observe what your
actual state is, and figure out a nifty way to automate the reconciliation operation; you’re good to go!
Degrees of deranged
Naturally, you can do GitOps well and you can do it poorly. How well you succeed comes down to how precisely you
describe your desired state and how well you implement the three actions your agent will do. I do understand that I am
contradicting myself a little bit here, since I started this post saying that code is
unambiguous
, but stay with me as
I give you a (silly?) example showing four different ways to tackle principles 1 and 2 listed above: by ordering a
spaghetti bolognese (S&B).
Let’s say you want to run
Longhorn
in your Kubernetes cluster (and eat a nice plate of S&B at your
favourite restaurant). You can achieve this in many different ways:
The name of the chart (
longhorn
) is the dish, the repository (
--repo https://...
) is the restaurant. When you run
helm install
,
Helm
generates the manifests (recipe) for how to deploy Longhorn, using whatever defaults the
maintainers (chef) of the Helm Chart have decided, and applies it to your cluster. Once. Neither Helm nor the chef
sticks around to check what happens once they’re done cooking. Maybe you have conflicts in your cluster? (Or the waiter
has an accident walking the plate to your table.) And if you try to place the same order again, you’re told that you
already have one. The YOLO approach trusts that you’ll get what you want, and that you can order the same thing tomorrow
and be equally pleased, by relying on the upstream maintainers.
(OK. This analogy is becoming complex and it’s falling apart on the first example. Bear with me.)
# 2. YOLO, but with preferences
helm install longhorn longhorn --repo https://charts.longhorn.io \--namespace longhorn-system --create-namespace--values values.yaml
Now there are some options for you to consider. Some might have reasonable defaults (determined by the maintainer/chef)
and there might be options for which you must provide an input. If you save a copy of your choices you can bring it back
tomorrow and order the same variant of S&B. But what if the menu has changed? Unless the chef is unusually thorough
(i.e., the chart ships a
values.schema.json
), Helm silently ignores any option it doesn’t recognise. Ask for “extra
parmesan” after it has been renamed to “cheese” and you get no cheese, and nobody tells you why.
The third option is what I would consider
good enough
or
acceptable
. You now have the opportunity to say: “I want my
S&B to be made with these options and I want you to follow
version 1.12.1
of your recipe.” In doing so you can be
quite confident that you will get the same S&B every time you order! We also use
helm upgrade
which allows us to
“re-order” the same dish again, and again, and again, circumventing the “you cannot order twice” issue from examples 1
and 2.
Rendered Manifests Pattern
Good enough isn’t great, though. I propose you take this one step further, because there’s still room for
interpretation and for things to be modified. For instance, what happens if the chart generates a password using
randAlphaNum
? Every
helm upgrade
renders a new one, and your login is silently rotated. Or what
if the chart references a mutable image tag, like
latest
, or the maintainer re-publishes
1.12.1
with a “small fix”?
Your command is identical, but the result is not. And since
helm upgrade
renders and applies in a single step, you
never get to see the manifests before they hit your cluster.
This is why I encourage you to follow the
Rendered Manifests Pattern
. Nothing is applied from
a URL or using
helm
directly. Instead, every component is vendored into the repository:
Running
helm template
is like asking the chef for the exact recipe for the S&B. What ingredients? How much of each?
Exactly how to prepare and cook the dish? Naturally, you then ask the chef (the agent) to do the actual cooking… but
at least you have the instructions. If your dish all of a sudden does not live up to your expectations, you can compare
and see what changed from last time you ate it.
OK. I’m dropping the cooking analogy here…
The key takeaway here is that by running
helm template
we can extract the
exact
recipe – the verbatim Kubernetes
manifests – to disk, for inspection. In the snippet above, this is done using a
Makefile
so you can: bump the
version, run
make render
, then check
git diff base.yaml
to see what changed in the new upstream version. If you want
to make alterations to the manifests you can use
Kustomize
and ensure you do the same alterations, the
same way, to every new version of the application, and write the output to a file like
out.yaml
. Now you have
exactly
your new
desired state
and can run
git diff out.yaml
to see what your agent will reconcile towards.
I want to make it crystal clear though: The point is not the tooling. The point is that
the change you review and
commit should be the exact change that your agent runs
.
Keep on reconciling. Keep on reconciling.
The purpose of the continuous reconciliation in principle four is two-fold:
If there is a way to do manual alterations to your application, principle four ensures those alterations are not
persistent. The code
shall
always win!
If your agent observes that your application keeps diverging from its desired state, something is likely wrong with
your deployment.
The most recent case – in the very cluster I use for my own development – was when Argo was syncing
Longhorn
roughly 288 times a day, on a repository nobody had touched. It turned out that I had written
pollInterval: 300s
in Longhorn’s
BackupTarget
manifest. Longhorn parses that value and
writes it back in canonical form:
5m0s
. Argo saw drift on a field it owned and “fixed” it. Five minutes later Longhorn
“fixed” it back. Forever.
Without reconciliation, that disagreement would never have surfaced. I changed the
pollInterval
to
5m0s
in the
config and made my deployment just a little bit better. In this case it was not a big issue, but the point was still
made clear: GitOps doesn’t just deploy your config, it
audits
it. Constantly.
Bootstrapping
Regardless of whether you use a Kubernetes cluster or adhere to GitOps in another environment, there is a bootstrap
problem: Somehow you need to set up your agent, maybe some pipelines, and the environment itself. In the environments I
manage I talk about being
above
or
below
the GitOps line.
In the cluster I manage for my own business,
Talos
(my operating system of choice),
Cilium
and
Argo CD itself are
below the GitOps line
and therefore installed “by hand”. Technically, the bootstrapping could’ve
been to install Cilium and Argo
once
and then let Argo reconcile those deployments as well, going forward. I don’t
like that approach. I believe that the agent should not be able to break itself (at least not too easily) and therefore
I refrain from having the agent manage things that are part of its own bootstrapping.
Naturally, I don’t just wing the bootstrapping! Here’s the
Makefile
in my
bootstrap/
directory:
Whenever I want to make a change to Cilium I update the
Makefile
, I render the manifests, I diff them against
main
,
and if everything is to my liking, I run
kubectl apply
. I want to adhere to the GitOps principles as much as possible,
even when I don’t let an agent be in charge of the reconciliation. The price is that principles three and four no longer
hold below the line: nothing pulls, nothing reconciles, so if someone (me) fat-fingers something, the cluster drifts
from
main
and stays that way until the next time I apply.
GitOps has a cost
As with all things that are worth doing, there’s a cost. And as always, the result you get is a function of what you put
in. If you
YOLO
your deployments and ask for
whatever S&B the chef feels like making today
, you might get a tasty
dish, but you will most likely not get the same dish twice; nor will you know what’s in it. Determinism is
imperative. If you follow the Rendered Manifests Pattern you must put some effort into ensuring two consecutive renders
are identical, or the pattern falls apart.
I’m hesitant to say that there’s a learning curve to using GitOps or even the Rendered Manifests Pattern. Sure, you need
to write code to do the actual rendering and you need to set up the agent – so there is
work
that needs to be done –
but the pattern ultimately asks you to use
simpler primitives
: plain, easy-to-read Kubernetes manifests as opposed to
complex Helm charts. But I shall not shy away from the fact that there are more pieces to lay. The huge benefit is that
the pieces stay where they are once you’ve placed them.
(Yet another analogy? Well…)
All I can say is: It is not only worth it, it’s a necessity once your environment becomes even slightly complex.
Conclusion
So,
why is GitOps so good
?
The short answer is: Because code, when written well, is unambiguous, and ambiguity has no place in software life
cycle management.
The longer answer is that being able to reproduce your entire tech stack (like a Kubernetes cluster)
and every
setting, policy and application inside of it
is amazing, and having an agent that constantly audits that it stays that
way is even better. Pair GitOps with a good backup strategy and you have the foundation for an excellent disaster
recovery plan. I have backup jobs (as code, naturally) and jobs that verify my backups (also as code,
duh
) running
regularly. If my cluster were deployed on a virtual platform, I could have everything up and running, and data read
back from off-site backups, in a matter of hours. Can your business do that? If you need to get people to keyboards and
start installing stuff by clicking around, you probably cannot.
BTW:
I plan a post on the topic of
observability
, which is one that I hold as dear as I do GitOps. Keep your
eyes peeled!
E-graphs have enabled recent advances in program optimization, synthesis, and verification, yet remain difficult to apply to effectful programs whose memory and I/O operations must respect execution order. Existing effect-aware extraction algorithms rely on integer linear programming (ILP) and dominate total runtime. We introduce statewalk DP, a new extraction algorithm that enforces effect ordering efficiently without external solvers. We prove that finding any effect-safe extraction is NP-complete, but show that statewalk DP is tractable in statewalk width, a parameter that measures the complexity of dataflow interactions among effects. In practice, statewalk width generally remains small, enabling statewalk DP to achieve order-of-magnitude speedups over ILP extraction while producing programs comparable to LLVM across our benchmarks. We implement the algorithm in eggcc, a prototype e-graph-based compiler for imperative Bril programs, and demonstrate that effect-aware extraction is no longer a bottleneck.
BibTeX
@article{2026-oopsla-eggcc,
author = {Flatt, Oliver and Pal, Anjali and Zhang, Yihong and Tjoa, Ryan and Graham, Kirsten and Fischman, Alex and Nandi, Chandrakana and Rosenthal, Eli and Tatlock, Zachary and Ni, Haobin},
title = {Efficient Extraction for Effectful E-graphs},
year = {2026},
month = oct,
journal = {Proceedings of the ACM on Programming Languages},
volume = {10},
number = {OOPSLA2},
articleno = {398},
numpages = {28},
publisher = {Association for Computing Machinery},
url = {https://doi.org/10.1145/3839530},
doi = {10.1145/3839530}
}
For over 20 years, Linux has been used everywhere, from servers to embedded devices. One area it has been lacking in, however, is the desktop space. Windows and macOS have constantly been keeping Linux out of the market, with gaming primarily being a Windows thing and content creators utilizing macOS.
Over the last decade, the Linux desktop has been improving dramatically: Flatpak, Wayland, Portals, PipeWire, and FreeDesktop have all been working to make Linux an operating system better suited to modern (desktop) systems. I'm not going to go over all of those though; as you could probably tell by the title, this is going to be about
Flatpak!
History
Let's take a quick look at the server space. It's not uncommon to see them running decade-old (sometimes even
decades
-old!) kernels and libraries. This makes sense, as their boot times are long and on every single system update, there's a risk of breakage, and needing to debug that; valuable uptime lost, especially for a service as large as Google. Naturally, they evolved a way to quickly patch the most relevant parts of the system, so security isn't too much of an issue.
However, the software they run may only be able to utilize newer features from newer libraries, not the old and crusty software the servers run. So how did they solve that?
Containers. Normally used to ship software to several customers in a consistent and safer way, they allow you to isolate software into a little box with all of the needed dependencies, at their specified versions, with limited access to the host system.
The present
We have Android, macOS, and iOS, all with limited access to the system, requiring end-user intervention to access certain resources. But what about the Linux desktop?
In 2015, Flatpak was released, taking all of the technology used from containerization on servers, and applying it to desktop systems. With it came
Portals
, and the
Freedesktop SDK
. This gave a consistent and generic platform and API to developers, a drastic change from what was previously a battleground of varying dependency versions, core system libraries, and packaging formats.
Of course, after having the distribution and development situation stay the same for a few decades, this was too large of a change to make at once. Many of the needed APIs exist, but developers need to take time out of their day to migrate to them, and some users (specifically, Flatpak-hating ones) vehemently refuse to help improve the situation, insisting we stick with the old way of doing things, and repackage software hundreds of times for thousands of varying systems.
To put it simply, naturally, nobody in their right mind gave a shit. Many new application developers are creating their apps with a confined environment in mind, and shipping their software to Flathub, allowing the software to get to end users in a fast and secure way.
Application confinement
What about the old applications, though? You can find 10-year-old apps shipped on Flathub, after all. From these applications spawned articles such as
Flatpak - a security nightmare
hey, you might recognize that name!
, and various
responses from well-known individuals
within the FOSS space intended to counteract misinformation and aggression from those articles.
For these apps, the FUD (fear, uncertainty, and doubt) articles like to cherry-pick the worst offenders and use this to say that Flatpak isn't worth pushing for at all. So I'd like to address that.
These applications were designed with an unconfined environment, and the APIs necessary for them either didn't exist at the time or they weren't updated to use the new API. Cherry-picking them to show that the Flatpak sandbox is
"not a sandbox"
is not a valid argument, and only shows that the applications themselves are insecure.
Of course, older apps aren't the only offenders. As the new APIs might not be mature enough, both newer and older apps may have to resort to
static permissions
in order to work properly. For most newer applications, this is fine, as they can restrict their permissions a
lot
more than older applications would be able to.
Flatpak
is
a sandbox. And
Flatpak
is
secure. The
applications
are not
. It doesn't help anyone to change the meaning of the word "sandbox". Just because the sandbox that some apps use isn't on par with iOS or Android, it doesn't disqualify it as a sandbox. If you'd like to blame Flatpak for that,
don't
be my guest. The fact that the apps rely on static permissions shows that the applications are insecure and rely on inconsistent interfaces, and in some cases, that the
current APIs have yet to improve enough for their use cases
. We should be focusing on improving that situation, not trying to tear it down.
If you want a real-world example of how a partial sandbox is still effective:
the "fractureiser" malware
. Even if the malware was nonfunctional on Linux in the first place, it's still an example of how traditional packaging fails to address the fact that modern desktop systems have plenty of ways for a system to be compromised. Running software "that you trust" isn't enough to protect yourself. To quote the relevant notes from the linked post:
If you use Linux, use the
PrismLauncher Flatpak
and be very careful of what you give it access to through utilities such as Flatseal. By default, it has no access to the needed directories to compromise the system.
Taking a quick look over the decompiled source code, it will indeed fail to function inside of the default PrismLauncher Flatpak sandbox; the current malware hardcodes the user's ~/.config/ directory. The creation of files inside of the Flatpak sandbox, if the app does not have access to that real path, will result in it being written to a tmpfs that gets wiped on a sandbox restart. systemd is also not available inside of the Flatpak sandbox, so executing that command will fail. The malware seems to not attempt to work around these limitations, and assumes it is running unsandboxed.
Some also like to bring up outdated dependencies to the argument. No, this doesn't matter. The runtime itself is updated whenever a needed security update is available (sometimes even
breaking the ABI
if it's a big enough deal) and application developers don't have to think about manually updating bundled dependencies with
automatic update checking
. And many major libraries, such as your GPU drivers, can be updated separately from your runtime if you so choose. Outdated dependencies isn't even an argument in the first place.
In the event an application
does
use outdated libraries, be it because an update broke the build process or the developer forgot to set up the data checker, there is the sandbox placed around all Flatpak applications that can help mitigate these issues while the developer addresses them.
The future
The hope is for the Linux desktop to migrate to developer- and more sandbox-friendly methods of software distribution and programming. We've already made great strides with PipeWire, which paves the way for
many
nice features with audio and video (including several apps using your camera at the same time!), and FreeDesktop, but we undoubtedly have a ways to go before Linux is a viable platform for developers to target and ship software to.
We can't move forward without modern software like Wayland and Flatpak, no matter how much one might want to repair the situation with Xorg and traditional packaging. If we keep trying to revert to the old way of doing things, all that's shown to developers is that Linux isn't a platform worth considering, and it ends up being a worse situation for end users; turning back into a "which came first: the chicken or the egg?" situation, and resulting in a
very
bad UX.
We don't want that happening.
More reading
If you want more information on Flatpak and in general more information on how it works and the current situation, the following articles are worth a read:
‘No influencers’: the hotels, restaurants and beauty spots restricting photoshoots
Guardian
www.theguardian.com
2026-10-19 00:00:19
Backlash against content creators includes restricted hours for filming and even outright bans Stand in any vaguely photogenic spot these days on holiday and the chances are you will come across people posing with raised phones and even ring lights. Some may be influencers with huge audiences on soc...
S
tand in any vaguely photogenic spot these days on holiday and the chances are you will come across people posing with raised phones and even ring lights. Some may be influencers with huge audiences on social media, others just overkeen
Instagram
users. With hotels and beauty spots now so overrun, however, bans on photography are coming into place.
The five-star Hotel du Cap-Eden-Roc in Antibes, known for its glamorous clientele, views of the Côte d’Azur and a stunning infinity pool, has brought in rules against photoshoots: no longer allowed without prior permission.
According to
reports
, this has been prompted by people booking lunch reservations and bringing bags of clothing and jewellery. Instead of sitting down to eat, they have used their time at the hotel for photoshoots of themselves in different outfits, creating images to post to their social media accounts.
The Hollies farm shop in Cheshire has banned photography and filming between 10am and 4pm.
Photograph: chasephoto/Alamy
Less glamorous spots are also clamping down. The Hollies, a Cheshire farm shop which has become a popular content stop thanks to the Love Island star Molly-Mae Hague posting images from there, has banned photography and filming between 10am and 4pm.
Meanwhile Jeremy King, the London restaurateur behind places such as
Simpson’s in the Strand
and
the Park
, wrote
an article
in the Evening Standard earlier this year titled: “I’m fed up with influencers over-running my restaurant – enough is enough.”
In the US, a shop on Nantucket, an island off Cape Cod, Massachusetts, went viral earlier this year for a sign reading “no influencers”, while the town of Pomfret in Vermont has banned influencers taking pictures in front of foliage in autumn. In Fujikawaguchiko in
Japan
, a screen has been put up near a convenience store to stop people taking pictures there in front of Mount Fuji.
Part of the argument from venues is that these photoshoots jeopardise privacy and discretion, especially as expected at expensive hotels. Hotel du Cap-Eden-Roc’s manager, Sophie Volant, told
Travel Weekly
: “As much as [guests] appreciate having people in the restaurants and in the bars, they also want their summer home to remain private. We had to think about a solution.”
Anna Fedou, the chief marketing officer at the Beaumier hotel group, says it sometimes works with influencers to capture content to promote its luxury hotels, which include Les Roches Rouges near Marseille, loved for its photogenic pool. The group does not have specific rules around photography, Fedou says, but stays mindful of its primary purpose.
“We’re in the business of hospitality, not running photo studios,” she says. “People travel from all over the world to experience the atmosphere, sense of space and feeling that make a hotel unique. It’s our responsibility to protect that.”
Rules around photography at hotels and restaurants mirror a trend away from capturing the moment and towards being in it. Alex Goat, the founder of the youth culture agency Livity, compares these rules to clubs asking visitors to put stickers over their phones’ cameras. “They want to signify that they’re here for people who love music. There’s something potentially similar [here],” she says. “It’s ‘I’m here because I want to enjoy the space’ rather than ‘I’m here to document something to other people’.”
Sleepy Hollow Farm in Pomfret, Vermont. The town of Pomfret has banned influencers taking pictures in front of autumn foliage.
Photograph: Michael McCormack/Alamy
Part of the disapproval towards influencers is a common misconception is that they are paid well for such content. Sometimes, as with Beaumier hotels, influencers will produce posts in exchange for a free room, but the idea is that brands will want to make deals with influencers due to their association with glamorous locations. “The majority are creating most of their content for their audiences for free,” explains Nicole Ocran, an influencer who set up
the Creator Union
to represent those in the industry. “They create content in the hope of courting brands and seeing who will bite.”
There has been previous outrage around influencers’ behaviour, as
in 2021
when Love Island stars travelled to Dubai during lockdown, for example. And if there is an underlying snobbery to a luxury hotel instigating anti-photoshoot policies, there may be sexism, too. “Influencer culture has always been vilified in popular culture,” says Sophie Bishop, the author of
Influencer Creep
. “It’s a very feminised form of media, that’s bound up in promotional culture.”
Ocran agrees. “Most people have a particular stereotype in mind,” she says. “That isn’t to say that influencers and content creators can’t overstep or be insufferable when getting their shots and filming in public.”
A screen was erected to block the view of Mount Fuji from outside the Fujikawaguchiko Lawsons convenience store after tourists crowded the area to take photographs.
Photograph: Franck Robichon/EPA
Fedou believes that the key is to walk a balance that engages with social media content while keeping a restful experience at hotels. “Influencers will generally choose quieter moments for shooting content, to capture the space without disturbing others,” she says. “Les Roches Rouges has a relaxed atmosphere, but guest experience always comes first.”
Ocran hopes that rules around photography might promote a more balanced attitude to social media in general. “[It’s] pushing back against the idea that not every space is meant for public consumption, and not every experience should be turned into content,” she says. “And as a creator, that’s quite a healthy message to send to us all.”
Recently, while troubleshooting a
PATH
issue, I noticed an entry for
/pkg/env/global/bin
. At first, I worried that something had gone horribly wrong. Turns out, this is part of macOS 27.0… though no one is sure what it’s for yet.
First, some background. Since Mac OS X 10.5 in 2007, the OS has included a
path_helper
utility. This reads entries from
/etc/paths
as well as from any files in the
/etc/paths.d
directory. While one could potentially take advantage of this system, I (and I’d guess most others) handle adding new PATH entries using the
.zshrc
file
, or similar. The
path_helper
utility seems to be primarily used by Apple.
In macOS 10.15, an entry was added to
/etc/paths.d
to support the new location of the
rvictl
utility
. In macOS 13.3,
Apple added some new entries
to support
Cryptexes
. Now in macOS 27.0, there’s a new
10-pmk-global
file
1
which adds
/pkg/env/global/bin
to the PATH list.
I only started digging into things when I noticed that entry. I assumed something had gone awry. Then I saw that there was, indeed, a
/pkg
directory in the root of my filesystem. After freaking out slightly, I fell down this rabbit hole.
The weird thing is, as far as I can tell, no one seems to know what this new directory is for! It’s odd that Apple would update their filesystem structure, add it to everyone’s PATH, and there not be some explicable reason.
The
/pkg
directory contains four subdirectories:
env
,
etc
,
inv
, and
var
. Based on its name and those subdirectories, it’s possible this could be used for an upcoming first-party package management system — but this is a wild guess. Apple recently
took over the Swift Package Index
, but this seems unrelated. I don’t know why you’d need a root-level directory to help with project-level dependencies. It’s also not clear what the “pmk” in
/etc/paths.d/10-pmk-global
refers to.
2
Here’s hoping we get more details on this at some point. In the meantime, maybe these details will help prevent someone else from freaking out when they see this entry in their PATH.
When designing software, the requirements you don’t have are as important as the requirements you do. Identifying what you can compromise on — what can be slow, or stale, or inflexible — is usually the key to an elegant design.
Elegant systems drop some requirements
For instance, take preforking web servers like
Unicorn
. Because they lack the feature of shared mutable state between server instances, they can run each server in its own process, which provides isolation for free. Because Unicorn specifically ignores the problem of slow client handling
1
, it can queue requests directly on Unix sockets, drastically simplifying the implementation.
Because
S3
does not support atomic multi-key updates — you cannot update multiple blobs in a single transaction — it can store data at the blob level however it chooses. That makes it much faster, since reads and writes don’t have to cross storage partitions, and much easier to scale, since less coordination means fewer sources of truth.
StatsD
uses UDP by default, which means it doesn’t guarantee that every piece of data you send makes it into storage. In exchange for dropping that requirement, it incurs much less network overhead, which is a big advantage for a stats aggregation service that’s constantly shoveling data over the wire.
The general design approach of fanning out data to an edge cache buys a lot of speed and scaling by dropping the requirement that data must always be up-to-date.
SQLite
buys operational simplicity — it can run out of a single file! — by dropping the requirement of concurrent writes. By accepting
high tail latency
2
, Cursor can scale their distributed git backend more easily. Well-designed systems turn their weaknesses into strengths.
Why dropping requirements is hard
Anyone who’s spent time designing real-world software (or who’s studied
distributed systems
) knows that system design is a process of compromise. If you attempt to satisfy every single potential requirement — speed, concurrency, up-to-date data, a simple interface, supporting complex user behaviors — you will fail to design a working system at all.
Figuring out what requirements you can relax is difficult because
it combines both business and technical expertise
. It is technically challenging to identify precisely the level of staleness that a particular design change will allow; it is likewise challenging from a business perspective to determine whether that level of staleness is acceptable to users.
In most cases, an engineer who understands the technical side must try and explain it to a product manager, who can make a judgement on the business side. But this is a very difficult partnership to get right. Engineers and PMs have different incentives and little ability to check each other’s work, which makes it hard to
build trust
. Without trust, the product manager is liable to avoid giving any ground at all
3
, which leaves the design in an impossible state.
This is an underappreciated reason why solo developers or startups can sometimes run rings around larger companies. Because the technical and business decisions are united in a single person, they can make design tradeoffs that would be impossible for a large company, enabling them to build systems that are far more elegant and powerful.
Working with LLMs
Knowing what requirements you don’t have becomes far more important when working with coding agents. Frontier models are very capable, but they have all gone through the purifying flames of
RLVR
: like high-achieving schoolchildren, they are obsessed with satisfying the Grader. On top of that, they have very little business context compared to an experienced human. That often manifests as them catching correctness or consistency “bugs” that are really just hypothetical unsatisfied requirements.
For instance, it’s not uncommon for an LLM to casually introduce a mutex or other concurrency mechanism to ensure that two pieces of semi-related data are kept in sync, even if not told to do so. I’ve seen LLMs add weird checks in the middle of request handling to ensure that some already-checked piece of data hasn’t changed mid-flight, even if that wouldn’t successfully prevent the feared
TOCTOU
bug
4
. LLMs are obsessed with edge cases like “what if the current user loses their admin status in the middle of us handling one of their admin requests?”
5
, or “what if the cache in storage partition A is updated a nanosecond before the one in storage partition B, leading some users to see different data?“. Particularly if run in a loop or told to “make no mistakes”, they will pile on cases like these until they’ve transformed your four-line change into a thousand-line monster.
This is why I’m confused by some people’s claims that
code review is dead
. About half the time I review a large AI-generated change, I notice some unnecessary requirement that makes the diff more complex. When I dig deeper, the LLM invariably introduced this requirement on its own.
When working with a cache, I will often spell out in my prompt that I don’t mind the data sometimes being stale or briefly inconsistent between cache instances. When reviewing Golang code, the first thing I do is scan for added mutexes or layers of indirection that don’t look necessary to me.
If you allow requirements like these to propagate unchecked through a codebase, they will petrify the system over time. The whole thing will be such a mess of checking and re-checking and holding locks and enforcing consistency that it cannot be scaled at all. Keeping systems elegant requires a ruthless focus: on accepting stale data or occasional tail latency, on avoiding all but critical instances of coordination, and in general on figuring out what requirements you
don’t
have to satisfy.
Here's a preview of a related post that shares tags with this one.
The VT100 terminal, launched in 1978, was DEC’s first ANSI-compatible terminal and their first that moved from discrete logic
to a microprocessor, the Intel 8080. Slight modifications to the supported escape sequences were made for the cost-reduced
follow-on models, the VT101 and VT102, and those changes became the definition of “VT100 compatible,”
in DEC’s internal
Video Systems Reference Manual
, used for the next 15 years.
This set of documents takes the original 8 KiB firmware for the VT100 and attempts to explain the workings. There is a fully annotated disassembly with links to the Technical Manual and the print set.
Why I built superlite, an autonomous build workflow for Claude Code that doesn't ask permission every four minutes: how it works, how to use it, and the benchmarks.
I had a dream. I would hand an agent a spec, close the laptop, make a sandwich, and come back to finished, tested, committed work.
Here's what actually happened. I handed over the spec. I made the sandwich. I came back. The agent had written one paragraph and was asking, very politely, whether I approved section 1 of the design.
I approved it. I sat down. I waited.
Section 2. Approve? Yes. Section 3. Approve?
Yes.
The spec? Yes. The plan? Yes, obviously, it's the plan I just watched you write. And how would I like the plan executed?
However is fastest, please, I beg you.
Then it started building. One task. Then a review of that task. Then a fix for the review. Then a re-review of the fix. Then the next task. I watched a progress log scroll past like a train at a level crossing: no stopping it, no getting past it, and no idea how many carriages were left.
I'd refresh the terminal. Still on task 3. I'd answer an email. Still on task 3. I'd start a second sandwich purely to have something to do with my hands. Task 4, under review.
The sandwiches were very good. The software didn't exist yet. And the worst part wasn't the time. It was that I couldn't leave. Every time I walked away, I came back to a question that had been sitting there for twenty minutes, waiting for me to type "yes."
I didn't want a collaborator that needed me every four minutes. I wanted a contractor. Here's the spec, here's the key, call me when it's done.
So I built
superlite
: a Claude Code plugin that plans a build, splits it into tasks that can run side by side, hands each one to the cheapest agent that can do it well, checks the seams between them, and reviews the result. Then it leaves you a tidy list of every decision it made while you were busy with the sandwich.
This post covers why it exists, how it works, and how to use it. The benchmarks are there to show I'm not just saying it's fast because I wrote it.
Why I built it
First, a disclaimer, because I like this project and don't want angry emails. I use
superpowers
a lot. It's a careful, collaborative workflow that keeps a human close to every step, and it's genuinely excellent at that. Superlite borrows its bones shamelessly: the plugin layout, the session-start hook, the lifecycle skills. Credit where it's due, and then some.
But when I already knew exactly what I wanted, most of the time went on the workflow waiting for itself. I profiled it, the way you'd check your bank statement after a suspicious weekend. The time went to five places:
8–12 human gates per feature.
One question per message, designs approved section by section, then separate reviews of the spec, the plan, and the method of executing the plan. It's very thorough. It's also how a four-hour meeting gets scheduled.
Strictly sequential execution.
One implementer, then one reviewer, then the next task. On my first benchmark that was a single-file queue of 21 dispatches, like a bank with one teller and a very long lunch.
A review after every task, with re-review loops.
About 12 minutes of a 34-minute build.
The full test suite, re-run by several skills.
In case it changed its mind.
Opus subagents on the critical path,
writing code at about half Sonnet's speed. Brilliant, thoughtful, and in no hurry whatsoever.
None of these are mistakes. Each one is a sensible safety net. Stacked together, they're perfect when you want to steer every step, and slightly maddening when you just want the thing built.
So
superlite
isn't a rival to superpowers. It's tuned for a different job:
autonomous development, at speed.
If you want to steer each step, use superpowers. If you want to hand over a spec and come back to working code, use
superlite
. Just don't enable both in the same session. They share skill names, both inject context at startup, and they argue like siblings in the back seat.
How it works
The short version: one approval, a plan written for parallelism, agents matched to the work, and rules enforced by code because, as it turns out, agents read the rules and then do what they like.
flowchart LR
A([Your request]) --> B[One batch of questions]
B --> C[Plan]
C --> D[Agents build<br/>in parallel]
D --> E[Review and fix]
E --> F([Done])
One batch of questions, one approval.
Superlite sizes the request first. A typo just gets fixed, without a design document about the typo. A change to an existing flow gets a short design in chat. A new project gets one batch of up to four questions, then one design-and-plan document. You approve it once. After that it only stops for things that are destructive, outward-facing or security-sensitive. It won't push to
main
while you're getting lunch. It will do everything else.
You choose who's in charge.
With a human orchestrator, you see the whole plan with its predicted schedule and approve it before anything runs. With an AI orchestrator, you're not needed at all, which is either freeing or mildly insulting depending on your mood. Every choice it would normally ask about gets recorded as a ruling: what it decided, why, and what it costs if it got that wrong. When you come back, you know exactly which decisions to second-guess first.
A plan written for the split.
The plan is a task graph. Each task lists the files it owns, the exact interfaces it consumes and produces, and the tests it has to pass. Tasks that don't share files and don't depend on each other run at the same time. The graph decides how wide the build goes. On the current benchmark that peaked at 18 agents working at once, which is roughly the size of a small startup, minus the ping-pong table.
Agents matched to the work.
The org chart:
Opus coordinates.
It plans and dispatches, and it is not allowed to touch the code. Management, basically.
Sonnet builds
most of the tasks.
Haiku builds
only small, fully specified "mechanical" tasks that aren't on the critical path. The intern gets the well-defined stuff.
Sonnet reviews
the packages.
A fresh Opus final reviewer
reads a review packet built from the run's logs and returns findings only. It's never allowed to fix anything. It just points.
Fix-only agents
in three tiers take those findings, routed by how well the cause is understood.
Gated by code, not by prompts.
I learned this one the hard way. You can write "the coordinator never edits code" in a prompt in bold, in capitals, with feeling. The coordinator will read it, nod, and edit the code. So now hooks enforce it. One hook blocks the coordinator from editing project code. Another catches any raw
pytest
or
npm test
it runs and quietly turns it into a background run, so tests never block it. Another refuses to let anyone kill processes by name (there's a story there, and it's in the deep dive). A plan has to pass
lint --stable
before work starts, and stable tasks are sent off the moment it passes.
Every run is measured.
Hooks record each agent's tokens, cost and time. That feeds the next run's predictions and a soft budget that taps you on the shoulder at 70% of the cap.
How to use it
You'll need Claude Code, git, Python 3.10 or newer (for superlite's own tools; the project you build can be in any language), and bash (Git Bash on Windows).
The source is
iha2/superlite
on GitHub. Install it from the marketplace:
Or clone
iha2/superlite
and load a local checkout for one session:
claude --plugin-dir <path-to-superlite>
To check it's working, open a fresh session and send
Let's make a react todo list
. A working install starts brainstorming before it writes any code. It's the "hello world" of agent workflows, and honestly the world doesn't need another todo list, but it's a good smoke test.
Then:
Describe what you want.
A paragraph or a spec file is enough. No need for a 40-page requirements document. Although it will read one.
Choose the orchestrator
when it asks: you check the plan, or the AI does everything.
Let it run.
Watch
.superlite/
in your project like a nature documentary.
progress.md
has the rulings and the log,
test-summary.json
has the latest test result, and
metrics.jsonl
has the time and cost per agent.
What you say shapes the flow:
Situation
Say something like
A new project
"Build me a static site generator from this spec"
A feature on existing code
"Add CSV export with column widths to the existing app"
Debugging
"This test fails on leap days: find the root cause and fix it"
A small change
"Rename
build
to
render
everywhere"
Hands off
"Build X. I'm away, decide yourself"
Shipping
"We're done: finish the branch"
It never pushes or merges without you. Autonomous, not reckless.
Does it actually work?
Anyone can call their own tool fast. I once called a script I wrote "blazing" and it took eleven minutes to rename some files. So every number below comes from a headless benchmark harness. It builds the same project from the same spec, on Opus, and scores the result with a hidden test suite the agents never get to see. No peeking, no studying for the exam.
The latest run: 16.1 minutes
The test project is deliberately not a todo list. It's a static site generator
plus
a spreadsheet engine (formula evaluator, HTTP API and a browser UI) built as one project from one spec, and scored by 177 hidden tests.
Here's the latest run, on the current build:
Wall-clock, spec to finished build
16.1 min
Hidden tests
177 / 177
Agents
21 in total,
up to 18 working at once
First agents building
about 3 minutes in
Final review
30 seconds
Stops to ask a human anything
0
Compared with superpowers on the same project:
Wall-clock
superpowers, stock (mean of 3 runs)
33.6 min
superpowers, orchestrated (mean of 3 runs)
23.5 min
superlite, latest run
16.1 min
52% less time
than stock,
31% less
than orchestrated
Same 177 out of 177 hidden tests, in about half the time. That's one run of the current build against earlier runs on the same machine, so call it a strong hint rather than peer-reviewed science. But it's a very strong hint.
It also beat its own previous build (which averaged 26.9 minutes) by 40%. Yes, I'm competing with my own past self. It's the only rival I can bully freely.
How it got there
The latest run didn't come out of nowhere. The first build was already quick on a smaller task:
sitegen
alone, nine modules, 89 hidden tests.
superpowers
superlite
Wall-clock
34.4 min
8.8 min
Hidden tests
89 / 89
89 / 89
Serial dispatch chain
21 dispatches
3 levels
Most of that speed came from getting rid of the queue. Superpowers dispatched 21 agents, one after another. Superlite dispatched 10, up to five at once. Same work, fewer people standing in line.
On the full 177-test project, an earlier superlite build ran three times against superpowers:
superpowers
superlite
Mean wall-clock
33.6 min
25.1 min
Runs
21.2 / 31.9 / 47.6 min
21.4 / 23.2 / 30.5 min
Spread, fastest to slowest
26.4 min
9.1 min
Hidden tests
177 / 177 every run
177 / 177 every run
Faster on average and much more predictable. A 47-minute worst case is the difference between "done before standup" and "done after standup, during which you had to say it's nearly done."
But the data also showed where superlite was still waiting on itself. The build was finishing at about 13 minutes, and then 10 to 18 more minutes went on reviews, fixes, and the coordinator running tests in the foreground and staring at them. So:
The coordinator lost the ability to edit code.
It took it surprisingly well.
Every test run moved to the background.
Fixes went to tiered fix-only agents.
Stable tasks started building while the rest of the plan was still being fixed.
That's the build that ran in 16.1 minutes.
The takeaway
If your agent workflow is slow, it's probably not slow because the model is thinking deep thoughts. It's slow because work is waiting in a line, and something keeps asking permission.
Split the work along interface boundaries. Let independent tasks run at once. Move the mechanical steps into scripts. And enforce the rules that matter with code, because asking nicely only works on people, and only sometimes.
In the follow-up post I go much deeper into the philosophy and the decisions behind superlite: the gates, the agent tiers, and the graveyard of ideas I was very confident about right up until I measured them.
Chicago O'Hare digs up 50-ton boulder under airfield, asks public for name ideas
Body camera footage obtained by 404 Media reveals the first Flock camera searches ruled unconstitutional by a federal judge, and highlights how the system has turned otherwise mundane traffic stops into interrogations for drivers.
On Friday, we reported
that a federal judge ruled the use of license plate reader systems in the arrest of a woman named Melissa Kyle to be an “unconstitutional warrantless search,” “indiscriminate mass surveillance,” and a violation of the driver’s Fourth Amendment rights. The judge in that case ruled that, even though Kyle had more than 91 pounds of meth in her vehicle, the police had no justifiable reason to search Flock for her license plate and no reason to suspect that her travel as shown on Flock’s system was suspicious. Therefore, all of the evidence from Flock and the search of her vehicle must be thrown out.
0:00
/
2:51
The body camera and in-vehicle footage, alongside records from Flock and the Motorola ALPR system obtained by 404 Media shows how the use of license plate reader systems is being used to create probable cause where a person’s driving patterns are suspicious enough to pull them over.
404 Media obtained the footage with the help of one of our readers, who agreed to go to the U.S. District courthouse in Tulsa and purchase it from the clerk; the court did not make the footage available online even though it was entered as evidence in the case.
In the footage, which is from Tulsa County deputy sheriff Freddie Alaniz’s body camera, Alaniz is seen driving 60 miles per hour, one hand on the steering wheel, one hand on his laptop, searching Flock before he had even fully pulled over Alaniz. Alaniz had seen the car Kyle was driving had California license plates, and decided to pull it over for no reason other than it was from California, the court determined. The video shows that Alaniz told his colleagues that he was sitting on the highway and “saw her go by, and I just started running her info on Flock and Vigilant [Motorola’s ALPR system].”
“She actually didn’t have any [Flock] hits until just west of Amarillo, [Texas], so I thought I’d drive up,” he said, suggesting that he thought it was odd she was driving back from California. “I got her for a lane violation.”
In the footage, Alaniz tells Kyle he pulled her over ostensibly for changing lanes without a turn signal. Kyle tells Alaniz that the car is a rental, and he asks her to step out of the vehicle and get into his car while she looks up the rental information. While she is looking up the rental information, he tells her she is only going to get a warning, but proceeds to interrogate her about the travel while going through the car’s driving history on his in-car laptop.
Body camera footage obtained from the court
In-car footage obtained from the court
Kyle told Alaniz she had been visiting family in California from Missouri for a few days after separating from her husband. As she’s telling him this, Alaniz scrolls through a record of her travel history on his in-car laptop, which documents every time the car passed a Flock or Motorola automated license plate reader camera over the last 30 days. Visible on the screen, there are a total of 79 hits, and roughly 50 during the few-day period Kyle was renting it. The ALPR hits show the car leaving Missouri, driving through Oklahoma, Texas, New Mexico, Arizona, and entering California when she passed a Motorola ALPR camera in Topock, Arizona, on the border with California. They then show her essentially reversing the route, and driving back through Oklahoma. (Alaniz did not have access to ALPR hits from California; this may be because Flock drastically limited nationwide sharing from California ALPR cameras following illegal searches for immigration violators and a woman who had an abortion.)
Alaniz asks Kyle where she’s been and where she stayed, and compares it to the license plate camera records. He begins quizzing her: “Do you remember what day you left Missouri?,” he asks.
Alaniz clicks different ALPR hits on his map, each bringing up a photo of her car, a geographic location, and a timestamp of when she drove by the camera. The government’s lawyers later argued in court that minor discrepancies between what Kyle told Alaniz and what the ALPR data showed meant she was lying about where she’d been on which specific days and therefore gave Alaniz probable cause to search her vehicle.
Alaniz tells Kyle that he is giving her a warning for changing lanes without a turn signal, closes his laptop, then says he wants to ask her a few questions.
“Your short trip to California, I feel like. I don’t feel, I know from my training and my experience that people who do very short trips to California and come right back are transporting large amounts of drugs,” he says. “People who do that—not everybody, but some people do. With my training and experience, I feel that may be something going on here. May I search your car?”
She says no. Alaniz calls for backup, and says “You are being detained. You are not free to go.” In the footage, Alaniz tells a colleague that “she went to California for two days, kind of making stuff up when I ask her where she stayed at.”
He used Alaniz’s travel history, her “nervousness,” and the fact that she doesn’t recall every detail of her travel precisely as probable cause to search her vehicle, where he and his colleagues found 91 pounds of meth. Alaniz described this in the footage as “a motherlode,” and “a shit-ton of meth.”
But the way that he came to this conclusion was unconstitutional, U.S. District Court Judge Sara Hill ruled last week, and all of the evidence—including the car’s travel history and everything the police found during the search of the vehicle—must be disregarded in court as “fruit of the poisonous tree.”
It is often the case that unconstitutional, privacy-violating searches that are regularly done on everyday people doing nothing wrong are discovered in court cases in which serious crimes have occurred. In this particular case, Alaniz discovered what appeared to be meth trafficking, but he did so only after suggesting that an ordinary interstate travel pattern was somehow suspicious, and only after using the Flock and Motorola systems to show an incredibly detailed history of a person’s travel and to interrogate her about it.
0:00
/
0:24
Hill wrote “The factors that the government relies upon [to search Kyle’s vehicle] are the same type of circumstances that everyday Americans encounter on long road trips for many legitimate reasons. Many of us drive longer than we want to get to a desired destination, or to no destination at all other than the road and sights ahead. Many of us lose track of what exact day of the week it is when we are traveling, even if it is for just a moment. Many of us travel for myriad reasons (some better than others), cross state lines, pack too much, buy too much, smoke cigarettes, and rent cars. And many of us even get a bit nervous when talking to law enforcement.”
One of the problems with automated license plate reader systems is that they allow police to recreate not just a single person’s movements and travel history, but any driver’s movements and travel history. Documents filed with the court show the totality of both the Flock and Motorola records, and show timestamped, geographically mapped images of the vehicle multiple times per day, driving throughout the entire country. The records also highlight just how many jurisdictions and businesses have Flock and Motorola ALPR cameras, and how that data forms a nationwide network.
For example, Alaniz had access to a photo of the rental vehicle taken by a Lowe’s hardware store-owned camera in Missouri, various Texas state police-owned cameras, by the New Mexico State police, the Kingman police department. In a five-day period, the car was scanned more than 50 times by 11 different law enforcement agencies.
“Alaniz’s search in just the ALPR system provided him with more than 50 individual records of Kyle’s whereabouts across the country for an entire month,” Hill wrote. “The Court finds that because the ALPR systems Alaniz used to search Kyle’s historical location information intruded on her reasonable expectation of privacy in the whole of her physical movements, it was a search under the Fourth Amendment. Based on the information in the record, the only reason Alaniz conducted that search was because he saw her license plate was from California. That search was not supported by probable cause, and it was done without a warrant in violation of Kyle’s Fourth Amendment rights.”
The Motorola ALPR report shows that, after the car was impounded, it was scanned two more times on the back of a tow truck later that day.
About the author
Jason is a cofounder of 404 Media. He was previously the editor-in-chief of Motherboard. He loves the Freedom of Information Act and surfing.
Updates to site guidelines and AI/LLM tags
Lobsters
lobste.rs
2026-10-18 21:28:53
Hey folks,
I've been having to perform an increasing number of moderation actions surrounding the vibecoding tag and AI/LLM related content. I started reading Lobsters because it had the most interesting viewpoints related to computing. During that time, I've found that this community is at it's bes...
I've been having to perform an increasing number of
moderation actions
surrounding the
vibecoding
tag and AI/LLM related content. I started reading Lobsters because it had the most interesting viewpoints related to computing. During that time, I've found that this community is at it's best when it's trying to, in good faith, help others grow. In lieu of a larger and more rambling discussion on this point, we would like to try two changes encourage that behavior again and re-focus topicality around ensuring that content submitted to the site should, at a minimum, be respectful of a reader's time and intelligence.
The first adjustment is two updates to the about page, which try to provide a bit more clarity in what we consider topical and what constitutes self promotion:
Intro:
Lobsters is a computing-focused community centered around discussing links. Our goal is to learn, craft, collaborate, and share interesting viewpoints.
The administrator is
Peter Bhat Harkins
("pushcx"), contact him or
another moderator
with any support issues. Lobsters was launched on July 3rd, 2012 by
joshua stein
(who is no longer running it, so please quit bugging him with site stuff) with careful design touches to encourage a healthy community:
At this risk of writing a mission statement, it seemed worth explaining what the site is and hopes to be to visitors from the first sentence of /about. (This original text came from
an intro post
.)
Then the Guidelines:
Topicality:
Lobsters is focused pretty narrowly on computing; tags like art don't imply every piece of art is on-topic. Some rules of thumb for great stories to submit: Will this improve the reader's next program? Will it deepen their understanding of their last program? Will it be more interesting in five or ten years? Is this compelling material that will seed a discussion, or is it just an artifact?
Pending an upcoming deploy, we no longer allow submissions which are code repositories. While, at first blush, this may seem odd for a community which is primarily centered around programming but it does eliminate the bulk of the "low effort, self promotional" submissions we've been seeing on the site. We've also found that being dropped into a new codebase doesn't start discussions because the reader has to have enough subject matter experience to immediately recognize what's novel or otherwise worth talking about. Instead, we are more interested in content around code bases which cover why it was created, the purpose it serves, the challenges overcome, and the reasons why it's a useful artifact in the ecosystem.
Some things that are off-topic here but popular on larger, similar sites: entrepreneurship; management; careers; news about companies that employ a lot of programmers; investing; world events; anthropology; self-help; personal productivity systems; last-resort customer service requests via public shaming; "I wanted to see what this site's amazing users think about this off-topic thing"; and defining the single morally correct economic and political system for the entire world when we can't even settle tabs vs. spaces.
We're listing "careers" as off-topic to try to head off posts about interviewing, promotions, burnout, and
farming
. We have the
job
tag because it's nice to help people connect to jobs, but the topic of getting a good job, weaving jobs into a career over your lifetime, and work is a different thing than the actual programming itself.
Self-promotion:
It's great to have authors participate in the community, but we do not want the community to be exploited as a write-only tool for product announcements or driving traffic to their work. As a rule of thumb, self-promotional activity should be less than a quarter of one's stories and comments in the last year. New users (
first 70 days
) are not allowed to submit self-promo.
This is how we've been enforcing the rule for a while, better to be explicit. It's unfortunately common that authors see their work posted, join the site, but then only use us for traffic. Hopefully this time helps them understand the difference between a symbiotic and parasitic relationship.
The second adjustment is that the
vibecoding
tag is now marked as inactive. It still appears on old stories but can't be applied to new ones. From my perspective, the tag was overloaded with six differing responsibilities:
First, it was the tag which was trying to capture the discussions related to the use and implementation of AI/LLM tools.
Second, it was a marker for content which is partially related to AI/LLM tools, tooling or companies.
Third, it was a marker for content which includes a discussion on or output from AI/LLM tools in a part of a larger work.
Fourth, it was a marker for content which was generated using AI/LLM tools.
Fifth, it was being used in competition to the
spam
flag, for really low-quality content which was generated via AI/LLM tools but without apparent significant human authorship.
Sixth, it was being used as a
tag of shame
by people who really dislike AI/LLM tools and used it to insult people at every passing mention.
The last couple years have been the biggest upheaval in the field for decades. While it's acceptable, within limits, to express frustration towards circumstance or technology, it's not acceptable to direct that behavior towards individuals whether they be members of the community or not. Other people can't be your punching bags and Lobsters can't be your boxing ring.
That's not acceptable
.
While `vibecoding` is no longer an active tag, we still feel that a subset of the tooling related discussions are relevant to the site. While this is reaching far back into the annals of computing history, tools like
compilers
,
databases
,
testing
, and
vcs
had similar points of consternation and concern when they were introduced. I'm not going to claim that I'm able to guess how the industry is going to shape up, but my gut feeling is that but my gut feeling is that it's going to be closer to something like we've seen with
systemd
than compilers. This new tag `ai-tooling` covers "The design, ux, development of AI/LLM-powered tools themselves".
As a fun addendum, there's a variant of Maslow’s Hierarchy of Needs which exist for websites, we kinda fell on the wrong side of that trying to migrate the site and get this out on a Saturday. Whoops!
Thanks,
355E3B
BBC Master Pi 1MHz Domesday
Lobsters
youtu.be
2026-10-18 21:20:14
Dominic Plunkett has updated the BBC Micro PiMHz software to emulate most of the hardware for a BBC AIV system, including the LV player! Just add a trackball/mouse and a PiTubeDirect and you'll be able to run the Domesday disc!
This video covers how the PiMHz implementation works (basically!), how t...
For quick and dirty rendering of simple dynamic content, you may not need the complexity of a templating language like Handlebars or a PHP backend.
Let’s use the example phrase,
“Come on, it’s
<currentYear>
”
. It should result in
“Come on, it’s
”
when rendered today.
You can write this directly in HTML—
without IDs, classes, or querySelectors in your JS!
Thanks to the
document.currentScript
property, we can refer to the
currently running
<script>
element
directly and go from there.
So the dynamic phrase
“Come on, it’s ”
would now be written as:
Come on, it’s
<script>
document.currentScript.replaceWith(new Date().getFullYear())
</script>
The script simply replaces itself with its computed value on the spot.
The code’s a bit wordy though, but we can
alias
it to a constant like
$
via
$=(...n)=>document.currentScript.replaceWith(...n)
. Then we’d have something reminiscent of
template literals
in JS.
Come on, it’s <script>$(new Date().getFullYear())</script>
The code is pretty readable at a glance without context (after you get past the bit of indirection that is the
$
alias).
A
noscript
fallback would be nice for those that don’t run JS.
Come on, it’s
<noscript>current year</noscript>
<script>$(new Date().getFullYear())</script>
The resulting script-noscript juxtaposition in the markup looks almost like Angular/Vue’s if-else markup, neat.
IIRC, I learned about this technique from the
Surreal
library or something similar. But I’m sure this is not a new discovery. These APIs have been standardised for a long time.
Real world examples
If you thought this technique is only useful for rendering the current year, you’re mostly right! As an example, I’ve used inline scripts to refer to relative dates in my living pages. Because
“ years ago”
sounds more natural than
“2017”
.
It was planted
<noscript>in 2017</noscript>
<script>$(new Date().getFullYear()-2017, ' years ago')</script>
but now it has grown tall and strong.
It was planted
but now it has grown tall and strong.
Random greeting
Another example is in my front page, which says a randomly selected greeting on each visit.
<span class="intro-line">
<noscript>Hello!</noscript>
<script>
$([
"Hello!",
"Hey~~~",
"What’s up ↑",
"Hi there →",
"Hey there →",
][Date.now() % 5])
</script>
</span>
The randomiser is just a
Date.now()
with modulo because it was more concise than
Math.floor(Math.random() * 5)
.
Splitting text for animation
Split text into characters using inline scripts to generate markup per character which can then be controlled or animated! In my case, I used it to render circular text, but a more common use case is text animation like the following.
Why pollute the global ID namespace and separate coupled code if we can avoid it?
Date().split` `[3]
is also a short (but very hacky) way to get the year.
At this point you may be asking, is this technique only really useful for rendering the current year? Maybe, but we can do more than just
rendering
text.
Come on, it’s , the web is rich and interactive!
The ubiquitous counter app example
This is not a simple templating example anymore, but shows the power of
currentScript
in
hydrating
self-contained bits of interactive HTML.
I used this ‘local script’ pattern all the time in a previous version of this blog. It’s useful when making interactive illustrations in the middle of a long post. You wouldn’t want to put that logic at the very end or start of the file, away from the relevant section! Same goes for styles, now made even better with the
@scope
rule
.
It’s a good way to manage islands of interactivity.
The catch
There are reasons people gravitate to libraries and frameworks. They’re just too convenient.
If you want to use the alias definition above—the
$
shorthand—then you'd first have to define it at the top of the HTML,
synchronously
. Say you want to use this in multiple pages, so you put this in a common script file and load it via
<script src="$.js"</script>
. This could result in a parser- and render-blocking fetch: potentially very bad for performance!
For my own cases, I don’t use the alias. I straight up just use
document.currentScript.replaceWith
. Wish it was
shorter…
Also, you cannot do
data-driven templating
this way, in the sense that you have
templates
to apply
data
onto. Metadata such as date published, post title, and tags that are stored in some posts table or in frontmatter somewhere, cannot be used for inline scripting purposes. You can’t fetch data from inline scripts. Therefore, unless data is somehow pre-injected in the global scope, no luck in pure vanilla JS templating. This is where templating languages like
Liquid
really shine.
Update: Data-driven templating
I previously said that you cannot do
data-driven templating
this way (see deleted section above). However, a nice reader has found a way to do so (thanks Amier)!
All you need is to save the
currentScript
in a variable, then you can refer to it in any async operation!
document.write()
used to (?) work like this for inline rendering, but it’s now deprecated because it had inconsistent behaviour.
Come on, it’s
<script>document.write(new Date().getFullYear())</script>,
stop using <code>document.write</code>!
Kylie Minogue songs already used to train AI as tech firms ‘strong-arm’ Australian government, music body warns
Guardian
www.theguardian.com
2026-10-18 20:57:46
Of the dozens of countries approached to water down their laws, Australia appears to be the only one considering it, publishers’ group saysGet our new political email, free app or daily news podcastAI has already been trained on the works of Australian artists including Kylie Minogue and Nick Cave w...
AI has already been trained on the works of Australian artists including
Kylie Minogue
and Nick Cave without compensation, the peak global body for music rights has claimed, as the Australian government has been warned against giving in to “strong-arming” from tech companies seeking to weaken copyright law.
The International Confederation of Music Publishers (ICMP) – which represents Sony, Warner and Universal as well as thousands of independent publishers on six continents – has warned that of the dozens of countries approached to water down copyright laws, Australia appears to be the only to consider doing so.
John Phelan, the ICMP’s managing director, told Guardian Australia AI companies were asking policymakers to “legitimise larceny”.
“They’re trying to strong-arm Australian policymakers into ‘if you don’t do this, we won’t invest’.”
In July,
Anthony Albanese said it would be “theft”
if artists did not retain control over whether their work was used to build and train AI, and what they were paid for its use.
Music, film, media and news organisations had expressed concerns the government was being lobbied by global tech companies behind closed doors to weaken Australia’s copyright laws to help train AI models, without compensating the creative sectors.
But government and opposition members of a parliamentary committee on artificial intelligence appeared to revisit the issue this week, describing the current situation as a stalemate.
They said AI models were already training on copyrighted works in the United States without compensating creators – but that without changes to local copyright laws, those companies were withholding training frontier AI models in Australia.
In a joint letter to the prime minister this week, the inquiry’s Labor chair, Jo Briskey, and its deputy chair, Liberal senator Jonathon Duniam, recommended the government “examine current copyright settings” while ensuring creators retain control and are paid.
The independent senator David Pocock
has raised concerns
that the committee was coming to a position on copyright predetermined by the prime minister, after staffer edits were seen in the letter. Briskey has rejected the claim.
AI companies’ demands
The ICMP has been tracking how AI companies are attempting to change copyright law in different jurisdictions to allow training. Phelan highlighted
methods that the companies had used
to train their models on music, such as with spreadsheets containing millions of lines of music available on YouTube.
A key claim of the AI industry is that its models are not trained on Australian content due to copyright rules. However, in evidence provided exclusively to Guardian Australia, ICMP showed Google’s Gemini was able to reproduce lyrics from Australian artists including Kylie Minogue, G-Flip and
Nick Cave
.
“There isn’t a single country among the other 61 [countries] … which has introduced a new text and data mining exception for commercial purposes, or reduce the idea of exclusive rights and copyright,” Phelan said.
“The world is very much watching what Australia does.”
“It’s fair to say the global music industry, as well as all creative industries worldwide we work with, are appalled by the idea of a statutory scheme or a government deal which would interfere with how Australian industries work and contract around the world.”
Anthropic’s special envoy, Jeffrey Bleich, told the AI
committee last week the company was not trying to dictate terms, but had shared information with the Australian government about training and what the implications would be “with respect to our capacity to operate here”.
“You can’t license the entire internet. Billions and billions of information exists there which is available to be viewed and studied, and that’s essentially what training is,” he said.
“Under existing
Australian law
, it’s our understanding that that could be determined to be illegal if we weren’t able to find a licence with every single person who had rights within Australia.”
OpenAI’s chief of economic policy, Adam Cohen, said the fair use exception in US law “fundamentally protects” the development of new technology. He pointed to agreements made with News Corp and the Guardian as examples of where the company makes deals for the use of work, despite arguing US law did not require such.
Phelan said he believed panic had set in among the AI companies over the sheer cost of investment and the need to make a return, coupled with the ongoing litigation over copyright in the US. He said they may be looking to Australia for a legislative solution.
“They’re seeing the legislative side as being the way to try to [find] a place to do business without licences, which will secure their future business model.”
In a submission to the inquiry, Guardian Australia said that undermining copyright protection would have a “profound impact on civil society” and copyright-protected material should only be available for AI training with the rights holder’s explicit prior authorisation.
South Park Episode Deemed ‘Best in a Decade’ After Spoofing Clavicular and Backrooms
Portside
portside.org
2026-10-18 20:53:44
South Park Episode Deemed ‘Best in a Decade’ After Spoofing Clavicular and Backrooms
Marti
Sun, 10/18/2026 - 20:53
...
Kyle’s younger brother is then involved in a live-streamed aura battle — spewed with Gen Z slang like “mogging,” “maxxing” and “cringe” — with a schoolmate named Chase Chadwick who looks undeniably like
controversial influencer Clavicular.
Although the episode strayed from
jokes about Donald Trump
, viewers seemed to love the comedy show’s takes on current internet trends.
“Holy s*** this new
South Park
episode was actually the best episode in like a decade, genuinely never thought they would make something that good again,” one fan wrote on X. “Instant classic in my opinion.”
Clavicular is spoofed in the latest episode of 'South Park'
(Comedy Central)
Another added: “Recent
South Park
episodes haven't been as good as past ones because reality is so much crazier than whatever Matt [Stone] or Trey [Parker] can come up with but the most recent episode was hilarious.”
Others agreed that it was the “best episode of this season so far,” with one writing, “Possibly the best episode in a decade, despite all the silly lingo.”
The October 14 episode of South Park referenced the 2026 horror movie 'Backrooms'
(Comedy Central)
In a statement to
The Independent
, Parker and Stone said: “Inspired by the bravery and patriotism of Apple and Google, we are changing the name of
South Park
to SOUTH AMERICA. We especially want to thank our parent company Paramount - a Skydance Capitulation.”
In an interview with
The New York Times
last year, the co-creators said that Trump was featured so heavily in the last season because of the way his presidency has affected culture.
“It’s not that we got all political,” Parker said. “It’s that politics became pop culture.”
D&D and Magic the Gathering Developers Unionize, Allege Wizards of the Coast Is Pushing “Adoption of LLMs and Generative AI”
Portside
portside.org
2026-10-18 20:41:16
D&D and Magic the Gathering Developers Unionize, Allege Wizards of the Coast Is Pushing “Adoption of LLMs and Generative AI”
Marti
Sun, 10/18/2026 - 20:41
...
D&D and Magic the Gathering Developers Unionize, Allege Wizards of the Coast Is Pushing “Adoption of LLMs and Generative AI”
Published
October 18, 2026
(Image credit: Wizards of the Coast)
The makers of Dungeons & Dragons and Magic: The Gathering have unionized. Today, the developers of the massive tabletop games have announced that they're joining United Wizards of the Coast - CWA, and are calling on their company to voluntarily recognize the union. Among their demands is protection from what they call an increasing push for AI use from Wizards of the Coast management.
United Wizards of the Coast announced its existence in April. Back then, it consisted only of the developers behind the digital card game, Magic: The Gathering Arena. Today, the workers behind Dungeons & Dragons, D&D Beyond, Magic: The Gathering, and Duel Masters announced their intent to unionize under the same banner. This union is supported by the Communication Workers of America, which has
previously supported unions at publishers like Activision
and Xbox.
Wizards of the Coast itself has until October 13 to respond to the union's request for voluntary recognition. The company did not respond to a deadline for voluntary recognition when the MTG Arena devs first announced their intent to unionize, but the union nonetheless won its election in June.
For now, the union is asking fans to support them by signing an
online petition
. Among demands like "fair wages," "reliable and easily accessible healthcare," and "remote work protections," the union is also demanding "protection against the encroachment of AI.
"Leadership, without regard for the desires of our teams, has pushed for adoption of LLMs and generative AI," the union claims. "This has to stop; our teams deserve a robust and enforceable AI policy that aligns with our goals and values."
The union has already filed an election petition with the National Labor Relations Board. If Wizards of the Coast does not choose to voluntarily recognize the union, it'll be up to elections among workers and the NLRB to force the issue.
Dustin Bailey joined the GamesRadar team as a Staff Writer in May 2022, and is currently based in Missouri. He's been covering games (with occasional dalliances in the worlds of anime and pro wrestling) since 2015, first as a freelancer, then as a news writer at PCGamesN for nearly five years. His love for games was sparked somewhere between Metal Gear Solid 2 and Knights of the Old Republic, and these days you can usually find him splitting his entertainment time between retro gaming, the latest big action-adventure title, or a long haul in American Truck Simulator.
Imprint’s average engineer is merging 4x more PRs than 2 years ago. Yay.
Aggregated behind the average is something even more interesting:
we have two teams that are merging 10x their PRs over that period.
One engineer is merging 25x the PRs per week of our average engineer two years ago,
and a number of others are closing in on that number.
That’s pretty neat, and the slope of the line suggests our average in a year is going to look much closer to
today’s p90 than today’s p50.
Even more importantly, we aren’t just shipping more, our quality has improved:
incidents are down 42% half-over-half, and critical incidents are down 78% half-over-half.
I think we’ve always known the quality/velocity tradeoff wasn’t a particularly useful
construct, but that’s undeniable today.
As we’ve walked this path, we–
like everyone else
progressing down it–have run into the problem of pull request review. The p50 pull request review took about 33 minutes to complete
2 years ago, but now takes us about 77 minutes. The slope here correlates tightly with the number of
pull requests getting merged. Tightly enough that addressing it became one of my priorities for the week.
We solved it! Just kidding, we’ve absolutely not solved it, but I think our current
approach is an interesting one, which we call the
small-change
.
The work discussed here was shaped and done by many folks at Imprint including Dan, Joy, Daniel, Lenny, Taylor, Ted, and Annie, among many others.
Why review pull requests?
There are four reasons we review pull requests:
Knowledge sharing between author and reviewer
– software engineering is generally learned via
apprenticeship, and reviews are a primary mechanism of experienced engineers teaching others what
good software looks like. We believe the current volume means that this knowledge sharing
will have to move towards operating on clusters of pull requests, rather than individual pull requests
Preventing errors
– review has always been an expensive time to catch errors,
and we believe that effective CICD along with harness verification techniques like poteto’s
pstack
are more effective mechanisms
for preventing errors than review
Preventing malicious behavior
– my experience is that even careful code review will generally
miss
competent
malicious behavior, although fortunately most malicious behavior is incompetent.
We believe both sorts of behavior are best identified using a combination of fixed rules (modifying
these specific objects/classes/files requires review), anti-abuse mechanisms that we’ve refined in
our LLM-based member support experiences, auditing, and audit log inspection
Compliance obligations in our documented controls
– these can be changed, but today they require that
an independent human reviews changes in a subset of our repositories
In the modern development paradigm, we think there is a better solution for each of these problems.
But, we also want to make these changes very cautiously.
Small steps with
small-change
We believe we move fast by finding narrow, contained ways to validate new practices,
so to iterate our way into an effective solution, we’ve developed the concept of a
small-change
. Here’s how it works:
When a pull request is marked ready, CICD determines whether it is eligible to be a
small-change
.
This is represented as a passing Github check. There is
also
a label for visibility,
but it is the check itself, managed by the build and not human modifiable, that determines eligibility.
(The label is used for initial filtering, but the check is still independently verified.)
Something is a
small-change
if it meets all of these criteria:
It is less than 1,000 lines of code
There are no p1 or p2 findings from our
ai-code-review
automated review bot
The author has “experience” in the service or application, defined as 10+ prior merged pull requests
into that service or application’s directories.
For changes working across multiple services or applications, the author must have experience in all of them to qualify
Impacts fewer than
N
distinct services or applications.
N
is 1 on our frontend monorepo,
and
N
is 3 in our backend monorepo, where typical changes will modify both a gRPC service and a common HTTP gateway
Shared libraries and utilities files are not eligible for
small-change
Each repository has a
.small_change
file which allows per-path customization while we continue to tune the behaviors.
For example, a service dealing with money movement can be excluded
Our Slack automation tags every reference to a pull request with reacji labeling the state of that pull request,
for example if it has failing tests, if it has been approved but tests are still running, or if it is ready to merge.
We added a
small-change
reacji that indicates which of those pull requests meet the
small-change
criteria
In our internal skills repository, we created two skills that have been distributed across harnesses:
review-small-change
which takes a list of repositories and reviews all open, non-draft, small-changes,
including providing approval if they meet the review’s criteria (all checks pass including
small-change
check,
and not touching on sensitive topics such as payments and security).
Importantly, this skill has only two options: approve or ignore. It
never
comments on the PR to avoid
the proliferation of “
meat proxy
review”
which has become a bottleneck-pretending-to-be-a-solution on some teams
review-pr-cluster
which reviews batches of pull requests to identify common themes that came up, and suggest opportunities
for discussion and adding verifications
We set the social expectation that any error caused by a
small-change
is a failure in our system,
and has to be solved at the system level: improvements to
ai-code-review
, to our verification mechanisms,
to our CICD, to our harness, etc.
This took about two days of infrequent attention to implement and rollout,
although I imagine we will be tuning the knobs here for a long time. Maybe forever.
Meat proxy review
I mentioned this in
4.1
above, but
meat proxy
review has become
an interesting bottleneck for many teams. It’s a particularly difficult bottleneck because it initially
looks like
a solution,
but it makes things worse. The pattern is roughly:
Team is overwhelmed with reviews
Team decides to review pull requests with their local harness
Pull requests get a large number of comments, some of which make sense, and some of which don’t.
It’s unclear which is which without study, and you don’t know which comments reflect the reviewer’s
point of view. So you end up having to do substantial work to disprove comments that the reviewer may
not even agree with
Those teams then start using harnesses to respond to the harness-generated comments,
making the entire review process an illusion that doesn’t facilitate learning,
and most importantly could be done without the involvement of the other team members
In every case that meat proxy review is performed, the team would get better outcomes by
investing into the centralized review mechanism, the harness’ loop for addressing the centralized review’s feedback,
and simply stamping approval.
fleet
: centrally orchestrated harness
I’ll briefly mention our other approach to reducing code review
volume, which anchors on our centrally-orchestrated harness,
fleet
.
(Which is similar to
Stripe’s Minions
although not following the one-shot approach in particular).
We rely on
fleet
to implement and verify software in a highly controlled harness running in the cloud, with independent
evaluation mechanisms to identify the correct number of independent reviewers for
any given change. That number can be as low as one (e.g.
fleet
writes, one human reviews)
for changes evaluated as safe.
Results / next steps / reception
I’ll be honest, it’s too early to give a useful result here.
From early results, about 10% of changes qualify as a
small-change
.
Those are now eligible for very fast approval, and generally get it unless
they trip a flag, generally due to touching a security or money adjacent topic.
While 10% is a small percentage, the core concept here is working,
and ultimately will succeed or fail based on our ability to expand
that percentage over the next few months in tandem with expanding
our verification mechanisms to be increasingly comprehensive.
This is ultimately going to fail or succeed depending on our ability
to improve our verifications, which does require more difficult sorts of techniques
to accomplish in
low scale-complexity, high domain-complexity
software
than in the high scale-complexity, low domain-complexity products where many techniques
like incremental rollouts are exceptionally effective. (Don’t get me wrong,
they still work, they just provide less coverage when most users have different configuration and behavior.)
Folks have not been uniformly excited about this,
it’s a substantial change from how we’ve learned to be good engineers,
and it’s uncomfortable to reevaluate whether a long-held best practice has become merely dogma.
The most energizing part of the current cycle is that we get to reevaluate these
practices we grew up on every week; the most painful part of the current cycle is that
we’re likely to fall behind if we ever stop reevaluating them.
The board re-recorded its prompts over the years. Choose the day you are calling.
The date also decides the Halloween greeting (25-31 October), the Halloween 1996 login sounds, the sysop's welcome for new callers and birthdays. Members on the even/odd-day economic plan are told it is not their day when the day of the month ends in the wrong digit: add
?date=1996-06-02
(even) or
?date=1996-06-01
(odd) to the phone page address.
// THE STORY
Sanity's Edge was a bulletin board you could only reach by telephone. No modem, no screen: you dialed, pressed keys, and listened. It ran from 1994 to March 1997 on a dedicated 286 PC in a house in Tampa, Florida, built by a father and his ten-year-old son.
It started in the garage. In a box of odds and ends Max found an open retail box for the BigMouth voice card and its SDK: the card, the SDK software, paper manuals and all. He had already taught himself BASIC, so a development kit caught his eye and he asked his dad about it. “Well, son, let me tell you about SDKs...” was how he learned what one was. Around the same time he got his first computer, an 8086 with no math coprocessor, and his father taught him C on it with Turbo C: how to look up what a function does in the reference manuals, then arrays and tables in more than one dimension.
His father was a radio-station automation programmer who worked from home. He became the sysop,
Dr. Null
, and wrote the database backend. Max wrote a lot of the rest, including the menu structures, and was a user of the board and its co-creator: the asylum theme was his idea, and he coded the maze himself. He was user number 7, and went by
Xela
(Alex backwards).
The phone number,
813-989-1950
, was Max's own line in his bedroom, wired up for the board; the house had three or four lines because Dad worked from home. Max designed business cards and a full-page flyer and handed them out. Anyone was welcome to call and register. Members paid a monthly fee, about five dollars as Max remembers it, and he opened the envelopes that arrived in the mail.
Callers were admitted to an asylum. Message bases were therapy rooms, the public forums were the “Men in White Jackets,” and every voice left behind became part of the fiction. Over three years the line took more than 26,000 calls and collected more than 46,000 voice messages from friends, schoolmates and strangers around the Tampa Bay area. His mother's voice is on quite a few of the recordings, including “What is Sanity's Edge?”, and his father's younger voice welcomes you to the Men in White Jackets.
Max's father passed away some years ago. Among his hoarded technology and data was a backup of Sanity's Edge, copied from hard disk to hard disk, then to solid state, and finally onto a CD labeled “Sanity's Edge” that Max's mother found and handed to him.
It took three generations of AI, and the Reverse Engineer Anything (REA) project, to crack it. ChatGPT 3, more than a year ago, did a poor job. Sonnet 4 almost cracked everything and built the first museum page, but that page was a bad recreation and the audio never played right. Then Claude Sonnet 5.5 with REA opened it completely: the audio codec turned up in Talking Technology's own converter inside the archive, the program and its logs were read directly, and every recording now plays as it did. The C source that was missing has since been rebuilt, function by function, from the machine code.
Read how the code was cracked →
It was a shared creation, and now it has a chance to last. Thank you, Dad, and thank you AI.
The business card belongs on this page too. Photo coming.
// THE ORIGINAL FLYER
What a new caller got in the 1990s: the information sheet (what the board is, the $8 a month plan, who Dr. Null is) and the hand-drawn map of every menu behind the phone. Photographed from the surviving paper copies. Click either one to read it at full size.
// THE ARCHIVE
2,254
Audio Files Decoded
24h 24m
Of Audio Preserved
47
Users Registered
9
Message Bases
// THE MESSAGE BASES
Nine rooms in the asylum, each with its own purpose. Patients left voice messages for each other -- sometimes funny, sometimes raw, always real.
1
.
The Padded Cell
2
.
Cosmology
3
.
The Dolphin Dave Show
4
.
Poetry
5
.
The Philosophical Base
6
.
The Entertainment Emporium
7
.
The Pasture
8
.
The Litter Box (rated R)
9
.
Music Therapy
// THE CALLERS
60
registered patients. These were real people who called a Tampa, Florida telephone number in the 1990s and left their voices on it.
1
Dr.Null
1000
3
2
Shelly
1001
3
3
MAry JAne
1002
—
4
Nicholas
1003
—
5
Pocki
1004
—
6
Ungah!
1005
41
7
Jaimi S.
1006
3
8
xelA
1007
31
9
Carrie P.
1008
—
10
Harmonic Flame
1009
2
11
Jane Doe
1010
—
12
Raptor
1011
—
13
Angela B.
1012
—
14
Speedo-Man!
1013
—
15
Mad Man672
1014
—
16
Blade
1015
—
17
Gene
1016
—
18
Erik A.
1017
—
19
Wicked
1018
3
22
Yoda or Barbeeeka!
1999
—
28
Suicidal Tendencies!
1027
3
30
Tammy M.
1029
—
31
Pyro tech the Anarchist
1030
—
32
Kitty cat whipped cream
1031
—
33
Death
1032
—
36
Cairo
1035
—
37
Honky Tonk Piano
1036
—
38
Alex Kid
1037
—
39
Blade Runner
1038
—
40
Shenen Rose
1039
—
42
Peekaboo!
1041
—
43
Kahn
1042
—
44
Midnight Sorrrow
1043
—
45
Christin
1044
—
47
Ricola
1046
—
51
Psycotic Delusions
1022
3
52
Jason E.
1666
—
53
Reba S.
2001
—
54
Jason P.
2002
—
55
Rachel T.
2004
—
56
Samantha P.
1019
—
57
Anavrin
1020
2
58
Shani
1050
6
59
MD
1028
3
60
Blade Runner
2031
—
61
Scorpion
3002
6
62
Mistique
2019
—
63
tanuke
2011
34
64
Trickster
2008
5
65
Tom Cat
2032
16
66
Wet and Wild
2017
—
67
Ice Man
2020
1
68
Kimber
2036
—
69
Domestic Goddess
2038
—
70
Dagger
2003
3
71
SandMan
2016
3
72
Mustang Man
2043
3
73
Liberty
2012
—
74
Cladenestra
2014
1
75
Dolphin Dave
2013
—
Names follow a privacy rule: full names only for callers known to be adults; everyone else is a first name and initial. Private mail is not public.
Try the board:
Speedo-Man!
-- use passcode
616241
;
Alex Kid
-- use passcode
139194
;
Shenen Rose
-- use passcode
172855
;
Mistique
-- use passcode
271653
.
Called in the 1990s and cannot remember your passcode?
Request your mailbox
.
// THE TECHNOLOGY
The system ran on a dedicated 286 PC -- modest even by 1994 standards -- equipped with a
Talking Technology Powerline I
ISA telephony card. This card handled the phone line: answering calls, playing audio prompts, recording voice messages, and reading touchtone key presses.
The software was
BigmOuth
, a voice BBS platform that turned the PC into a single-line interactive phone system. Callers navigated menus by pressing keys on their phone. There was no text, no screen -- only voice. The entire experience happened through the telephone handset.
Audio was stored in a proprietary format on the hard drive. In February 2026, these files were first decoded into standard WAV format, making it possible to hear the original recordings for the first time in decades.
Compilers are good at making mechanical transformations that make code faster. Unfortunately, most of them are not as good at non-trivial reasoning, so they can’t invent a completely novel approach to solving your problem.
When designing a library for floating-point calculations, I had to implement a function that takes a float
and produces a float corresponding to the lowest set bit in
. For example, if
in binary, it would return
.
This can be implemented with bit twiddling, but the straightforward algorithm breaks for powers of two, so I had to insert an
if
:
iff32::from_bits(x.to_bits() & !f32::MANTISSA_MASK) == x { // is x a power of two?return x; // x itself is the lowest bit
} else {
return x - f32::from_bits(x.to_bits() & (x.to_bits() - 1)); // x, minus x without lowest bit
}
This
if
really annoyed me. It’s slowed down for the common case, and branches could be mispredicted. I wanted to find a formula that automatically handled powers of two, but try as I might, I couldn’t find anything convincingly optimal.
So I made a non-orthodox play.
Brute-force
What if there was a way to find such a formula automatically? No, not by spawning an LLM swarm, but by brute-forcing all possible formulas. LLMs can miss stuff or overindex on popular patterns; brute-force can’t.
But how do we check if a formula is correct? Theorem provers are too slow, but we can design a few representative test cases and hope that whatever formula we find is correct. And if it has a counterexample, just add it to the list of test cases and repeat.
This is not as insane as it sounds: by this moment I had already implemented an algorithm with
operations, so I just needed to iterate over formulas with
ops or fewer. I knew that the following operations could be useful:
Integer addition/subtraction and bitwise AND/OR/XOR for bit tricks.
But we also need to choose the inputs to each operation, which can be either the input value
or some constant. I guessed that we’ll only need constants that cover various fields of the
float
binary representation, and not completely random ones, reducing the list to
different constants. That’s
combinations, which sounds like a lot, but in practice we can cull many of them.
Search
To implement the search efficiently, I build up the formula set inductively.
Formulas with
operations are just
and constants; formulas with
operations can be found by combining all pairs of formulas with
and
operations:
Induction allows us to prune duplicates. For example,
and
are different expressions, but they return the same values. Keeping just one expression for each set of outputs allows further iterations to complete faster. This is the reason why brute-force can complete in just
minutes! (I’m sure it can be optimized further, but I preferred watching YouTube over optimizing a one-off script.)
To save time and memory, I avoid deduplication on the last iteration and output all matching candidates. Memory usage matters because I had
test cases by this point, so I had to store
bytes per expression, and there are
a lot
of expressions.
Results
So, did this exhaustive search find anything interesting? Yes! There were several formulas with
operations, e.g. this one:
I couldn’t find formulas with
operations, but this approach has a limitation: it doesn’t take into account that calculations can be reused. So, for example, if
x & 1
is used in two places, it will count that as two operations, not one. I was hoping that one of the
-op formulas could actually be expressed as
operations via reuse, and after manually checking every formula, the very last one turned out to have this property! Here’s what it looks like:
leta = x.to_bits() & !f32::MANTISSA_MASK; // x without mantissa bitsreturnf32::from_bits(x.to_bits() & (a - x.to_bits())) - f32::from_bits(a);
It behaves a little differently for powers of two – it flips the sign bit, which I don’t care about. And the logic doesn’t make sense at first glance, and yet it works.
The reason why only this formula can reuse
a
is the subexpression
a - x.to_bits()
. It’s equivalent to
-(x & f32::MANTISSA_MASK)
, which is how other formulas refer to it. All formulas compute
x & !f32::MANTISSA_MASK
and
x & f32::MANTISSA_MASK
, but this one rewrites the latter as
x - (x & f32::MANTISSA_MASK)
, and then merges that with negation to save one operation!
I was flabbergasted when I realized it found such a clever rewrite. You don’t need an LLM to be amazed by what computers can invent! And it doesn’t destroy industries.
Linus Torvalds has released the 7.3
kernel, as expected.
It's Sunday afternoon, and this week I somehow kept my wits
together long enough to keep track of the day of the week, so the
release isn't randomly delayed. Will wonders never cease?
Anyway, nothing very special seems to have happened ...
Linus Torvalds has
released
the 7.3
kernel, as expected.
It's Sunday afternoon, and this week I somehow kept my wits
together long enough to keep track of the day of the week, so the
release isn't randomly delayed. Will wonders never cease?
Anyway, nothing very special seems to have happened this last week,
so as expected the final 7.3 is out, and thus tomorrow the merge
window for 7.4 opens. Except I'm on my annual family vacation, so
instead of merging anything first thing in the morning, I'll spend
most of the day on a boat and under water. I'll get back to merging
in the afternoon, but I expect my schedule to be a bit unusual for
a while.
This release is a record-breaker on all fronts; it brought in 18,765
non-merge commits from 3,021 developers, 807 of whom were first-time kernel
developers.
Release: llm-tools-datasette 0.1.1
When I switched LLM over to httpx2 in LLM 0.33 I forget that this would break any plugins which used httpx without directly depending on it. llm-tools-datasette was one of those plugins, now fixed.
Tags: datasette, llm...
Sponsored by:
Teleport
— AI agents (and sub-agents they spawn) are given the same access as humans, but they never sleep. Learn how to monitor and constrain their behavior with isolated ephemeral trusted runtimes.
Park Güell, Barcelona, 1990
Michael Girard, Deborah Gibson, Timothy Leary, Eric Gullichsen, William Gibson.
Susan Amkraut obscured behind Deborah
The Cyberspace Rumor
From the first days of the web, people have repeated the story that Autodesk trademarked "cyberspace" and Gibson retaliated by trademarking "Eric Gullichsen".
Autodesk Cyberspace
In 1989, I was working at the Autodesk Research Lab on early virtual reality, a project started after we visited Scott Fisher at NASA Ames. Our nascent system was a 386 with a pair of Matrox graphics cards on the ISA bus, a VPL EyePhone, a Polhemus tracker, and a data glove. It ran at six to ten frames per second on models with a few hundred polygons. Sluggish, but marginally enough to get us
Through the Looking Glass
.
Our motto was “Reality Isn’t Enough Any More”.
Timothy Leary
I was also spending a lot of time hanging out with Timothy Leary, whose suggestion was responsible for my quitting my job at
MCC
and moving to California. I’d met him at the Hackers 2.0 conference in 1986 and gave him a ride to the San Jose airport. We became fast friends, and I did quite a lot of writing with him, most of which remains unpublished. But that’s a story for later. Timothy, who appears in a samizdat
Autodesk virtual reality video
, nicknamed our VR lab “Cyberia”.
Timothy was a tremendous fan of Gibson, and considered his seminal 1984 novel
Neuromancer
extremely prescient about the impending digital revolution.
As our VR developments crept slowly towards becoming a product, we at Autodesk applied to register a trademark “cyberspace”. Timothy informed me Gibson was plenty miffed about this, so I wrote him what I felt was a conciliatory letter,
1
though ending snarkily by quoting his own words, “The street finds its own use for things.”
In reply, Gibson had his lawyers send Autodesk a letter
2
. Which I recall we ignored.
Timothy - ever the incorrigible prankster - circulated the rumor that Gibson was attempting to trademark “Eric Gullichsen” in retaliation. Then Barlow, for reasons of his own,
embellished that rumor
. Later amplified by
Rudy Rucker
.
Art Futura 1990
About a year later - after I'd already left Autodesk for my VR startup, Sense8 Corporation - we were invited to the inaugural Art Futura 1990 in Barcelona. And there, in the lobby of some swank hotel, I met Gibson. He opined in a laconic drawl that although the street finds its own use for things
“Autodesk is not the street”
.
There was plenty of cava consumed in the small hours before the time Barcelonans sit down to eat endless rounds of tapas. As I recall, after all the many Art Futura parties we'd put the matter behind us, or close enough.
And there was a memorable visit to Gaudi’s Park Güell, whose giant lizard of crazy-quilt ceramic appears in
Count Zero
.
So: Autodesk did
apply to register
Cyberspace, and Gibson really did object. But Gibson trying to trademark Eric Gullichsen was Timothy Leary's prank, propagated until it became accepted history.
How Quickly Can the DoD Rebuild and Recast the Munitions Industrial Base?
Recent analyses have identified the
causes
and
consequences
of shrinking munitions
stockpiles
. Policymakers and industry should now turn their efforts to not only rebuilding the munitions industrial base but also recasting it for the demands of modern high-intensity wars of precision and attrition. Doing so calls for both increasing the size and changing the composition of the U.S. munitions arsenal, embracing
magazine breadth
as well as magazine depth through equipping the joint force with a “
high-low mix
” of exquisite and affordable missiles and interceptors. The emergence of multiyear “
framework agreements
” between the Department of Defense (DOD) and contractors is important, but they need to be followed by appropriations from Congress, increased capital expenditures (CapEx) by industry, and contracts between the Pentagon and companies.
What is a realistic timeline for this rebuilding and recasting of the munitions industrial base? Looking at the president’s fiscal year 2027 budget request, subsequent initiatives, quarterly company reporting, and recent contract announcements provides a clearer picture of the planned future as well as the obstacles that need to be overcome to achieve those objectives.
The Changing Composition of the U.S. Munitions Arsenal
Based upon the DOD’s FY 2027
budget requests
and subsequent policy announcements, the Pentagon plans to significantly grow stocks of the nation’s proven and capable missiles and interceptors. For example, requests for Patriot PAC-3 Missile Segment Enhanced (MSE) interceptors have grown 839 percent, from 341 in FY 2026 (by the U.S.
Army
and
Navy
) to 3,203 in FY 2027 (by the
Army
and
Navy
); asks for Terminal High Altitude Area Defense (THAAD) interceptors have climbed 2,216 percent, from 37 in FY 2026 (by the
Missile Defense Agency
) to 857 in FY 2027 (by the
Army
); and requests for Tomahawk missiles have surged 1,740 percent, from 57 in FY 2026 (by the
Navy
) to 1,049 in FY 2027 (by the
Navy
and
Army
). While expensive, these exquisite munitions are intricately designed, high-performance systems optimized to undertake the most difficult missions. Multiyear agreements, combined with coproduction efforts under consideration as well as direct-to-supplier agreements, could potentially help to reduce the 25-to-51-month
manufacturing lead time
for these systems. But unfortunately, these and other exquisite legacy systems were fundamentally built for performance and not designed or funded for production at scale.
Those limitations, plus the need for a broader portfolio of munitions to better address threats such as swarms of Russian and Iranian Shahed unmanned autonomous systems, have helped lead to an increased focus on lower-cost and more producible systems. Low-cost, expendable munitions have long been included in the United States’ stockpiles, ranging from the Joint Direct Attack Munition guidance kit developed in the
1990s
to the
Coyote
counter-unmanned aircraft system pioneered the following
decade
. Yet the amount of attention and capital devoted to expanding affordable options within the U.S. arsenal is dramatically growing. The Pentagon launched the
Drone Dominance Program
in December 2025, for example, a
$1.1 billion
initiative to scale domestic small drone production, remove acquisition barriers, and rapidly field some
340,000
units by the end of 2027.
Since May 2026, the Pentagon and munitions manufacturers have signed several multi-year framework agreements to rapidly field substantial inventories of low-cost cruise missiles. These efforts include the Air Force’s Family of Affordable Mass Missile (
FAMM
) program for over
27,000
air-launched cruise missiles requested over the next five years and the Low-Cost Containerized Missiles (
LCCM
) program for some
10,000
ground-launched cruise missiles delivered by the beginning of 2030. Through the
Multi-Mission Affordable Capacity Effector
program, the Navy plans to request roughly
4,500
hypersonic air-launched cruise missiles through FY 2031. The Army seeks to equip its air and missile defense systems with modular interceptors costing under
$1,000,000
per unit under its low-cost interceptor (
LCI
) initiative. The
Missile Defense Agency
, meanwhile, aims to counter ballistic and hypersonic threats at less than
$750,000
per interceptor through an effort of the same name. To accelerate acquisition and production timelines for these new capabilities, the DOD is holding competitions for contracts between emerging defense companies in programs such as
Drone Dominance
and the
Army LCI
and signing framework production agreements with newer firms such as
Anduril
,
CoAspire
, and
Zone 5 Technologies
for LCCM and FAMM. These new munitions will be welcome additions to the DOD portfolio, but government and industry need to work closely to develop, rigorously test, deliver, and effectively incorporate these low-cost systems into the joint force.
The Pentagon’s FY 2027 budget request and subsequent initiatives reinforce the shifting DOD priorities within its munitions portfolio toward more affordable weapons. As Figure 1 shows, roughly 49 percent of munitions units the DOD requested for FY 2027 cost less than $600,000 per unit, which increases to over 70 percent in FY 2031 based upon projected munitions budget requests.
llm-echo 0.5
Simon Willison
simonwillison.net
2026-10-18 19:16:16
Release: llm-echo 0.5
I'm working towards a new LLM release, and testing PRs caused me to revisit the llm-echo debug plugin. This plugin provides a "model" which doesn't involve an LLM at all - it just repeats back the prompts that have been fed to it. The new release now updates the simulat...
I'm working towards a new
LLM
release, and testing PRs caused me to revisit the
llm-echo
debug plugin. This plugin provides a "model" which doesn't involve an LLM at all - it just repeats back the prompts that have been fed to it. The new release now updates the simulated token usage counts to take tool calls, system prompts, and reasoning tokens into account.
First I consider the prompt, then I decide what to say.
{
"prompt": "hi there",
"system": "",
"attachments": [],
"stream": true,
"previous": []
}
Token usage: 2 input, 24 output
There are various ways to convert integers to their string representation. These conversions are rarely a bottleneck, but they often show up while profiling certain applications. For instance, they're very common in
Lwan
while building the response headers.
To use Lwan as an example: initially,
snprintf()
was used to convert numbers. Although this works, it is quite boring, performance-wise.
The second approach was using the naïve algorithm, which basically divides the number by
10
in succession, writing backwards the result of modulus by
10
to a string, and then reversing the string when the number reaches
0
.
// Code based on https://code.google.com/p/stringencoders/size_tnaive_uint32_to_str(uint32_tvalue,char*str){char*wstr=str;// Conversion. Number is reversed.do*wstr++=(char)decimal_digits[uvalue%10];while(uvalue/=10);*wstr='\0';// Reverse stringstrreverse(str,wstr-1);returnwstr-str;}
This was fine for a while, but that string reversion step always bothered me. Why not just write the string backwards already?
I've then changed the code in Lwan to the following snippet. Note the nice trick of multiplying the size of an integer in bytes by
3
to obtain an approximation of the number of digits for
MAX_INT
, including the zero terminator, regardless of what
sizeof(int)
is.
Reducing writes to the array made this algorithm significantly faster. However, I eventually did what one should always avoid when tinkering with this kind of thing: I've changed the array lookup to an addition, without measuring if it would perform better, and committed the code anyway. The lookup table is ~9% faster. Ouch!
Last year, the Facebook Engineering team
posted a function
to convert integers to strings that manages to be even faster. They do use the same idea of avoiding having to reverse the string after they're done converting each digit, and they use a lookup table as well.
But the nice trick is that, instead of having a lookup table for 10 digits, there's a table for all pair of digits, from
00
to
99
. This cuts the amount of divisions by half, yielding a significantly faster algorithm: around 31% faster than the above snippet:
size_tfacebook_uint32_to_str(uint32_tvalue,char*dst){staticconstchardigits[201]="0001020304050607080910111213141516171819""2021222324252627282930313233343536373839""4041424344454647484950515253545556575859""6061626364656667686970717273747576777879""8081828384858687888990919293949596979899";size_tconstlength=digits10(value);size_tnext=length-1;while(value>=100){autoconsti=(value%100)*2;value/=100;dst[next]=digits[i+1];dst[next-1]=digits[i];next-=2;}// Handle last 1-2 digitsif(value<10){dst[next]='0'+uint32_t(value);}else{autoi=uint32_t(value)*2;dst[next]=digits[i+1];dst[next-1]=digits[i];}returnlength;}
The
digits10()
function is also another function that calculates the number of digits of a number in a very efficient manner. Even being performant, though, one can get rid of the call altogether: using a constant like
numeric_limits<uint32_t>::digits10
will keep the same interface. This is possible because the
dst
buffer should be large enough to hold all the digits of the largest 32-bit unsigned integer anyway.
Because of implementation details -- the function basically compares numbers to powers of 10 and recurses when the number of digits surpasses the maximum power that they're comparing to -- the speedup of using a constant length won't be significant for small numbers (one and two digits); but if you're optimizing to this level, using a constant won't hurt. So much so, that it is consistently faster on my machine (a Core i7 2640M laptop, with an up-to-date 64-bit Arch Linux):
Relative speedup of
facebook_uint32_to_str()
using
digits10()
and a constant value
That chart was obtained by using a
benchmark program
I wrote that will test all these ways of converting an integer to their string representation. To compare with other methods, here's the full chart:
Results for
snprintf()
omitted to not skew results. Spoiler: it's slow.
Unfortunately, there's a licencing issue that won't let me use this code in Lwan. The blog post doesn't mention the license. I've found this
two-digit lookup table in places unrelated to Facebook
as well, so I'm not sure who had this idea first. My go-to source of this kind of thing is usually
Hacker's Delight
, but even then it's not there.
August in Servo: CSS Grid, text selection, and more
Servo 0.6.0
contains all of the changes we landed in August, which came out to
417 commits
!
The big news is that we’ve turned on support for
CSS Grid
by default (
@nicoburns
,
#45621
).
This has had a huge positive impact on the visual appearance of many websites!
PeriodicWave
and
createPeriodicWave
on
BaseAudioContext
(
@kevlu93
,
#47492
)
This release also contains significant improvements to
navigation
,
document loading
, and
session history
, which are some of the
gnarliest
parts of the HTML specification. Who knew that loading
about:blank
was
so complicated
? The upshot to all this work is that pages that open additional windows or include iframes work much more reliably.
We upgraded to
SpiderMonkey v153
, which brings many new security and crash fixes to Servo’s JavaScript engine integration (
@sagudev
,
@Gae24
,
#47489
).
Navigating away from a document that
activated fullscreen mode
now exits fullscreen mode (
@shubhamg13
,
@jdm
,
#47123
).
Real world compat
CSS Grid enabled by default means that many websites with traditional grid layouts now look correct, like
rustweek.org
.
Panning gestures initiated by touch inputs now lock to the dominant axis (
@yezhizhen
,
#46983
).
This results in more predictable panning when interacting with pages in Servo.
Accessibility support
in Servo continues to make great strides; it can be enabled with the
--pref accessibility_enabled
command line argument.
Servo now reports
positions and sizes
for items in the content accessibility tree (
@philocalyst
,
@alice
,
@mrobinson
,
#46996
), allowing macOS VoiceOver to work more reliably.
We also report many
ARIA roles
for web content elements to accessibility toolkits (
@mukilan
,
#47318
).
We made a lot of progress on the
LargestContentfulPaint
performance metric, implemented behind the
--pref largest_contentful_paint_enabled
argument.
Servo now supports the
element
and
loadTime
attributes, (
@shubhamg13
,
#46553
,
#47475
), URLs for video element posters (
@shubhamg13
,
#43376
), accurate size information (
@shubhamg13
,
#43378
), and painting text nodes (
@shubhamg13
,
#47212
).
We’re continuing work on the
ServiceWorker
feature, which can be enabled with
--pref dom_serviceworker_enabled
.
This month we implemented the
CookieStore
interface behind the
--pref dom_cookiestore_enabled
command line argument (
@Taym95
,
#47044
) as well as the
Cache
interface (
@gterzian
,
#47220
).
Servo now supports a
disk-backed HTTP cache
that can be enabled with
--pref network_http_disk_cache
(
@Narfinger
,
#43819
).
This cache persists between runs, but there is not yet any way to clear it.
Embedding API
Breaking change:
WebView
::
toggle_sampling_profiler
has been removed (
@lumiscosity
,
#47014
).
To perform sampling profiling on Servo, follow the instructions in
the book
.
Building Servo now requires at least
Clang 19
on all platforms (
@jschwe
,
#47421
).
Additionally, the
cargo-ohos
tool is now required for building for OpenHarmony (
@jschwe
,
#47334
).
Debug builds on Windows can now complete successfully (
@jschwe
,
#47372
).
Linux arm64 builds have been customized to work on
Raspberry Pi 5
(
@mukilan
,
#47113
).
Any libservo embedders targeting the same platform will require a similar change if they are using jemalloc.
Meanwhile, the
OpenHarmony
port now supports external keyboards with US keyboard layouts (
@jschwe
,
#47359
).
Additionally, there are now better fallback font selections for CJK characters (
@RichardTjokroutomo
,
#47116
,
#47664
).
Setting the
device_pixel_ratio_override
preference is no longer ignored on Android and OpenHarmony (
@jschwe
,
#47081
).
On platforms that memory map font data (such as OpenHarmony and macOS), we can now save time that would otherwise be spent loading font files from disk (
@jschwe
,
#47029
).
Similarly, reading system fonts is no longer in the critical path of starting up the engine (
@Narfinger
,
@jdm
,
#46476
).
Canvas renderer worker threads can now be adjusted by the
thread_pool_canvas_workers
preference, allowing more performance granularity according to embedder needs. (
@jschwe
,
#46691
,
#47018
)
Historically,
about:memory
has reported all memory usage by Rust implementations of JS APIs as one undifferentiated
js/malloc-heap
number.
We now break it down by memory usage of nodes in document trees (
@pylbrecht
,
#46931
) and interfaces that are not part of the DOM (
@jdm
,
#47531
). We also report memory usage for the network stack’s cookie database (
@Narfinger
,
#47248
) and the canvas renderer backend (
@janeoa
,
@jdm
,
#46958
).
We’ve added an
experimental threadboost
mechanism (
@jschwe
,
@mrobinson
,
#46843
,
#47027
) that has been observed to improve Speedometer results by
50%
and allow canvas rendering to reach 60 FPS.
This is initially enabled for OpenHarmony, but future expansion to other Linux-based platforms is expected.
More on the web platform
We upgraded to
resvg 0.48
, fixing
many issues with SVG images
with missing width/height attributes that specified a
viewBox
(
@nicoburns
,
#46937
).
Upgrading to
Taffy 0.14
fixed a number of
CSS grid-related crashes
, support for grid names, better intrinsic sizing, and improved performance (
@nicoburns
,
#47031
,
#47493
).
We also fixed some issues in the Taffy grid integration for more accurate baselines (
@nicoburns
,
#47518
).
Session history traversals (i.e. navigating backwards or forwards in history) now wait for any outstanding traversal to complete (
@mrobinson
,
#47293
,
#47485
).
Meanwhile, navigations to
about:blank
are skipped if the initial about:blank document is present (
@jdm
,
#47074
).
For non-about:blank content, we also made the document loading phases more reliable (
@TimvdLippe
,
@mrobinson
,
#47426
), improved conformance of
javascript:
URL evaluation and navigation target selection (
@mrobinson
,
#47486
,
#47516
), and addressed longstanding compatibility issues with cross-origin
Window
and
Location
objects (
@mrobinson
,
#47549
).
Our media playback has improved; we fixed several issues around
canPlayType()
on
HTMLMediaElement
that allow Servo to report that
MP4 content is playable
(
@jdm
,
#47612
,
#47641
,
#47670
).
Input elements with the
autofocus
property inside of a
<dialog>
now receive focus when that dialog is opened (
@skyz1
,
@mrobinson
,
#45826
).
Servo is also on
thanks.dev
, and already
36 GitHub users
(+1 from July) that depend on Servo are sponsoring us there.
If you use Servo libraries like
url
,
html5ever
,
selectors
, or
cssparser
, signing up for
thanks.dev
could be a good way for you (or your employer) to give back to the community.
We now have
sponsorship tiers
that allow you or your organisation to donate to the Servo project with public acknowlegement of your support.
If you’re interested in this kind of sponsorship, please contact us at
[email protected]
.
Tom the Dancing Bug’s Inner Hive, and Harvey Richards, the Greatest Lawyer in the History of Fiction
Daring Fireball
tomthedancingbug.com
2026-10-18 18:53:00
Ruben Bolling’s long-running Tom the Dancing Bug is one of my favorite comic strips. I’ve been a huge fan since the early 1990s, when I started reading it in alternative newspapers. (Newspapers were sort of like websites, excepted they were printed daily or weekly. I swear.) Back in 2012 Bolling — n...
What is the Inner Hive? It’s a subscription service. It’s a secret society. It’s a ragtag group of ne’er-do-wells with ideas that are so crazy, they just might work.
It’s the team that literally makes it possible for Tom the Dancing Bug to exist in this world.
And YOU are invited to become a member!
Every week, you’ll get an email with that week’s Tom the Dancing Bug AT LEAST A DAY BEFORE IT’S PUBLISHED ANYWHERE ONLINE. Plus exclusive commentary, insights, process pics, extra comics, jokes, puzzles, recipes, and all benefits accruing.
How can you join? Let me count the ways:
You can join on
Patreon
, now the most popular platform for new Inner Hivers, offering not only emails but also a website on which you can read the posts. Plus, the Patreon option offers different levels of membership, with varying benefits.
(Monthly or annual automatic recurring payments.)
You can join at
MailChimp/CampaignZee
, the platform on which the Inner Hive was first launched, way back in 2012, offering weekly emails only (no website option).
(Semi-annual automatic recurring payments.)
You can join on
Substack
, the latest platform to join the Inner Hive family.
(Monthly or annual automatic recurring payments.)
No matter how you join, you’ll earn the adoration of a grateful nation and world.
Friends of Tom the Dancing Bug
: If you don’t want to join the Inner Hive, but want to make a grant to the Tom the Dancing Bug enterprise, you can become a
Friend of Tom the Dancing Bug
by making a payment
of any size
HER
E
. You will get a nifty electronic Thank You message.
Thank you for reading this message, and I hope to see you on the team.
–
Ruben Bolling
The 256 numbers in the key schedule of Ron Rivest’s RC2 cipher were said to come from π, but the method was never published. A card shuffle that uses π’s digits as dice reproduces both of RC2’s tables exactly.
Summary
RFC 2268 says the 256-byte table PITABLE in RC2’s key schedule is “based on the digits of PI”, but gives no method, and a second table in the same document is given no origin at all. Both are reproduced exactly by the Fisher–Yates shuffle, using the decimal digits of π as its source of randomness: each draw reads exactly three digits, and draws that would bias the result are discarded. PITABLE starts at the leading 3; the second table starts four digits later. Rivest’s MD2 hash uses the same shuffle but reads a varying number of digits per draw, which may be why the connection went unnoticed. This is very likely how the tables were originally made, though how Rivest arrived at the rule is not documented. The question was raised in public by an engineer at RSA Data Security in 1996; an extensive search found no earlier public answer. The result has no bearing on RC2’s security.
1
The question
RC2 is a block cipher Ron Rivest designed in the late 1980s. To turn a key into the longer internal key it actually encrypts with, it passes every byte through a fixed table: the numbers 0 to 255 in a scrambled order. Every implementation of RC2 carries the same 256 numbers.
A table like this is where a designer could, in principle, hide a weakness. Cryptographers guard against that suspicion by deriving such tables from a public constant like π and showing the derivation, so anyone can rebuild the table and confirm nothing was chosen by hand. These are known as “nothing-up-my-sleeve” numbers, and they only reassure if the derivation is public.
RC2 named its constant but never its derivation. Rivest’s specification, RFC 2268, calls the table “an array of ‘random’ bytes based on the digits of PI” and prints it without a method.
1
When the cipher’s code leaked in 1996, an engineer at RSA Data Security, which owned RC2, listed in public as an open question how one could tell whether the table came from π.
2
No answer followed, and some implementations, such as LibTomCrypt, still carry the comment from the leaked code: “probably derived somehow from pi”.
3
,
4
Section 5 tells that history. This note gives a construction that reproduces the table exactly.
2
The answer
Picture 256 cards numbered 0 to 255, laid out in order. Take each card in turn, from the second to the last, and swap it with a randomly chosen card at or before its own position. This is the Fisher–Yates shuffle, the standard way to shuffle fairly, and it was not secret. What was never published is where the randomness came from. The tables are reproduced exactly when the dice are the decimal digits of π, read
exactly three digits for every draw
, starting from the first 3. Figure 1 plays the first steps.
The shuffle, step by step
Shuffle
217
120
249
196
25
221
181
237
Published
217
120
249
196
25
221
181
237
The first eight of 256 positions, shown in decimal. All 256 match.
This animation requires JavaScript. The first steps are: read 314, so card 1 swaps with place 314 mod 2 = 0; read 159, so card 2 swaps with place 159 mod 3 = 0; read 265, so card 3 swaps with place 265 mod 4 = 1; and so on.
Figure 1.
The first nine steps of the construction, then the result. At each step the next three digits of π choose where the newest card goes: the remainder after dividing by the number of available places.
Written out precisely, the construction is Algorithm 1. The discard step keeps the draws fair. When the number of available places does not divide 1,000 evenly, a draw that lands in the few highest values (960 to 999 when there are 240 places, for example) is discarded and three new digits are read. Over the whole shuffle this happens 21 times, two of them at the run of six 9s at the 762nd decimal place of π known as the Feynman point.
a
In total the shuffle uses 828 digits.
Algorithm 1.
Construction of PITABLE
input: d = 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, … (decimal digits of π)rand(n):
loop
x ← next three digits of d // 0…999
if x < n · ⌊1000 / n⌋:
return x mod n
// otherwise discard x
S ← [0, 1, …, 255]
for i ← 2 to 256:
j ← rand(i)
swap S[j], S[i − 1]
return S // = PITABLE
Why it may have stayed hidden.
In 2014 Rivest confirmed that his MD2 hash builds its π table with the same shuffle.
5
But MD2 reads as few digits as each draw needs: one digit while there are up to 10 places to choose from, two up to 100, three beyond that. Applied to RC2, MD2’s exact rule matches 1 of 256 entries, no better than chance, so the obvious test would have suggested the tables were unrelated. The only change needed is to read three digits every time.
3
Verification
Algorithm 1 reproduces RFC 2268’s PITABLE in all 256 positions. Figure 2 runs it in your browser, alongside five plausible alternatives, and compares every output with the published table.
Does the method reproduce Rivest’s table?
Alternatives:
…
of 256 positions match the published table
Same number as the published table
Different number
Numbers shown in hexadecimal, as printed in the RFC
This figure requires JavaScript. The
reproduction script
performs the same comparison and the controls in Table 1.
Figure 2.
Each method is run on this page, with π and e computed in integer arithmetic, and its 256 outputs compared position by position with the tables printed in RFC 2268. A random shuffle would match about one position.
The match is not the kind of coincidence a broad search could stumble on. There are about 10
507
possible orderings of 256 numbers. The search that found the rule tried roughly 100,000 candidates (four digit sources, seven ways of drawing a number, six shuffle orders, 300 starting points, and both the table and its inverse), and exactly one matched in full: the simplest. Variants that change the digit source or the width of each draw fall to chance level. Dropping the discard step leaves the first 112 draws unchanged, so 29 early positions still match before it drifts (Table 1).
Table 1.
Positions of PITABLE reproduced by Algorithm 1 and by nearby alternatives.
Method
Matching
Algorithm 1: decimal π from the leading 3, three digits per draw
256 / 256
Algorithm 1 without the discard step
29 / 256
Hexadecimal digits of π in pairs, keeping first occurrences
2 / 256
MD2’s digit rule (one, two or three digits per draw)
1 / 256
Algorithm 1 starting one digit later
1 / 256
Algorithm 1 on the digits of e
0 / 256
The hexadecimal method in Table 1 is included because, when asked “how was the RC2 PITABLE generated from the digits of pi” on 17 October 2026, Google’s AI Overview described it. Its own worked example begins
24 3f 6a
; the published table begins
d9 78 f9
.
The result was reproduced twice after it was found: by a second implementation written from the RFC and a one-paragraph description of the rule, without access to the first, and by a third using its own computation of π and a fresh copy of the RFC.
4
The second table
Section 6 of RFC 2268 prints a second permutation of 0 to 255, the RFC’s
Table[]
, called the version table here. It encodes an effective key length of 1 to 255 bits as the
RC2Version
parameter of RC2-CBC, as used in PKCS #5 and related standards,
6
and the RFC says only that it “is not the same table that appears in the key expansion phase”.
1
It is Algorithm 1 started at the fifth digit of π (
5926…
) instead of the first. It matches in all 256 positions, again using 828 digits with 21 discarded draws. Both tables in the RFC can therefore be produced by one generator, run from two starting points.
5
How the table stayed unexplained
5.1
An exportable cipher, 1987–1989
In the 1980s the United States controlled the export of strong encryption much as it controlled weapons, and the National Security Agency carried out the technical review. Lotus Development was preparing to sell Notes, a business application with encryption built in, developed for it by Ray Ozzie’s company Iris Associates, and could not obtain an export licence for it using the standard cipher, DES. According to Steven Levy’s account, the NSA agreed in mid-1987 to evaluate a replacement. Lotus engaged Rivest, who designed RC2 within a few weeks; Lotus paid for the work and RSA Data Security held the rights.
7
(Rivest’s 1997 draft specification is dated “Created 1987”; a 1998 paper he co-authored gives the design date as 1989.
1
,
8
)
Figure 3.
Ray Ozzie, creator of Lotus Notes, who led the export negotiations with the NSA (photographed 2011).
Rivest submitted the design to the NSA, which asked for “a couple of tweaks”. Ozzie, who led the negotiations, put the obvious question to Rivest:
“How do you know they’re not doing something to weaken it?”
Ray Ozzie to Ron Rivest, as recounted by Levy
7
Rivest judged the suggestions technically sound and adopted them. Levy’s account does not say what they were.
Figure 4.
NSA headquarters, Fort Meade, Maryland. The agency reviewed commercial cryptography for export.
5.2
Secrecy and disclosure, 1989–1998
In 1989 the NSA verbally offered Lotus an export licence for RC2 with keys limited to 32 bits. In 1992 an agreement negotiated through the Software Publishers Association gave expedited export approval to retail software using RC2 or its sibling RC4 with keys of at most 40 bits,
9
on the condition that RSA and its licensees keep the designs secret.
7
RC2 shipped worldwide inside commercial products while its internals, including the table, remained unpublished.
Figure 5.
A protest T-shirt from the period of export controls. It carried RSA code and declared itself “classified as a munition”.
Figure 6.
The table in the anonymous source posting to sci.crypt, January 1996 (excerpt; lines reflowed).
3
On 29 January 1996, RC2’s source code was posted anonymously to the Usenet group sci.crypt; references to debugging tools suggested it had been reverse-engineered. Four days later Robert Baldwin of RSA Data Security posted a list of open technical questions about the cipher to the cypherpunks mailing list. The first concerned the table:
“How can you tell whether the permutation is based on some sequence of digits from PI?”
R. W. Baldwin, “RC2 technical questions”, 2 February 1996
2
No answer appears in the thread. In March 1998 Rivest published RC2 as RFC 2268, printing the table in full without a construction.
1
A paper he co-authored the same year states only that the table “was derived from the expansion of π”.
8
5.3
A related table, explained in 2014
Rivest’s MD2 hash function contains its own 256-byte permutation, “constructed from the digits of pi” according to its specification,
10
and it too was unexplained for years. In 2013, commenters on Hacker News and Cryptography Stack Exchange noted that both the MD2 and RC2 tables remained unexplained.
11
In 2014 a Stack Exchange user obtained the MD2 construction from Rivest by email and posted it.
5
We found no published work that applies it to RC2.
Figure 7.
Ron Rivest, designer of RC2 and MD2.
6
Discussion
It helps to separate three claims.
Established by computation:
Algorithm 1 reproduces both published tables exactly, and anyone can check this with the published script.
Strongly supported, but not proven:
this is the method, or something very close to it, by which the tables were originally made. A short rule that matches every entry of both tables, while its near variants fail, is hard to explain any other way, and the rule is Rivest’s own documented MD2 shuffle with one change.
Not established:
exactly how Rivest arrived at it, including whether he tried other rules or starting points before settling on this one. The tables alone cannot tell us that.
The last point matters for the “nothing up my sleeve” question. The 256 entries were not chosen one by one: they follow from a short rule applied to π. That leaves far less room for deliberate selection than a table chosen entry by entry, but it does not remove it entirely. A designer could, in principle, have tried several simple rules or starting points and kept one; the second table’s different starting point shows that such choices were made. Nothing here tells us what the NSA’s 1987 changes were, or whether they touched this table.
The result does not affect RC2’s security. The cipher has long been deprecated, though it persists in older PKCS #12 certificate files, and knowing the origin of a public table makes it neither weaker nor stronger. Rivest presumably always knew the method; the claim here is only that it had not been published.
The search for earlier work covered the 1996 cypherpunks archive and part of the sci.crypt discussion (Google Groups’ search was rate-limited), the 1998 design paper, the Japanese government’s CRYPTREC evaluation of RC2, Cryptography Stack Exchange, Hacker News, GitHub, X, IACR ePrint, and searches in Chinese, Russian and Japanese. It found the question asked several times and never answered. Semantic Scholar and print-only sources could not be searched fully, so an earlier explanation may exist in a source we did not reach. Corrections are welcome and will be credited here.
7
A note on method
This result came from an experiment in using AI agents on neglected problems whose answers can be checked exactly. In October 2026, Anthropic reported that its model Claude had traced the seeds of the NIST elliptic curves to a standard C library random-number generator seeded with timestamps from 1997 and 1998.
12
,
13
I set up a pipeline that collects long-unanswered questions, ranks them by whether a solution would verify itself, and assigns the most promising to AI coding agents.
RC2’s table was the first result. The agent, Claude, reasoned that if one of Rivest’s π tables had been explained, the other might yield to the same method, and found the three-digit rule. OpenAI’s Codex wrote the independent second implementation described in Section 3, and a later sweep of other “derived from π” tables found the second RC2 table. None of this needs to be taken on trust: the script in the repository computes π and checks both tables against the RFC in under a second.
Notes
a.
The Feynman point is the sequence 999999 beginning at the 762nd decimal place of π. Algorithm 1 reaches it while choosing among 240 places, where any value of 960 or more is discarded, so both 999s are discarded.
[7]
S. Levy.
Crypto: How the Code Rebels Beat the Government, Saving Privacy in the Digital Age
. Viking, 2001.
[8]
L. R. Knudsen, V. Rijmen, R. L. Rivest, M. J. B. Robshaw.
On the Design and Security of RC2
.
Fast Software Encryption
, LNCS 1372, 1998, pp. 206–221.
[9]
RSA Laboratories.
What is RC2?
In
Frequently Asked Questions about Today’s Cryptography
, 1998 (archived mirror).
Revisions.
17 October 2026: first published. 18 October 2026: history of the cipher added, animated walkthrough added, format revised, and the distinction between what is computed and what is inferred made explicit.
Verizon Is Going to Charge $10/Month for iPhone Handoff
Daring Fireball
www.verizon.com
2026-10-18 18:20:06
Verizon, in a post headlined “Switch to Verizon and Get the New iPhone Duo Now. No Trade-In Needed.”:
Verizon will support iPhone Handoff, giving customers the
flexibility to use a single Verizon phone number seamlessly
across two compatible iPhone models. Whether using the pocketable
iPhone Duo...
NEW YORK, N.Y.
—It’s official. Verizon will offer
iPhone Duo
, the first foldable iPhone, with pre-orders beginning Friday, October 16. iPhone Duo hits stores on Friday, October 23, joining
iPhone 18 Pro
and
iPhone 18 Pro Max
. With a breakthrough design that opens to a versatile 7.6-inch display for gaming and multitasking and closes to a pocketable 5.4-inch screen, there’s never been a better time to upgrade than with iPhone Duo. Built to last with a durable precision hinge, it pairs an advanced camera system with impressive all-day battery life.
For customers who are tired of complexity and want a simple, cost-effective plan alongside the new iPhone lineup, Verizon offers simple pricing, no activation or upgrade fees and a brand-new iPhone every single year. Plus, Verizon is offering the latest Apple products, including
Apple Watch Series 12
,
Apple Watch Ultra 4
and
AirPods 5
.
Simplicity moves beyond tiered network confusion and provides a simple choice for mobile service, with options to get a new phone every year. With America’s Most Reliable 5G Network
*
for everyone at an affordable price, including unlimited 5G Ultra Wideband data, 10GB of premium mobile hotspot and roaming in Canada and Mexico all standard. That’s it. That’s the plan.
Verizon will support iPhone Handoff, giving customers the flexibility to use a single Verizon phone number seamlessly across two compatible iPhone models. Whether using the pocketable iPhone Duo on the go or iPhone 18 Pro for work, customers can switch active status between devices at any time while keeping full access to Verizon’s 5G network. iPhone Handoff will be available from Verizon for $10/month on compatible iPhones models running iOS 27.
Goodbye activation and upgrade fees:
All postpaid customers on all phone and connected device plans can opt-in to Verizon’s Loyalty program and say goodbye to activation and upgrade fees—that’s up to $40 in fees per device.
Verizon Dollars:
A first-of-its-kind program that rewards customers with 3% back in Verizon Dollars every single month, just for being a customer. Verizon Dollars can be redeemed for devices (including the latest iPhones models), accessories or up to 5x for each Verizon Dollar from top brands.
Verizon Shine, every Monday, every day, all year-round:
The loyalty program that gives customers a reason to look forward to Monday, all year-round. All Verizon customers on any plan can enter weekly for a chance to win once-in-a-lifetime experiences, alongside daily drops including tickets to concerts and sporting events, exclusive merchandise, dining vouchers, gift cards and more. Opt-in into loyalty in one simple step through the My Verizon app.
iPhone Duo
is the first foldable iPhone, featuring a breakthrough design that’s beautiful, versatile and durable. iPhone Duo opens to a large 7.6-inch inner display for viewing content, gaming, and multitasking, and closes to a compact, pocketable 5.4-inch outer display. Built to last with an innovative hardware design and precision hinge, iPhone Duo is powered by A20 Pro to deliver pro performance and impressive all-day battery life, and offers an advanced camera system, with the folding design unlocking fun new ways to use the camera that aren’t possible on any other iPhone. iOS 27 is also reimagined for the versatile ways users can interact with iPhone Duo.
iPhone 18 Pro
and
iPhone 18 Pro Max
offer the new 48MP Fusion Main camera with variable aperture, the most advanced camera Apple has ever made, and new Pro controls let users customize their experience. Powered by A20 Pro, iPhone 18 Pro and iPhone 18 Pro Max deliver huge leaps in battery life and performance. iPhone Duo and iPhone 18 Pro models feature Apple Intelligence
¹
and Siri AI
²
, an entirely new version of Siri, rolling out in beta in English with iOS 27, to bring AI capabilities together with a user’s personal context to become an intelligent personal hub with privacy and security at the core. iPhone Duo is available in two refined colors: star white and night sky. iPhone 18 Pro and iPhone 18 Pro Max are available in four elegant finishes: black, silver, glacier and an all-new burgundy.
iPhone Duo and iPhone 18 Pro models feature eSIM
³
, offering greater flexibility, better security, seamless connectivity compared to traditional physical SIM cards, and more battery life on eSIM-only models. iPhone Duo features an eSIM-only design that saves internal space to maximize battery capacity while eSIM-only models of iPhone 18 Pro and iPhone 18 Pro Max take advantage of the space formerly occupied by the physical SIM with a larger battery that provides two additional hours of video playback.
Apple Watch Series 12
and
Apple Watch Ultra 4
offer the most accurate heart rate sensing in a wearable
⁴
. Both new models have been engineered with the new Health Sensing System and S11 chip to offer an enhanced suite of health and fitness features including a new readiness score, higher-frequency heart rate and heart rate variability (HRV) measurements, plus extended workout battery life and faster charging. Apple Watch Series 12 is available in 42mm and 46mm sizes in an array of beautiful finishes, including dark bronze, black, light gold and space gray aluminum; radiant gold and natural titanium; and a stunning ceramic material, in pearl white and night blue. Apple Watch Ultra 4 is available in natural and black titanium.
With watchOS 27, Apple Intelligence comes to the wrist, bringing Siri AI to Apple Watch Series 12 and Apple Watch Ultra 4 with personal context understanding and broad world knowledge
⁵
. Arriving later this year, new Audio Intelligence features roll out in beta in English to help users stay aware of the world around them, catch what they missed, and remember key moments—with user control, privacy, security, and accessibility at the center of their design
⁶
—along with a redesigned Health app on iPhone and iPad, starting in U.S. English, including a new Longevity tab with a Health Age feature showing how metrics are tracking relative to a user’s age
⁷
.
AirPods 5
deliver the industry’s best Active Noise Cancellation (ANC)
⁸
in an open-ear design, powered by a new multiport acoustic architecture and next-generation Adaptive EQ for even more immersive sound. Their breakthrough open-ear ANC removes up to 50 percent more external noise compared to the previous generation, alongside a more natural Transparency mode. Combined with Siri AI and iPhone, AirPods enable users to draw on their personal context and get answers with broad world knowledge, entirely hands-free
¹
. Users can also respond to Siri using head gestures or use Live Translation to help connect across languages. For users who want even more,
AirPods 5 with Wireless Charging Case
adds longer battery life and on-stem volume control
⁹
.
Gurman on HomeView: ‘Finished Units Have Been Sitting Boxed Up in Warehouses for the Better Part of a Year’
Daring Fireball
www.bloomberg.com
2026-10-18 17:58:33
Mark Gurman, today, in his weekly Power On column for Bloomberg (gift link):
Without a serviceable version of the new assistant, Apple couldn’t
deliver the experience it had envisioned. That left the hardware
ready to go, but the software nowhere near finished.
So Apple postponed the HomeView r...
We've detected unusual activity from your computer network
To continue, please click the box below to let us know you're not a robot.
Why did this happen?
Please make sure your browser supports JavaScript and cookies and that you are not
blocking them from loading.
For more information you can review our
Terms of Service
and
Cookie Policy
.
Need Help?
For inquiries related to this message please
contact
our support team
and provide the reference ID below.
This is a small server that runs in your own Cloudflare account. You link your phone to it once, the way you'd link WhatsApp Web, and from then on any MCP client (Claude Code, Claude Desktop, anything that speaks MCP) can search and read your chats. It can read and search your messages, and remember names you give it for phone numbers. It can't send anything.
Ask your agent things like:
"What did Dana say about the flights?"
"Find every message where someone mentioned the lease, across all my chats."
"Summarize what I missed in the family group this week."
How it works
Your phone stays the source of truth. The server is a linked device that your agent talks to.
It doesn't stay connected to WhatsApp. When your agent asks for something, and once a day, it connects, collects whatever WhatsApp queued for it since last time, writes that to its own database, and hangs up. Your phone keeps working normally and keeps getting notifications.
Your messages live in a SQLite database inside a Durable Object in your Cloudflare account. Nothing goes anywhere else.
Set it up
You need a Cloudflare account on the Workers Paid plan (see the note below), Node 20 or later, and your phone.
git clone https://github.com/finereli/whatsapp-mcp
cd whatsapp-mcp
npm install
# 1. A place for the sign-in tokens. Paste the id it prints into wrangler.jsonc.
npx wrangler kv namespace create OAUTH_KV
# 2. A password for the page that links your phone. 12+ characters.
npx wrangler secret put OWNER_PASSWORD
# 3. Deploy.
npm run deploy
Wrangler prints your URL, something like
https://whatsapp-mcp.your-name.workers.dev
. Open it. The front page has the two remaining steps:
Link WhatsApp.
Scan the QR code with WhatsApp (Settings, Linked Devices, Link a Device). If you're on the phone itself and can't scan a screen, use the phone number option instead. The first link imports your history. The page shows progress, and you can close it.
Connect your agent.
In Claude Code:
claude mcp add --transport http whatsapp https://your-url/mcp
Then type
/mcp
and sign in with the password. Other clients: point them at the same
/mcp
URL.
If you want your own domain, see the comments at the bottom of
wrangler.jsonc
.
The Workers Paid note
Importing a large history decodes a lot of data in one go, and the default CPU limit on Workers is too small for it.
wrangler.jsonc
raises it, and raising it needs the paid plan, which is a few dollars a month. I haven't tried the free plan. If you're on it, remove the
limits
block and expect the first import to be fragile.
Things to know
This isn't official.
WhatsApp has no API for reading your own personal messages. This uses the same protocol WhatsApp Web uses, through an open source library (Baileys). That's against WhatsApp's terms. For a linked device that only reads, the practical risk is low, but it isn't zero. Use it on your own account, and don't use it to send messages.
You get what WhatsApp sends.
The first link imports whatever history WhatsApp decides to hand a new device. It may not be everything. It only does this once per link. To import again, relink (your stored messages are kept, and a re-import fills in anything missing).
Some chats show up as phone numbers.
WhatsApp doesn't give a linked device every contact name, and most of these are one-off messages from people you never saved. For the ones that matter, your agent can fix it: it lists the unnamed chats, looks the numbers up in your contacts with whatever contacts tool it already has (a Google Contacts or Gmail connector, for example), and saves the names. The server never connects to a contacts service itself. See "Naming chats" below.
Media isn't downloaded.
Photos, voice notes and documents appear as labels like
[image]
or
[voice note 12s]
, with the caption if there was one. Nothing is transcribed.
It's for one person.
One deployment is one WhatsApp account and one owner. That's deliberate: each deployment holds a full message history and a live login to the account, so everyone should run their own.
Relinking.
If your phone says the device was removed, or you want to start over, ask your agent to run
relink
, or open
/setup
and choose "Unlink and scan again". You scan a new QR code. Stored messages are kept.
What your agent can do
Tool
What it does
list_chats
Chats, most recent first. Filter by name or number.
get_messages
Read one chat. Page back or forward by date.
search_messages
Full-text search across everything, or within one chat.
unnamed_chats
Chats known only by phone number, busiest first, with the last thing the other person said.
set_contact_names
Save names for phone numbers, in any format. Names stick to the number, so they also show up in groups.
sync_now
Pull new messages right now.
link_status
Is it linked, when did it last pull, how much is stored.
relink
Unlink and start over. A human has to scan the new QR code.
Every read tool first tops up from WhatsApp if the stored copy is more than ten minutes old.
Naming chats
WhatsApp only gives this server the names it knows. The rest show up as phone numbers. Rather than have the server log in to a contacts service (which means a cloud project, consent screens and, for Google, an app review), it hands the job to your agent, which usually already has a way to reach your contacts.
Say "find names for my unnamed chats". The agent calls
unnamed_chats
, matches the numbers against your contacts, and saves what it finds with
set_contact_names
. It won't find everyone: most unnamed chats are a single message from a stranger.
Agents get nudged toward this on their own. The server's instructions mention it, and so does every "no chat found" and "no matches" result, because that's the moment an agent is stuck on a name.
link_status
also says how many chats are unnamed.
For agents, and people adapting this
Everything below is for whoever is changing the code, including an AI agent working on a fork. The top of this file is for the person who owns the deployment.
Shape of the thing
MCP client ──OAuth──> Worker (src/index.ts)
├─ /mcp ───────────> mcp.ts: tools, one fresh McpServer per request
├─ /, /setup, /authorize, /login/*, /pair/* (landing, sign-in, pairing UI)
└─ cron 04:00 UTC ──> pull()
│ RPC
v
WhatsAppStore (Durable Object, one instance named "owner")
├─ SQLite: auth keys, messages, chats, contacts, FTS5 index
└─ Baileys socket, opened only during a session (pairing or pull)
│ WebSocket
v
WhatsApp servers
One Durable Object holds everything. Its SQLite is both the Baileys auth store and the message store. The Worker is stateless apart from a KV namespace the OAuth provider uses for tokens and a short-lived "pending sign-in" record.
Extracts the wasm from Baileys' Rust bridge. Runs on
npm install
.
local-export/
A separate one-off script that dumps your history to JSON files with no server. Not part of the deployment.
How sessions work
All WhatsApp traffic happens inside
runSession()
in
whatsapp-do.ts
. There are two kinds:
Pairing
(
startPairing
). No credentials yet. Baileys emits QR strings, kept in memory and rendered to SVG by
pairStatus()
. After a scan WhatsApp closes the socket with code 515 (restart required), and the session reconnects with the new credentials. History arrives as
messaging-history.set
chunks with a
progress
percentage. The session ends when WhatsApp reports 100 percent and the stream has been quiet for a few seconds.
Pull
(
pull
). Reconnects with stored credentials. WhatsApp delivers whatever it queued while we were away, then signals
receivedPendingNotifications
. The session ends after a few quiet seconds.
Callers share one session: a second
pull()
while one is running gets the same promise.
A pairing session outlives the HTTP request that started it.
startPairing
sets a Durable Object alarm, and
alarm()
awaits the session promise. An in-flight alarm handler is what keeps the object alive. The pairing page only watches; closing it doesn't stop the import.
Idle detection counts only data events (
messaging-history.set
,
messages.upsert
), not connection chatter. Counting everything keeps a session open forever, because presence and contact updates never stop.
Data model
All in the Durable Object's SQLite (
store.ts
,
initSchema
).
messages(chat, id, ts, from_me, sender, push_name, type, body)
, primary key
(chat, id)
. Media is a label in
body
. Edits update
body
; deletes set it to
[deleted]
.
messages_fts
, an FTS5 index over
body
, kept in sync by triggers.
chats(jid, name, is_group)
,
contacts(jid, name, notify)
and
custom_names(jid, name)
. Display names resolve by WhatsApp's chat name, then WhatsApp's contact name, then a saved name, then the person's own push name, then the number.
custom_names
is what
set_contact_names
writes.
alias(lid, pn)
. WhatsApp is moving to anonymous
@lid
identifiers. This maps them to phone-number JIDs, and
addAlias
folds existing rows into the phone-number form so one person is one chat.
auth(k, v)
, Baileys credentials and signal keys, JSON with Buffers encoded by Baileys'
BufferJSON
.
meta(k, v)
, currently just
last_pull
.
Ingest is idempotent. Re-importing history upserts: it fills in a missing
sender
or
push_name
and never duplicates. That is what makes relinking safe.
What to know before changing things
These all cost real time to find. Read them before touching the Baileys parts.
Baileys needs three shims to run on workerd.
ws
: the package needs Node sockets.
ws-shim.ts
wraps the Workers WebSocket, opened with
fetch()
and an
Upgrade
header because that's the only way to set the
Origin
header WhatsApp checks.
whatsapp-rust-bridge
: it ships its wasm as base64 and compiles it at runtime, which workerd forbids.
vendor-bridge.mjs
writes the wasm to a file and patches the loader to import it as a
CompiledWasm
module. The
vendor/
folder is generated, not committed.
Timers: Node timers have
.unref()
and workerd's don't.
polyfills.ts
adds it. It must be the first import in both the Worker and the Durable Object module.
lru-cache
autopurge breaks the first import.
Baileys creates caches with
ttlAutopurge: true
, which starts one
setTimeout
per entry. workerd allows 10,000 pending timers per object, and the first history sync blows through that with
QuotaExceededError
.
lru-shim.ts
turns autopurge off. Expired entries are still dropped lazily on access.
QR pairing never sets
creds.registered
.
That flag belongs to the mobile registration flow. "Is this linked" is
creds.me?.id
.
History comes once per link.
If a first import fails halfway, that history is gone until you relink. Don't ship a change to ingest code without testing it against a real first link.
Group senders arrive in two places.
Live messages have
key.participant
. History messages put it on
msg.participant
. Read both.
Pin Baileys exactly.
It's a prerelease and its API moves between release candidates.
Deploys don't evict a busy Durable Object.
An object with an active session keeps running old code until the session ends. Renaming the class with a migration didn't evict it either. If you've shipped a fix and the object still misbehaves, stop sending it requests and wait three to five minutes. Every probe, including
/debug
, resets its idle timer, so polling a stale object keeps it stale. Baileys also leaks interval timers when a socket closes;
finish()
in
whatsapp-do.ts
clears them so the object can go idle at all.
Logging out takes two steps.
logout()
first connects and calls Baileys'
logout()
, so the device disappears from the phone's list, then clears local credentials. If the first step fails it says so in the debug events, and the user has to remove the device by hand.
WhatsApp stores a placeholder where a name should be.
Chats it has no contact for are named after the number, sometimes masked (
+972∙∙∙∙∙∙∙20
), in the chat name and the contact name.
numberLike
in
store.ts
treats those as no name, and ingest refuses to store them. Before that fix a placeholder outranked a real saved name.
Don't call
markOnlineOnConnect
.
It's set to false on purpose. Marking the linked device online makes the phone stop showing notifications.
Configuration
Name
Kind
Purpose
OWNER_PASSWORD
secret
Password mode (default). 12+ characters or sign-in refuses.
OWNER_EMAIL
var
Login-service mode: the one email allowed in.
OPERATOR_NAME
var, optional
Shown on the privacy page as who runs this server.
DEFAULT_COUNTRY_CODE
var, optional
Country code (digits, no plus), used when your agent saves a number written without one, e.g.
972
.
LOGIN_ORIGIN
var
Set this to switch to login-service mode.
ALLOWED_ORIGINS
var
Login-service mode: comma-separated origins whose tokens are accepted. Production should list only production.
PIN
secret, optional
32+ random characters. Enables the
/debug
routes via an
x-pin
header. Leave it unset to leave them off.
OAUTH_KV
binding
Token store for the OAuth provider and pending sign-ins.
WA
binding
The Durable Object.
Keep a deployment's own values (domain, KV id, email) in
wrangler.local.jsonc
, which is gitignored, and deploy with
npm run deploy:local
.
wrangler.jsonc
is the template other people start from.
Adapting it
Add a tool.
Register it in
mcp.ts
and put the SQL in
store.ts
. Read tools should call
fresh()
first. Keep tools read-only unless you mean otherwise. If a failure leaves an agent stuck, say in the tool result what to try next, the way
NAME_HINT
does for missing names.
Change who can sign in.
auth.ts
picks a mode (
authMode
) and the routes in
index.ts
follow it. To add another identity provider, add a mode there and a callback route. The rest of the code only sees an opaque bearer token.
Make it multi-user.
Today the Durable Object is addressed by the fixed name
owner
(
wa()
in
index.ts
,
handleMcp
in
mcp.ts
), and
userId
is the constant
'owner'
in the OAuth props. To go multi-user, derive both from the signed-in identity and key the object on it. Think about whether you want to hold other people's message history first.
Other ways to fill in names.
Anything that can produce
{ jid, name }
rows can call
store.setCustomNames
. A CSV upload, a CardDAV pull or a scheduled job would all work. The agent route exists so the server needs no credentials for any of them.
Sending messages.
Not built, on purpose. Think hard before adding it.
Debugging
With
PIN
set, these return JSON and need the header
x-pin: <PIN>
:
/debug
: session phase, linked or not, counts, and the last events from the session (connection changes, history chunk sizes, errors).
/debug/pull
: run a pull now.
/debug/chats?q=
,
/debug/messages?chat=
,
/debug/search?q=
,
/debug/types
: read the store without going through MCP.
/debug/unnamed
: the chats
unnamed_chats
would return.
/debug/sql?q=
: one read-only
SELECT
against the store, for finding out why a name or a count looks wrong.
/debug/logout
: the same as
relink
.
Local development:
npm run dev
with a
.dev.vars
containing
OWNER_PASSWORD=...
(12+ characters). It runs a local Durable Object with its own empty storage, so you can exercise the sign-in flow and see a real QR code, but linking a phone from local dev makes a second linked device.
To test the pairing UI states without a phone, serve the page with a mocked
/pair/status
. Everything the page needs is that one JSON shape:
paired
,
running
,
progress
,
qrSvg
,
messages
,
chats
.
Checking a change
npm run typecheck
, then
npm test
. The test runs the real store code against Node's built-in SQLite (Node 22.13 or later), including the migration from older versions. That SQLite has no FTS5, so search itself isn't covered.
Deploy, then
GET /debug
with the PIN. It should come back with
phase: "idle"
and
paired: true
.
GET /debug/pull
. A quiet account should return
reason: "idle"
in about ten seconds.
Call
list_chats
, then
get_messages
on a Hebrew or emoji-heavy chat, then
search_messages
. Then
unnamed_chats
, and
set_contact_names
on one number, and confirm the chat shows the name.
If you touched ingest, relink and confirm the stored message count doesn't grow (re-import is idempotent) and that group messages show real sender names.
Known gaps
Chats with no name in WhatsApp and none saved show as phone numbers. Nothing refreshes names by itself: they only get saved when an agent (or you) does it.
If the daily pull finds the session logged out, nothing tells you.
link_status
shows it the next time your agent asks.
Edits and deletes are applied when they arrive as protocol messages. That path hasn't been tested against real ones.
It's only been exercised against one real account.
License
MIT
Claim Chowder: The Information on HomeView Having a ‘Robotic Swiveling Base’
Daring Fireball
www.theinformation.com
2026-10-18 17:26:32
Wayne Ma and Qianer Liu, reporting, wrongly, for The Information in January this year (paywalled; here’s MacRumors’s summary)
Apple’s pin joins a growing portfolio of AI-powered products the
tech giant has under development, including AirPods equipped with
enhanced sensors, a security camera, sm...
This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.
What can I do to resolve this?
You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.
Show HN: OmniPTY – Opinionated terminal emulator for macOS and Linux
If your terminal is really a terminal plus a stack of add-ons — tmux for splits and sessions,
a file manager in another pane, a prompt framework, a copy-mode plugin — OmniPTY builds those in.
A file tree you drive like vim sits beside your panes and follows your shell's
cd
. Tabs and
splits group into named workspaces you can pin, so they reopen with the same layout and
directories. Copy mode puts vim keys on the scrollback, and the status bar knows your git
branch and when you're inside
ssh
. It's all configured in one TOML file that reloads when
you save.
Under the hood, it's GPU-rendered on
GPUI
(Zed's UI framework), with
alacritty_terminal
(Alacritty's PTY + VT parser)
doing the emulation, so vim, htop, and tmux itself still just work. No account, no AI, no
telemetry: the only thing OmniPTY asks the network is whether there's a newer release.
Renamed from Oxide
Oxide became OmniPTY in 0.9.0 (there's an unrelated company called Oxide, and the
name was getting in the way). Nothing to do if you already had it installed:
The in-app updater carries an installed Oxide across: it lands as
OmniPTY.app
with your config, themes and pinned workspaces intact. A Dock icon pinned to the
old
Oxide.app
path needs re-adding.
Homebrew: switch to the new cask with
brew uninstall --cask --force oxide-terminal && brew install --cask --adopt omnipty-terminal/tap/omnipty
.
--adopt
keeps the
OmniPTY.app
the updater already put in place.
~/.config/oxide/config.toml
and
~/.cache/oxide
are copied to
omnipty
directories on first launch; the originals are left alone.
$OXIDE_SESSION
and
$OXIDE_VERSION
are still exported through 0.9.x; switch
dotfiles to
$OMNIPTY_SESSION
/
$OMNIPTY_VERSION
.
theme = "oxide"
keeps working; the palette is now also called
omnipty
.
Install
macOS
brew install --cask omnipty-terminal/tap/omnipty
Or
download the DMG
and drag OmniPTY to Applications. Builds are Developer ID signed and notarized, so there's no
right-click-to-open dance, and OmniPTY keeps itself up to date afterwards — it checks on launch
and every six hours, or on demand via
OmniPTY → Check for Updates…
Updates are signed, and
OmniPTY only installs one whose signature matches the key it was built with.
Linux
(Wayland or X11, x86_64)
# Arch and derivatives: a pacman package from the PKGBUILD in this repo# (an AUR package will follow once AUR registration reopens)
git clone https://github.com/omnipty-terminal/omnipty.git
cd omnipty/packaging/aur/omnipty-bin && makepkg -si
# any distro: the release tarball
tar xzf omnipty-linux-x86_64.tar.gz
cd omnipty-*-linux-x86_64 && ./install.sh # into ~/.local, no root
Download the tarball
; older versions are on the
releases page
.
install.sh
puts
omnipty
on your PATH and adds the launcher entry and icon;
--prefix /usr/local
(with sudo) installs system-wide,
--uninstall
removes it.
Installed copies announce a newer release in the top-right corner;
git pull
and
makepkg -si
again, or a fresh tarball, does the update.
macOS 12 or later, Apple Silicon or Intel; or Linux with glibc 2.35 or newer
(Ubuntu 22.04, Debian 12, Fedora 36 and later), a Vulkan driver (any GPU
from the last decade — Mesa's
vulkan-radeon
/
vulkan-intel
, or
nvidia-utils
) and
notify-send
(libnotify) for desktop notifications.
No font to install — JetBrainsMono Nerd Font Mono is bundled. Set
font.family
to use your own.
zsh or bash for the built-in prompt and shell integration. Other shells run fine and keep
their own prompt.
OmniPTY never writes to your dotfiles. Full instructions are in the
install docs
.
A closer look
A minute in OmniPTY
— the tree, a markdown preview, the file finder, splits, tabs, the palette and theme picker, workspaces.
Features
The short tour. Every feature has a page in the
docs
.
Real terminal
— full VT emulation via Alacritty's parser: truecolor, wide glyphs and
combining marks, bracketed paste, mouse reporting (SGR), alternate-screen scrolling, OSC 8
hyperlinks, OSC 52 clipboard. vim, htop, and tmux just work.
Inline images
— the kitty graphics protocol, iTerm2's, and sixel:
kitten icat
,
imgcat
,
img2sixel
, yazi's previews, snacks.nvim. A picture lives in the scrollback
like text does — it scrolls, reflows, and clears — and is drawn at the display's real
resolution. Unicode placeholders carry images through tmux.
File tree drawer
— follows the focused pane, so switching splits re-roots it to
that shell's directory. Modeless vim navigation (
j
/
k
/
gg
/
G
, nvim-tree style
h
/
l
),
type-to-filter with
/
, and file operations:
a
add,
r
rename,
m
move,
d
delete
(to Trash) — or drag a row onto a directory to move it there; the tree scrolls when the
drag nears its top or bottom, and the empty strip under the rows is the root. Drag the
drawer's edge to resize it, double-click it to go back to
tree.width
.
Dims gitignored files, watches the filesystem, and follows the shell's
cd
automatically.
The tree/terminal seam
—
y
inserts the selected path at the prompt, quoted and
relative;
cmd-click
a
path:line:col
in output to open it in
$EDITOR
at that line
(nvim, VS Code, emacs, Sublime, Helix dialects built in); rows are coloured by git status;
cmd-p
fuzzy-finds any file under the root;
cmd-shift-r
reveals the shell's directory;
right-click a row to re-root, copy, rename, move, delete, or reveal in Finder / your file
manager — a directory, the root's name, or the empty space under the rows to add a file or
folder there — or, on a
.md
file, preview it (
P
from the keyboard)
rendered in a new tab or split (
markdown.preview_in
; full CommonMark and GitHub markdown, with
tables and highlighted code with click-to-copy);
enter
on a picture shows it in a tab or
split of its own (
images.preview_in
), any key to close;
drag rows or drop files onto a pane. A file opened while the pane is busy in an editor gets a tab
or split of its own (
editor.open_in
).
Scrollback search
—
cmd-f
, live,
⏎
/
⇧⏎
to walk matches; regex, case-sensitive,
and whole-word toggles as clickable chips (
cmd-alt-r
/
c
/
w
), and a malformed
regex says so instead of matching nothing.
Copy mode
—
ctrl-w [
(or
cmd-shift-v
) turns the scrollback into a vim buffer:
hjkl
,
w b e
,
0 ^ $
,
gg G
,
ctrl-d/u
, counts like
5j
,
/
and
?
search with
n
/
N
,
v
/
V
/
ctrl-v
visual selection,
y
to yank and leave. Nothing typed
reaches the shell until you
esc
.
Prompt jumping
—
cmd-↑
/
cmd-↓
hop between previous prompts in scrollback.
SSH awareness
— OmniPTY watches the foreground process: an
ssh
shows
ssh: host
in the status bar, and
[[ssh.hosts]]
patterns give a host an accent colour
on the pane border so a production box is visibly red. The process name also titles
the tab (
vim
,
cargo
,
ssh prod-web
).
Command awareness
— the shell integration's OSC 133 markers are read straight off the
PTY, so OmniPTY knows what's running, how long it took, and whether it failed: elapsed time
in the status bar, activity dots on tabs, a red flash on a background pane that failed, a
failure gutter you can click to jump to the command, and desktop notifications for long or
failed commands in panes you aren't watching (click to focus the pane).
Command history
—
cmd-r
searches every command run in any pane, with its directory
and exit status;
⏎
inserts it at the prompt,
⌘⏎
runs it.
cmd-shift-c
copies the last
command's output.
Status bar
— workspace, current tab (number or name,
status_bar.tab
), cwd plus git
branch, dirty state, and ahead/behind, rendered natively.
Configurable prompt
(optional)
— compile a powerline prompt from TOML segments
(
cwd
,
git
,
exit_status
,
time
,
duration
, …), injected without touching your
dotfiles (ZDOTDIR shim for zsh,
--init-file
for bash), with OSC 133 semantic prompt
markers. Or set
prompt.enabled = false
and keep your starship/p10k prompt as-is.
Themes
—
catppuccin-mocha
,
catppuccin-latte
,
gruvbox-dark
,
tokyonight
,
dracula
,
nord
,
solarized-dark
, and
omnipty
(rust-toned, naturally), plus the
Omarchy
set:
kanagawa
,
everforest
,
osaka-jade
,
matte-black
,
hackerman
,
rose-pine-dawn
, and a dozen more —
25 presets in all. Any color
individually overridable, including
selection_fg
.
follow_system = true
switches
between a dark and a light preset with the system appearance (macOS, or the desktop's
dark/light preference on Linux). Config reloads live.
Split panes
— split in any direction and nest freely; navigation moves by what's
on screen, and
exit
or
ctrl-w q
closes a pane and reclaims its space. Drag a
divider or use
ctrl-w < > - + =
to resize. tmux reflexes:
ctrl-w z
zooms a pane
to the full tab,
ctrl-w b
broadcasts typing to every pane in the tab (with a red
border and a loud status-bar pill),
ctrl-w o
closes the others,
ctrl-w x
swaps with
the neighbour.
window.inactive_pane_opacity
dims the panes you aren't in.
Command palette
—
cmd-shift-p
lists every action with its binding, fuzzy-searchable.
Every text field edits like the rest of the system:
opt-←/→
by word,
opt-delete
a word
back,
cmd-←/→
to the ends (
ctrl
on Linux).
Menus on Linux
— a ☰ button in the top-left corner holds the same OmniPTY / File /
Edit / View / Window / Help menus macOS puts in the menu bar, shortcuts included
(
app::menu
opens it from the keyboard).
Configurable keys
— a
[keymap]
table in config.toml rebinds anything; typos get a
toast with a suggestion, and a bare key that would steal from your shell is refused.
Toasts, not dialogs
— config errors, update problems, and other notices land as
toasts in the bottom-right corner; click or
×
to dismiss. The first launch after an update
shows one that opens the changelog in a new tab.
Tabs
— a Zed-style in-app tab bar, so tabs work everywhere (including under
tiling window managers).
cmd-t
opens one in the current directory or
~/
(
window.new_tab_directory
);
cmd-1..9
jump straight to a tab. Double-click or
ctrl-w ,
to rename one (names survive with pinned workspaces), drag tabs to reorder,
cmd-shift-t
reopens the last closed one. Each tab carries its number
(
tabs.show_numbers
), and the whole bar can be hidden — View → Toggle Tab Bar, or
tabs.enabled = false
— with the status bar still showing which tab you're on. Closing
a workspace's last tab closes the workspace, or with
tabs.close_last = "new_tab"
leaves
it a fresh tab in your home directory.
Workspaces
— named sets of tabs and splits, tmux-session style, managed from the
drawer below the file tree (
a
add,
r
rename,
d
or a row's
×
delete,
p
pin,
drag to reorder);
cmd-alt-1..9
jump straight to one. Temporary by
default; pinned ones survive restarts, restoring layout, tabs, splits, and each
pane's directory with fresh shells.
Startup commands
— the tmuxinator move: give a pane a command (
ctrl-w r
,
prefilled with the last thing that ran there) and a pinned workspace re-runs it on
restore, once that pane's shell is actually at a prompt.
on exit
per pane: back to
the shell, close the pane, or restart with backoff (and a breaker after five quick
exits).
e
in the workspaces panel edits every pane's command at once;
--no-startup-commands
or shift at launch restores the layout without running any.
The details
— window size/position persistence,
cmd-click
to open URLs, a mouse
selection that scrolls the view when dragged to the pane's top or bottom, copy-on-select option, font size at runtime
(
cmd +/-/0
), configurable bell, a
[cursor]
section (block / bar / underline, blink
rate, unfocused look — and vim's per-mode DECSCUSR shapes are honoured), a font
fallback list for CJK and emoji, a "2,340 lines above" pill while scrolled up,
cmd-k
to clear scrollback, and optional dimming of the whole window when another app is
frontmost.
Keys
The everyday ones. The
full keymap
lists every
action id, and a
[keymap]
table in your config rebinds any of them.
The
ctrl-w
chords are the same everywhere. Where macOS uses
cmd
, Linux uses
ctrl-shift
(the usual terminal convention — plain
ctrl-c
stays the shell's) and
alt-1..9
for tabs, because Super belongs to the window manager.
macOS
Linux
Action
ctrl-w h
/
ctrl-w l
/
ctrl-w w
same
focus tree / terminal / toggle
cmd-b
ctrl-shift-b
toggle the drawer
ctrl-w t
/
cmd-shift-e
ctrl-w t
/
ctrl-shift-e
focus the file tree from anywhere
cmd-f
ctrl-shift-f
search scrollback (
⏎
older,
⇧⏎
newer,
esc
close;
cmd-alt-r
/
c
/
w
—
ctrl-alt-r
/
c
/
w
on Linux — toggle regex / case / whole word)
ctrl-w [
/
cmd-shift-v
ctrl-w [
copy mode — vim keys in the scrollback,
y
yanks,
esc
leaves
insert the path at the prompt (relative / absolute)
cmd-c
(
ctrl-shift-c
)
copy the path
cmd-shift-o
(
ctrl-shift-o
)
reveal in Finder / the file manager
c
/
-
re-root at selection / at parent (cd's the shell too)
/
filter (
esc
clears)
a
/
r
/
m
/
d
add (
dir/
with trailing slash) / rename / move / delete to Trash — also on right-click
P
preview a markdown file
drag a row
onto a directory: move it there; under the last row: to the root; onto a pane: insert its path
I
/
R
toggle hidden / refresh
esc
dismiss input → clear filter → back to terminal
In copy mode
—
ctrl-w [
; keys never reach the shell
Keys
Action
h
j
k
l
, arrows
move the cursor (counts work:
5j
)
w
b
e
/
W
B
E
word motions (punctuation-aware / whitespace)
0
^
$
/
gg
G
/
H
M
L
line / buffer / screen positions
ctrl-d
ctrl-u
/
ctrl-f
ctrl-b
half page / full page
/
?
then
n
N
search forward / backward, repeat — same bar and toggles as
cmd-f
v
V
ctrl-v
character / line / block selection
y
/
yy
/
⏎
yank the selection (or the line) and leave
esc
/
q
clear the selection, then leave
In the workspaces panel
Keys
Action
j
/
k
move selection
enter
/
o
switch to workspace
a
/
r
/
d
add / rename / delete (
y
confirms) — also on right-click;
×
on a row deletes without asking
drag a row
reorder
p
pin — persist this workspace across restarts
e
edit every pane's startup command — also on right-click
esc
dismiss input → back to terminal
Configuration
~/.config/omnipty/config.toml
— a fully commented default is generated on first run.
Font, colors, keys, and notifications apply live;
[shell]
and
[prompt]
apply to new
sessions.
Every option, with defaults →
[font]
family = "JetBrainsMono Nerd Font Mono"size = 14.0
[colors]
preset = "omnipty"# or override any color individuallyfollow_system = true# ...or switch between preset_dark / preset_light with the systempreset_light = "catppuccin-latte"
[cursor]
style = "bar"# block | bar | underline
[window]
new_tab_directory = "pwd"# pwd | homeinactive_pane_opacity = 0.8# dim the panes you aren't in
[[ssh.hosts]]
match = "*.prod.example.com"# red border while ssh'd into prodaccent = "#f38ba8"
[tree]
follow_cwd = true# tree re-roots when the shell cd'sopen_on_startup = true# false starts with the drawer hidden (cmd-b shows it)
[editor]
open_in = "tab"# tab | split — where a file opens when the pane is busy
[markdown]
preview_in = "tab"# tab | split — where a markdown preview opens
[images]
enabled = true# draw the images programs send (kitty, iTerm2, sixel)memory_limit = 128# MB of decoded images per panepreview_in = "tab"# tab | split — where a picture opened from the tree is shown
[status_bar]
enabled = trueposition = "bottom"tab = "number"# number | name — the current-tab chip
[tabs]
enabled = true# false hides the tab barshow_numbers = true# small position number on each tabclose_last = "workspace"# workspace | new_tab — what closing the last tab leaves
[prompt]
enabled = false# keep your own prompt (starship, p10k, ...)
[keymap]
"cmd-j" = "pane::split_down"# keystroke = "action id"; "" unbinds
Build from source
You'll need
Rust
(2024 edition). On macOS, also full Xcode with the Metal
toolchain — GPUI compiles Metal shaders at build time:
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
xcodebuild -downloadComponent MetalToolchain # if the build asks for it
On Linux, the GPUI build dependencies (Arch shown; Debian/Ubuntu equivalents are in
.github/workflows/ci.yml
):
The
omnipty
command takes a directory,
-e <command> [args...]
to run a
program in the first pane instead of the shell,
--app-id <id>
for the
window's Wayland app-id / X11 class, and
--no-startup-commands
. The first
two are what
xdg-terminal-exec
passes, and the
.desktop
entry declares
them, so on Linux OmniPTY can be the default terminal: on Omarchy, put
omnipty.desktop
first in
~/.config/xdg-terminals.list
.
The first build compiles GPUI — expect several minutes. A
cargo run
binary is a debug
build: fine for poking at a change, but a full-screen program like nvim will feel sluggish
in it (an unoptimised GPUI redraw doesn't fit in a 60 Hz frame; the release build uses a
quarter of the CPU). It also never checks for updates, and on macOS it isn't an app bundle,
so its notifications can't be clicked. Use
scripts/bundle.sh
/
scripts/linux-package.sh
for the real thing. Cutting a release is covered in
RELEASING.md
.
Architecture
One binary crate. The PTY reader/parser runs on its own thread
(
alacritty_terminal
's event loop) and mutates a shared
Term
behind a mutex;
the GPUI main thread briefly locks it during paint to copy the visible grid out,
then shapes and paints batched text runs directly — no per-cell elements.
An image is text as far as the grid is concerned — placeholder cells written where the
picture goes, each naming its slice — so scrollback, reflow, and clears need no special
cases; the pixels are decoded on the background pool and drawn under the text.
Directory scans, git queries, and file watching run on the background pool.
The tree follows
cd
by polling the PTY's foreground process group cwd
(
tcgetpgrp
+
proc_pidinfo
on macOS,
/proc/<pid>/cwd
on Linux), so it works
with zero shell cooperation. Platform differences are confined to a handful of
cfg
sites: the process lookups, notifications (
UNUserNotificationCenter
/
notify-send
), the updater, the keymap tables, and the window chrome.
Known limitations
No IME / dead-key composition yet (two-stroke accents, CJK input).
Narrowing a pane past the width of a multi-line bash prompt can scroll the prompt's
first line into scrollback until the next prompt is drawn (
enter
brings it back).
Pinned workspaces restore layout and directories with fresh shells; running
programs can't survive a full quit (tmux only manages it because its server
never exits). Startup commands are the workaround: declare what a pane runs
and it's re-run on restore.
on_exit
needs shell integration with zsh or
bash; other shells get the command typed in and nothing more.
Images: no animation yet (a GIF shows its first frame), and an image is part of the
text grid rather than a layer over it, so text printed across one replaces that part
of it and kitty's
z
index is ignored. The kitty protocol's file and shared-memory
transfers are refused; programs fall back to sending the pixels down the pipe.
Left/right Option can't be distinguished;
option_as_meta
treats
left
/
right
as
both
.
Linux: there's no in-place self-update (the pill opens the release page);
window.titlebar
is ignored — the compositor owns decorations, and under a
compositor without server-side decorations (GNOME) the window has none.
Community
Questions, ideas, or just want to see what's coming? Join the
OmniPTY Discord
. Bugs and feature requests go in
issues
—
Help → Report an Issue
in
the menu bar (the ☰ menu on Linux), or
Report an Issue
in the command palette, goes to the same place. Wondering how OmniPTY stacks up against iTerm2, Ghostty,
kitty, WezTerm, Alacritty, or Warp? There's an
honest comparison
.
I think the title captures the idea fully but I'll dig into it because this ain't Twitter.
You're working an idea, a piece of code, or a multibillion a year SaaS app which is probably saving the world. Maybe you're automating the cloning process of grabbing new Labubu release images and taking the 2D image and using a ComfyUI to translate it into a 3D CAD to get the replica production started faster because CNY is on the horizon and global manufacturing halts around that time. Maybe you like to use your tokens to search against the most powerful computer software ever developed for macronutrient information for a McRib or some shit.
You're most likely chatting with some type of frontend thats tied into a paid subscription from the provider of your choice. TUI, GUI, Voice call, whatever. It's your data going in and their data coming back for you. That's what they're selling, I'm happy to buy that right now. They'll show you something like this as proof of work happening:
yikes y'all
That is a distraction. That is not token usage statistics with time series data meant for engineers. I can't make a decision with this bullshit. Surely the big labs will have valuable insight to share with the curious user who digs into the Analytics panel.
I can't make a decision with this bullshit. I hear you already, "there's OTel export options!!1!". Cool, I guess. This is one reason, here's 5 more off of the top of my head right now:
multi provider, multi models, at a single endpoint you control
logs of which key called what model with what client at what time and its status
use virtual api keys to stop littering your single main key over your work, agents, and harnesses
its infra you control
you can pivot model and provider extremely fast without resetting everything up (again, probably, for like the 3rd time)
I'm not going to suggest a proxy provider for you to use, only that you run it yourself somewhere you control. When you pick one, don't forget you can modify it for your actual needs. I've modded mine for better insight, for custom MCP server endpoints, additional features. Whatever you choose, you should be getting something along these lines for data.
When I see a cache miss during a coding session, I can pinpoint why that happened in 20 seconds by hand. I haven't automated it but the proxy I use has an API, so it's possible to automate.
Own your infrastructure, your application visibility, data pathing, and storage. I do this at home because it's fun and it's how I like to learn. I do this at work because I'm not doing my job right if I don't. I may never fully understand how the fuck a large language model works well enough to white board it in an interview. But I can wrassle it down and make sure it's instrumented while serving inference.
How Discover-Tech turned targeted ads into a pipeline for zero-click spywares
Devices at international news network Al Jazeera were infected with mercenary spyware from Candiru (rebranded as “Integrity Labs”) via targeted online advertisements. We provide the
first public technical confirmation of a zero-click mercenary spyware attack delivered via targeted advertising, which we call AdFection
.
The malicious advertisements were purchased by Discover-Tech, an Israeli company that presents itself as a legitimate advertising company, but which we found operates as a facilitator for multiple mercenary spyware partners.
Discover-Tech operates a platform called
Controlium
that enables its mercenary partners to de-anonymize, fingerprint, and automatically infect devices the moment an advertisement is rendered — a form of zero-click attack.
Analysis of four billion Discover-Tech bidding records shows that during a four-month period, the company’s ads were shown on almost 200,000 unique websites and Android/iOS apps in dozens of countries.
Discover-Tech’s ads also covertly directed millions of devices to contact Candiru’s servers, likely for large-scale tracking and reconnaissance. Discover-Tech is linked to mercenary spyware and intelligence threat actors beyond Candiru, including Intelos and Bindecy.
A separate threat actor we call
DARK CARTOGRAPHER
is using Discover-Tech’s infrastructure to exploit vulnerabilities across numerous mobile carriers to link device advertising IDs with phone numbers, mass-deanonymizing internet users. We will detail our findings concerning this threat actor in a separate forthcoming report.
Discover-Tech has appeared on lists of “certified” and “approved” vendors maintained by Google and advertising industry association IAB Europe, and has served ads via major networks such as Google, Yandex, and Beeswax. Discover-Tech has also leveraged the European General Data Protection Regulation (GDPR) consent frameworks to target users within the European Union.
Discover-Tech’s mass abuse, privacy invasion, and facilitation for mercenary spyware attacks illustrates structural flaws with the online advertising system, which failed to detect or prevent the abuse documented in this report.
We call on regulators to investigate whether Discover-Tech and Candiru/Integrity Labs violated applicable laws, and make recommendations to lawmakers, defenders, and the advertising industry on how to stop AdFection-style attacks and espionage.
We disclosed our findings to ad vendors and industry organizations. Google, IAB Europe, Beeswax, Vungle (Liftoff), and Eskimi took action to disconnect Discover-Tech’s access to the digital advertising ecosystem. Other ad vendors we found to be involved in Discover-Tech’s operations did not respond to our request for comment within the timeline provided. We are also actively working with vendors to mitigate
DARK CARTOGRAPHER
’s mass-deanonymization attack.
1. Introduction
This section provides an overview of the online advertising ecosystem, and summarizes our findings about Discover-Tech.
The Online Advertising Ecosystem is Ripe for Abuse
When a user sees an ad on an app or a website, it is likely the result of a real-time auction, where advertisers bid on the chance to show that specific user that specific ad. So-called
Real-Time Bidding (RTB)
auctions, which are hosted on ad exchanges
operated by
companies including Google,
take place
hundreds of billions of times a day. In less than a second, the user’s device initiates a bid request, advertisers submit their bids, and the ad exchange determines the winner of the auction and pushes the ad to the user. Besides an image or video, an online ad can also contain code that runs within the app or browser that shows the ad.
Both advertisers and publishers of apps and websites use ad vendors that act as their
intermediaries
in these auctions. Advertisers typically buy ads via a so-called Demand-Side Platform (DSP), and a Supply-Side Platform (SSP) sells ad inventory on websites and apps.
Malicious actors make use of two interrelated facets of the online advertising ecosystem:
The advertising ecosystem collects a lot of data and enables individual-level targeting:
When a publisher of an app or website wishes to show ads, they add code from an SSP to their app or site. This code
collects and shares
granular information about the user and their device with ad exchanges to solicit
bids
for the ad slots. This information
can include
device identifiers and characteristics, precise location, and IP address data, as well as data about the app or website, and specifications about the ad slot. The DSP or advertiser then examines this information and decides whether they wish to bid on the impression in order to show an ad. The auction system
is
designed
to enable targeting single individuals based on their mobile advertising ID, cookie ID, IP address, and other identifiers.
The advertising ecosystem allows many different third parties to run code in apps and websites:
It is tempting to think of an online ad as, simply, a video or image. However, ads themselves
may
contain
code
from the advertiser, DSP, and other parties, and run it in the app or browser while the ad is shown to the user, for example to track users, ad impressions, and clicks. Code run by advertisers, DSPs, SSPs, and other third parties within apps and websites is often
referred
to
as “tags”, “pixels”, “SDKs”, or “third-party tracking” more generally.
Exploiting Advertising Tech for Surveillance
The totality of information gleaned from ad auctions is quite valuable. A company with access to auction data
can
track
users without their knowledge as they move around in physical space, or switch between cellular, Wi-Fi, and VPNs, by observing how bid requests tied to a specific identifier change location or IP address over time. In fact, the surveillance industry sells access to so-called ad intelligence (ADINT) platforms that leverage this sort of data, often combined with third-party tracking data. In recent years, several investigations and media reports
have
uncovered
vendors
that sell ADINT to defense, intelligence, and law enforcement agencies.
Zero-Click Spyware Delivered via Targeted Ads: AdFection
Beyond passive data harvesting, malicious parties can also exploit this infrastructure to target certain individuals based on user data included in ad auctions and then run malicious code on their devices. Advertisers or DSPs may run HTML and JavaScript code when an ad is shown to the user. That code retrieves additional JavaScript code, which may, in turn, load further code, such as a browser exploit to install spyware. Since the code can contain identifiers for the user or their device, arbitrary JavaScript code can be sent precisely to a single user’s device. Our research in this report indicates that this architecture is indeed abused to facilitate the delivery of zero-click targeted spyware, and that the simple display of a targeted ad is enough for infection.
There
has
been
some reporting about the intersection between spyware and the advertising ecosystem. However, the specific ways mercenary spyware companies plug into the ads ecosystem to target particular users have remained largely secret.
This report exposes zero-click spyware delivered via targeted ads, which we call
AdFection
, and is the first technical demonstration that mercenary spyware is being distributed via targeted advertisements.
Discover-Tech is a Bridge Between Mercenary Spyware Companies and the Advertising Ecosystem
We present technical evidence that the Israel-based company Discover-Tech, while purporting to be a legitimate advertising company, appears to be a front for large-scale ad espionage abuse, including the automatic delivery of mercenary spyware when ads are displayed to a target and the mass profiling and deanonymization of users.
The company serves as a bridge between ad vendors and the mercenary spyware ecosystem. In fact, it appears that serving as this bridge is Discover-Tech’s primary purpose. Its platform, Controlium, allows malicious actors to precisely profile and de-anonymize millions of individuals, fingerprint their devices, and target them with a form of zero-click hacking, where their devices can be automatically infected when an ad is displayed to them.
Discover-Tech appears to work with multiple mercenary spyware, hacking, and advertising vendors, connecting the spyware industry to the online advertising ecosystem. As we detail in this report, Discover-Tech ads are used to infect and profile on behalf of mercenary spyware vendor Candiru. We also detail connections between Discover-Tech and another mercenary hacking company, Bindecy, as well as connections with Intelos, a mercenary ADINT firm.
What is Discover-Tech and How Does It Operate?
Discover-Tech is led by its CEO Dekel Boni, who has a background in digital advertising. Eric Banoun, whom Haaretz
describes as
“one of the pioneers of offensive cyber in Israel”, joined the company’s board of directors soon after it was founded in 2020 and remained there until 2025. Between 2020 and March 2026, Discover-Tech’s shareholders included a company linked to Sara Hamou, who has managed the corporate network of the spyware group Intellexa.
Discover-Tech appears to place advertisements using several techniques. Firstly, the company operates a platform called
MyDSP,
which interfaces with online ad vendors including Google, Yandex, Vungle (Liftoff), and Sunteng. Secondly, separately from MyDSP, it purchases ads via the ad vendors Eskimi and Comcast-owned Beeswax (Freewheel).
A large number of ads placed by Discover-Tech contain a
script
tag pointing back to what the company refers to as a “
NOAS server
” (also called a “getAd server”). This tag causes the ad, when rendered, to connect back to Discover-Tech, submit advertising identifiers for the user (either a cookie ID or a mobile ad ID), and automatically execute any JavaScript code returned. The NOAS server decides, apparently based on a combination of the source IP address and the advertising identifiers, whether the target is eligible to receive any JavaScript. If so, then code is returned. If not, a 0-byte response is returned. The NOAS server is a key part of Discover-Tech’s strategy, allowing Discover-Tech to avoid directly sharing malicious code, or even pointers to malicious code, with the companies who serve and display the ads.
As detailed in
Section 9
, Discover-Tech appeared on several lists of “certified” and “approved” ad vendors maintained by Google and the advertising industry association IAB Europe from the year 2020 until 2026. These listings helped make Discover-Tech appear to be a legitimate ad vendor and facilitate its participation in the digital advertising ecosystem at scale.
As a result of this investigation, both Google and IAB Europe removed Discover-Tech from their ad vendor registries in early October 2026. Google, which collaborated in the investigation, terminated Discover-Tech’s access to its ad exchange platforms. Beeswax removed Discover-Tech from its ad buying platform, Vungle (Liftoff) paused Discover-Tech’s access while conducting a review, and Eskimi blocked Discover-Tech’s accounts and domains.
In this report we provide an overview of the different types of ad abuse facilitated by Discover-Tech, the company’s ad targeting systems and practices, as well as its partners and corporate network.
In
Section 2
, we show how Candiru works with Discover-Tech to conduct AdFection attacks, and describe one such attack: the targeting and infection of devices at the international media network Al Jazeera with Candiru’s mercenary spyware.
In
Section 3
, we examine Controlium, a Discover-Tech platform that provides a control-panel style interface enabling mercenary spyware customers to target specific users with “controlled ads.”
In
Section 4
, we examine links between Discover-Tech and mercenary spyware companies Candiru/Integrity Labs and Bindecy. We then outline their relationships with other mercenary surveillance companies, including advertising intelligence (ADINT) vendor Intelos, and an ADINT vendor we refer to as
DARK CARTOGRAPHER
, which is building databases linking users’ mobile advertising identifiers to their phone numbers.
In
Section 5
, we analyze
where
Discover-Tech’s malicious advertisements land. We identified a Discover-Tech server that published almost four billion ad bidding records. These records show that Discover-Tech ads were served in almost 200,000 different Android apps, iOS apps, and websites in many countries. We also highlight specific countries and government networks where Discover-Tech’s advertisements had impressions.
In
Section 6
, we use technical analysis to examine how Discover-Tech deploys ads, tracks users and exchanges user identifiers with other ad vendors, including with Beeswax, Yandex, and Microsoft’s ad system Xandr.
In
Section 7
, we present our research on Discover-Tech Ltd, its corporate network, key persons linked to the company, the origins of its MyDSP advertising technology, and its connection to the wider advertising ecosystem.
In
Section 8
, we summarize what is known about the mercenary surveillance firms Candiru, Bindecy, and Intelos, and we further examine their activities and corporate networks in the context of the findings presented in our report.
In
Section 9
, we explore how major industry organizations and ad vendors helped enable Discover-Tech’s ad operations, including Google, IAB Europe, Beeswax (FreeWheel/Comcast), Vungle (Liftoff), Eskimi, Sunteng, and Xandr (Microsoft).
In
Section 10
, we discuss the implications of AdFection for user security and human rights.
In
Section 11
, we provide recommendations to lawmakers, regulators, defenders, and the advertising industry on how to mitigate and block threats from AdFection-style attacks.
The Citizen Lab sent requests for comment to 13 companies; their responses are included in full in the ‘Correspondence with Companies’ section.
This section provides the first public technical confirmation of a zero-click spyware attack via targeted ads in the wild: the targeting and infection of devices at the international media network Al Jazeera with mercenary spyware
.
We refer to this type of attack as
AdFection
. Using network analysis, infrastructure fingerprinting, and analysis of implant behaviour, we connect Discover-Tech’s infrastructure with the distribution of Candiru’s mercenary spyware.
What AdFection Looks Like
The instances of Candiru AdFection via Discover-Tech ads all share similar characteristics. First, Discover-Tech wins a bid, and one of their ads is pushed to a website or app that is open on a user’s device. The user may see this ad, such as in
Figure 4
, though in some cases the ad may render in the background.
When the website or app receives the ad, it renders it, requesting JavaScript from a Discover-Tech server embedded within the ad. In most cases, the user who sees the ad is
not
selected for targeting, and the server will
not return any
JavaScript to be executed. Nevertheless, the ad will still gather data from the user’s browser and submit it back to Discover-Tech, which can include cookies set on the webpage including the ad, as well as the device’s public IPv6 address.
Confirming the Targeting of Al Jazeera with Candiru Spyware via Discover-Tech Ads
In 2024 and 2025, international news network
Al Jazeera
was targeted in a series of zero-click attacks that we link with high confidence to Candiru’s spyware delivered via Discover-Tech’s ads. At least 45 devices within Al Jazeera were targeted in these attacks.
Analysis of network logs provided to the Citizen Lab by Al Jazeera collected during the attack period provides a clear temporal signature of how the attack was executed. Infected devices first show contact with domains from Discover-Tech infrastructure, indicating an ad impression. Next, the devices show connections with a Candiru validator server. The validator server performs an initial check of the device before it is further profiled and infected. Ultimately, an infected device communicates with a Candiru Command and Control (C&C) server. This temporal signature is illustrated by
Figure 5
.
Fingerprinting Candiru Servers
We developed a fingerprint for Candiru validator servers. Both
keyadapter[.]com
and
sharethere[.]net
returned banners that matched the following regular expression on Censys.
1
We refer to this as
Fingerprint V1
:
We found hosts on Censys matching
Fingerprint V1
between August 2022 through July 2026, though we note that in May and June 2026, this behaviour gradually began being retired. In all, we found 305 distinct domain names on 319 IP addresses, though to save query costs we only searched one historical Censys snapshot per month. The set of 305 validator server domains we found includes ones publicly attributed to Candiru by
Sekoia
, as well as
Recorded Future
.
We also identified a separate fingerprint for the C&C servers used in the attack,
Fingerprint C1
. Four of the servers matched it (
fearevolve[.]com
,
insightenterprisells[.]com
,
jobmarcher[.]com
,
plasticbells[.]com
). We could not locate a response in Internet scanning data for the other three.
Al Jazeera isolated a Windows DLL file from one of the compromised devices which contains hardcoded Command & Control servers matching Fingerprint C1. The sample is available on VirusTotal.
This sample hard-codes two C&C servers that match
Fingerprint C1
:
fearevolve[.]com
and
jobmarcher[.]com
. The functionality broadly overlaps with the functionality of the Candiru chain from our 2021
report
. For example:
Both samples use a COM hijack for persistence, though make use of different DLLs.
Both samples obfuscate strings using a 48-byte repeating XOR key, though the samples have different keys. Both samples also have an interesting quirk where obfuscated strings contain a “dummy” null-terminator character that is not deobfuscated (the deobfuscation with the key would be nonsensical), and is instead silently discarded. The only function of this dummy null-terminator appears to be to ensure that the right-size chunk of memory is allocated to hold the XOR-decrypted output.
The configuration within both samples hardcodes the same ordered list of domain names to fetch to check network connectivity: http://www.google.com and http://www.microsoft.com.
The combination of the COM persistence hijack, the use of a distinctive 48-byte repeating XOR obfuscation technique with a “dummy” null terminator, and the specific hardcoded network connectivity check leads us to conclude with high confidence that this sample is a newer version of the Candiru attack chain that we
captured
in 2021.
3. Exposing Discover-Tech’s Controlium: Malicious Ad Targeting Platform
This section examines Controlium, a platform that provides a control-panel style interface allowing mercenary spyware customers to target specific users with “controlled ads” that deliver malware. Discover-Tech published the full source code for Controlium’s frontend on the app’s login page, which allowed us to review and reconstruct the user interface.
Discover-Tech provides its customers with access to a platform called
Controlium
that appears to be specifically designed to allow them to push malicious content to individual targeted users alongside advertisements. Customers can use Controlium to select a user for infection or profiling based on their mobile advertising identifier (iOS or Android), browser identifier (MyDSP or Beeswax cookie ID), and/or IP address. Discover-Tech’s malicious ads (referred to as “controlled ads”) sometimes also contain branding of companies that are closely linked to Discover-Tech, or branding from apparently unwitting third-party companies, including Amazon and
AliExpress.
We have no evidence that these ads were purchased by Amazon or AliExpress.
As is standard for many web apps, the entirety of the source code for the Controlium frontend is included on the app’s login page. We visited the login page in a web browser and saved the page to disk to obtain a copy of the frontend.
2
We modified our copy of the code to remove any communication with any external servers, and to reveal all available screens in the UI. We then opened this version in a web browser to explore the app’s user interface.
In our analysis of Controlium, we downloaded only publicly accessible resources without circumventing any access controls. Most data associated with Controlium, such as information about Discover-Tech’s customers and their operations, is intentionally protected with an authorization token. However, we were able to obtain data on Controlium user logins from an unauthenticated API endpoint (see below: ‘Unauthenticated Endpoint’). We also assess that it would have been possible for a hacker to spoof a valid authorization (see below: ‘Authentication Vulnerability’), although we did not test this.
Attribution to Discover-Tech
We found the Controlium platform available on the following websites:
Furthermore, if a user tries to access a particular endpoint in the app called “/jsConfig”, the app displays the following message, which is a possible reference to Discover-Tech’s CEO Dekel Boni:
message='ONLY DEKEL IS ALLOWED!!!';
Finally, an unauthenticated API endpoint (see below: ‘Unauthenticated Endpoint’) shows frequent login activity from users whose names overlap with Discover-Tech employees on LinkedIn.
Controlium: Examining Admin Mode
An account designated as an “admin” on the Controlium platform can configure a number of different parameters for customers of the platform. First, an admin may grant a customer access to the web interface, or the API. It also appears that the Controlium product can be “white labeled” with a different logo, and that access can be restricted to specific IPs.
Next, admins may add restrictions on what type of campaigns a customer may run. These restrictions control which combinations of user IDs and IP addresses they are allowed to bid on, and which “URL Types” they can access.
Customers can have certain “OpSec” restrictions placed on their ad bidding, which appears to be an effort to ensure that customers are not bidding too frequently or too broadly:
There is also another type of “OpSec” called “Ad URL OpSec”, which we explore more in
Section 4
.
Customers can be further restricted based on how many campaigns they can run daily or monthly, or restricted based on a “Domains Whitelist” or “Apps Whitelist”, which appear to control on which domain or within which mobile apps ads can be bid on. As is customary for licensing of an attack platform, customers can be restricted to only bid on ads in certain countries via either an allowlist or blocklist.
Controlium: Examining Customer Mode
The exact steps a user or customer would need to take to use the platform are not clear. The Controlium user interface includes a number of modules and forms that provide, in part, overlapping functionality to set up ad campaigns and monitor ad data.
Controlium users can create a “tag”, which defines a combination of an ad image, a landing page, a “NOAS URL” (see below: ‘A Look at the NOAS Server’), and URLs for logging impressions and clicks.
Users can select a DSP to use for delivering the ad. The available options include Beeswax, Eskimi and Discover-Tech’s own MyDSP. When selecting MyDSP, they can also choose whether to use the Google or Yandex ad exchange.
Controlium’s “OP Creative Upload” module allows users to upload and configure advertising content (e.g. an ad), and then upload the data to a DSP. Users can attach a tag to the ad either by defining a landing page, a NOAS URL and URLs for logging impressions and clicks, or they can paste a “Custom Tag” generated by the “Tag Generation” module.
The available DSP options include “MyDSP WW”, “MyDSP Yandex RU”, “Beeswax (Palm 3)”, “MyDSP Google (Palm 3)”, and others. Users can also select several “Add Ons” including “Infinite FIFO”, “Detect Zuid”, and “User Agent”.
Another module labeled “Campaigns” allows Controlium users to associate “Ad URLs” to selected “controlled ads”, which can be served either in mobile apps or on websites, according to Controlium’s source code. As shown in the screenshot, the module allows users to define target “User IDs” and select a “URL Type”.
The URL types available for selection include “Ad URL”, “Test URL”, “Script”, “User Agent”, “Monitor”, “Pixel”, and “De-anon”. We are unsure what most of these options mean, but we think that for “Ad URL”, the NOAS server returns JavaScript adding a 1×1 iframe to the page pointing at the specified URL, and “Script” may be designed to allow arbitrary JavaScript to run. Any URL is delivered via the NOAS Server (see below: ‘A Look at the NOAS Server’).
Authentication Vulnerability
While the data associated with Controlium’s customers and their operations are nominally protected with an authorization token, it appears that it would be easy for a hacker to spoof a valid token. We did not attempt to exploit this issue, as we believe doing so would have constituted unauthorized access to Discover-Tech’s systems.
The underlying issue stems from Discover-Tech’s improper use of Okta’s
Auth0
product. When a Controlium customer authenticates with
Auth0
, a JWT is returned to their browser. This token is digitally signed by
Auth0
, and contains information about scopes and expiry that the backend server should validate. However, Controlium ignores this token and instead passes a separate
user
object as a token to the backend server. The
user
object simply contains unauthenticated metadata about the user, such as their name and email address. Controlium encrypts this information with a secret key published in the Controlium platform.
Interestingly, the
correct
code to use the JWT as an authorization token was present within the Controlium platform, but was commented out in lieu of the vulnerable code.
Unauthenticated Endpoint
During our analysis of the Controlium platform, we observed that the source code mentioned an endpoint called “/csv-download”, which accepted start and end date parameters. When we sent normal HTTP GET requests to this endpoint without any password, special headers, or authentication token, we received logs showing which users had logged in to Controlium, and from which IP addresses. We successfully exported authentication logs for 128 days and identified 120 distinct usernames logging into the Controlium instances on
controlium[.]net
and
powerium[.]net
. We further delve into this data in
Section 4
.
A Look at the NOAS Server
We were able to elicit code from NOAS servers by testing “dummy” User ID values. For example, we observed that a visit to:
This version of “Mini Platform C” does not appear to support any other options besides “Ad URL” for tasking the NOAS server. A similar version of the “Mini Platform C” app is also available on the site
events-ui.discover-tech[.]io
. The JavaScript code for both app versions is available on archive.org (
1
,
2
).
Additional Customer Mode Functionality
The Controlium platform provides several additional modules, according to our analysis of the app’s user interface and source code.
Two Controlium modules named “Targeting” (also known as “Targeting Config”) and “cTargeting” (also known as “Upload Audiences”) allow users to upload digital identifiers referring to single or multiple targets, including mobile advertising IDs for Android and Apple devices, Beeswax user IDs, MyDSP user IDs and IP addresses. The “Targeting Config” module attaches the uploaded identifiers to a “segment”, a widely used term that
describes
lists of identifiers to be used for targeting in digital advertising.
Controlium users can view data on ad impressions for a target identifier or IP address in the last 30 minutes:
A similar module named “Bid Requests” allows users to view data on recent ad bid requests for a specific target identifier or IP address. It provides a list of records that contain user IDs, the website visited or app used by the user, the IP address of the user’s device and other attributes.
The “Events Logger” module provides access to activity records related to ad serving. The available data sources in another Controlium module named “OP Reporting” include MyDSP, Beeswax, Google, and Facebook. We are unsure what kind of reporting data would be displayed by that module. The “Ads Dashboard” module provides reports about ad impressions, the number of users reached and the amount spent (in $) for active campaigns.
Three Controlium modules named “User Info”, “User API Info”, and “User Sync Info” appear to provide key/value information on specific users upon entering user identifiers. They mention a number of attributes which we do not fully understand. For example, they offer to display user identifiers labeled “UUED” and “UUPD”. One module provides a “User ID Type” selection. The available options include “EYield”, “TYield”, “VYield”, “SYield”, “Sync_User”, “Sync_Domain”, “Sync_App”, “AH_User”. Some of these options appear to be related to user ID syncing across different vendors, which is further examined in
Section 6
.
The modules that provide access to information on bid requests, ad impressions, events, and users can be used for troubleshooting and verification purposes, but also to spy on targets and other users whose data is in the bid requests.
4. Discover-Tech’s Links with Mercenary Spyware, ADINT, and Mass Surveillance Vendors
This section examines links between Discover-Tech and the mercenary spyware companies Candiru and Bindecy
.
We also illustrate that, beyond facilitating mercenary spyware delivery, Discover-Tech is linked to ADINT firms, including Intelos. Discover-Tech also supports mass-deanonymization of internet and app users by a threat actor we call
DARK CARTOGRAPHER
,
which exploits vulnerabilities in mobile networks to unmask users’ phone numbers.
Links with Candiru/Integrity Labs
We observed that Discover-Tech sends encrypted ad impression data to Candiru using Controlium’s “Ad URL OpSec” feature. We identified several 2024 and 2025 Candiru infection links to at least six domains matching
Fingerprint V1
and that also contained a parameter “?q=” whose value was 16 bytes of data in Base64-encoded form. In every case, the value of the “?q=” parameter was correctly decrypted with the “V1” AES-256 key published on a page called “Ad URL OpSec Decoder” on the website
myipinfo[.]io
. The website
myipinfo[.]io
is clearly linked to Discover-Tech: passive DNS data shows multiple overlaps in IP addresses and CNAME records with other Discover-Tech websites, including
powerium[.]net
and
myweb3id[.]io
(see also
Section 7
).
One case of a Candiru infection link bearing a Discover-Tech
Ad URL OpSec
parameter is
listed publicly
on VirusTotal. The “?q=” parameter decrypts to an IP registered at the Saudi Ministry of Foreign Affairs, indicating that organization as a potential target of Candiru spyware via Discover-Tech ads:
We assess that this opsec data is included to facilitate a secure handoff from Discover-Tech to an attacker. The attacker presumably compares the visitor IP for the infection link against the IP encrypted by Discover-Tech, to make sure the link from the ad impression was not silently swapped to a different device (as a security researcher might want to do to capture an exploit).
Tracking the Candiru/Integrity Labs Pre-Sales Team
Based on our analysis of Controlium user logins from an unauthenticated API endpoint (
Section 3
), we identified two users who logged in to Controlium from an IP address in Israel that we attribute to Candiru/Integrity Labs. One of these users, which we refer to as
INTEGRITYPRESALE1
, matched the name of someone listed on LinkedIn as having a “Head of Presale” position in Israel at “Cyber Security Company”. The “Cyber Security Company” page is nominally for a Jakarta-based company, but we think the user selected this page because it has a generic name that conveys the
industry
in which they work without naming the specific company. Viewing the “Cyber Security Company” page on LinkedIn shows “Integrity Labs”, “NSO Group”, and “Integrity Lab” (apparently a typo of “Integrity Labs”) in the top three spots in the “pages people also viewed” panel.
The second user signing in from the Integrity Labs IP address, which we refer to as
INTEGRITYPRESALE2
, has a username that appears to include a first name, and ends in “_pap_pres”. We suspect the “_pres” stands for “presale”. There is a user on LinkedIn who shares a first name with this user, and is a “Presales Engineer” at “Cyber Security Company”, though we cannot be certain it is the same individual.
We identified
INTEGRITYPRESALE1
and
2
signing into Controlium from locations in the following countries: Azerbaijan, Czechia, Israel, Italy, Mexico, Montenegro, UAE, and the United States.
We are unsure what the phrase “pap” refers to, but we noted only two other usernames that contained the string “pap”. They were part of a cluster of users signing in exclusively from the local IP address 10.0.0.52, suggesting these as further possible Candiru-linked users:
While tracking Candiru’s infrastructure in 2025, we noticed that two domain names that matched our
Fingerprint C1
were registered within two hours of each other on March 18, 2025 with
info@rockhoster[.]com
in their SOA record:
outdooutcome[.]comsuggestutterly[.]com
A third domain that looked similar was registered on March 18, 2025 within the same timeframe, also with
info@rockhoster[.]com
in its SOA record, but it
never matched
our Candiru fingerprint:
However, we noted that starting in April 2025, URLs pointing at
sincereaccertain[.]com
were distributed via Discover-Tech ads. The URLs looked like this:
https://sincereaccertain[.]com/?qq=[...]
The qq parameter contained Base64 data. Pasting the Base64 data into Discover-Tech’s “Ad URL OpSec Decoder” (see above) resulted in a successful decrypt using their “V2” AES decryption scheme. The decrypted data looked like this:
<IP>|<Timestamp>|<User-Agent>|<Ad-ID>
In May 2025, we observed
d1fcoizt7mje85.cloudfront[.]net
with URLs and data that decrypted to the same format. We conclude that
sincereaccertain[.]com
is linked to
d1fcoizt7mje85.cloudfront[.]net
because URLs to both domain names appeared to be distributed via the same
Infinite FIFO
ID, number 778. Deployment of the
d1fcoizt7mje85.cloudfront[.]net
URLs appeared to cease in December 2025. We estimate that between hundreds of thousands and millions of users were directed to these domains via Discover-Tech ads.
We identified no similar activity until January 2026, when Discover-Tech appeared to evolve their
Infinite FIFO
feature. The NOAS URL associated with these new Infinite FIFOs was
ppv2[.]mtrtb[.]com
. We were able to gather statistics from an unauthenticated endpoint on this server for five months between January 2026 and June 2026, when Discover-Tech removed the unauthenticated endpoint. The statistics counted (among other things) the number of “
eligible users
”, which appeared to be the number of users who were directed to
ppv2[.]mtrtb[.]com
and
who were intended to receive some infinite FIFO code. We counted a total of 3,637,213 eligible users during this period, though we note that it is possible that Discover-Tech customers other than Candiru may make use of the Infinite FIFO feature.
Later in 2026, we noted a migration to what we assess is “V3 OpSec”, which allows a custom name to be specified for the parameter instead of “qq” (we noted “impid”), and a per-user key. Discover-Tech neglected to update their “Ad URL OpSec Decoder”, so we were unable to decrypt this data.
We were unable to obtain any of the JavaScript code from
sincereaccertain[.]com
or these CloudFront distributions, likely because of
Discover-Tech
’s
Ad URL OpSec
feature, though we note that
Confiant was able to obtain related code
.
Bindecy
Based on our analysis of user logins from an unauthenticated API endpoint (see
Section 3
), we noted that two users,
maya
and
mayaqa
, were logging into Controlium from multiple IP addresses including an IP address in Israel
62.90.129.xxx
. We noted that this IP address was administering multiple websites that had self-signed certificates issued by “
cupid-ca
”:
We identified a total of seven certificates on Censys issued by “
cupid-ca
”. Other domain names included
pickarest[.]com
and
infoanalytics[.]live
. Both pointed to IPs that returned a distinctive speedtest page on port 8443 without TLS:
One of the IPs that matched this same fingerprint was 52.174.65.77, while it was pointed to by the domain:
archer.westeurope.cloudapp.azure[.]com
Other domains pointing to the same IP were connected to a Heroku app:
bd-mainserver.herokuapp[.]com
From talking to our partners, we understand that Bindecy has products called “Archer” and “Cupid”. We believe the “bd” in “bd-mainserver” may also be a reference to Bindecy.
Some of the domain names we mapped to Bindecy were registered in the name of an Israeli software company, Moveo Group. Additionally, one of the domain names appeared to be a domain name bearing the name of an Israeli web developer and entrepreneur without any obvious connection to Bindecy.
We were able to fingerprint Bindecy’s servers and identify locations of some Bindecy operators: Belgium, Germany, Norway, Portugal, Sweden, Singapore, and Spain. We also identified a customer that appeared to be using Bindecy’s spyware in Mexico and Colombia, but were not able to determine the location of the operator.
We further discuss the Israeli spyware vendor Bindecy and its corporate network in
Section 8
.
Bindecy did not respond to our request for comment within the timeline provided.
Links with Intelos, DARK CARTOGRAPHER, and Other Vendors
Intelos
Based on our analysis of user logins from an unauthenticated API endpoint (
Section 3
), we identified several users logging in to Controlium from IP addresses that returned certificates for
globaldatapoints[.]com
. We identified passive DNS data showing a CNAME record for a subdomain of
globaldatapoints[.]com
that contained the word “Intelos”.
Furthermore, a subdomain of
globaldatapoints[.]com
briefly returned a login page for an application called “AD/HOC”, which has been
reported
to be the name of an Intelos product.
We identified at least 15 Controlium users that we believe are linked to Intelos.
Table 1
shows users that signed in from locations that did not appear to be VPNs or proxies:
Username
Sign-ins from
bear
Belgium, Israel, Singapore, Poland
timtamteam64
Israel, Spain
liinine77263, johny7716243
Macedonia
Landrover
Spain
bear_solo
Hungary
carpe_eb
Israel, Portugal, UAE
rollsgreen1
Spain
JonG
Belgium, Czechia, Greece, France, Israel, Italy, Serbia
mishreg
Israel, Latvia
Barhi
Israel, Thailand
metalica1
Belgium
Table 1
Controlium sign-ins from Intelos-linked users.
The mercenary ADINT vendor Intelos, which reportedly offers both ad-based geolocation surveillance and the delivery of spyware via ads, has additional links to Discover-Tech via Intelos shareholder Eric Banoun (2018 – present), who was also a director of Discover-Tech (2020 – 2025), as detailed in
Section 8
.
Intelos did not respond to our request for comment within the timeline provided.
DARK CARTOGRAPHER: Mass-Deanonymization With Ads
We identified Discover-Tech ads that sought to exploit the well-known “WebRTC IP Leak”
issue
, which can potentially reveal the IP address of VPN and proxy users. The same ads also attempted to unmask the phone number (MSISDN) of mobile users who were served the impression. The MSISDN leaks exploit various issues, including widespread problems with so-called “zero-click login” technologies, which aim to facilitate frictionless authentication and purchases for users on their mobile devices.
One way “zero-click login” operates is that mobile providers select certain websites for “HTTP header enrichment,” so that when plaintext HTTP requests pass through the provider’s mobile gateway, an HTTP header (like X-MSISDN) is added to the request that provides the user’s phone number to the website. As an alternative to HTTP header enrichment, third-party services may work directly with the telco to facilitate this “zero-click login”. There appear to be widespread bugs with this allowlist matching, as well as bugs or security issues in third-party enrichment providers. While mainstream web browsers such as Chrome are moving towards blocking any non-HTTPS requests, it is likely that the app ecosystem will still embed webviews that permit non-HTTPS content.
We taxonomized the issues into five types, exploited by attackers across numerous mobile providers in more than 30 countries in North America, South America, Europe, Africa, and Asia, and disclosure to companies is in progress. Once the disclosure process is complete, we will release our subsequent report delving into technical analysis and attribution of these attacks.
Notably,
DARK CARTOGRAPHER
’s infrastructure links to both a mercenary adtech vendor and a U.S. government contractor. It is rare to see such direct overlaps between mercenary vendors and U.S. government or intelligence contractors. We assess that this attacker has been exploiting MSISDN leak issues since at least 2019, fronted by a variety of mercenary adtech companies. Our investigation into this threat actor is ongoing.
Other Vendors
We found a number of Controlium users that we could not conclusively attribute to a specific company: the user
mi19mos25a
primarily logged in from India, and occasionally Israel; the user
rcs1
exclusively logged in from Italy, primarily a static IP in Milan; the user
Pindi
exclusively logged in from Pakistan.
5. Uncovering Discover-Tech’s Billion-Bid Scale Ad Targeting
To understand the scope of Discover-Tech’s activity, we analyzed nearly four billion ad bidding records that were publicly exposed on a Discover-Tech website. We found that Discover-Tech ads were displayed in over 70,000 mobile apps, and over 120,000 websites between March and June 2026.
We found two world-readable Apache Druid instances running on Discover-Tech’s website
mtrtb[.]com
. The
druid.mtrtb[.]com
endpoint contains bidding data for Discover-Tech’s MyDSP platform, which is connected to several upstream ad providers including Google, Yandex, Vungle, and Sunteng. The
cn.druid.mtrtb[.]com
endpoint appeared to contain additional bidding data for Discover-Tech’s use of Sunteng. These instances did not contain any information about Discover-Tech’s use of Beeswax or Eskimi DSPs. Discover-Tech appeared to shut down both instances in August 2026.
There were no instances of cookie IDs, advertising IDs, or GPS coordinates recorded in the Druid data. However, the data includes IP addresses or /24s, presumably provided by SSPs, as well as city-level geolocation information. The provenance of the location data is unclear.
What Upstream Ad Providers does MyDSP Use?
MyDSP appears to make use of several upstream ad providers, which are listed in the “exchange” field of the database. We identified five distinct values.
Exchange
Share of Bids
YANDEX
67.4%
GOOGLE_AD_MANAGER
24.74%
VUNGLE
7.24%
GOOGLE_RETARGETING
0.05%
SUNTENG
0.03%
TABLE 2
Share of MyDSP bids by the value of the “exchange” column.
No Good Evidence of Legitimate Ads
We reviewed bidding data for MyDSP for four months (March through June 2026). In this period, Discover-Tech’s MyDSP bid on 3,770,286,576 impressions, and appeared to win 441,954,291 (11.7%). About 76.7% of the bids were for ad impressions in mobile apps, and 23.3% for impressions in the web browser.
The database shows a total of three advertisers, with nine total combinations between advertiser and an advertiser domain name. Most of the advertisers seem to be directly attributable to Discover-Tech itself, or to entities we consider to be linked to it, like Akedo, MyIPInfo, and Volasim’s RemindMeWhere app.
Advertiser
Advertiser URL
Share of Bids
discover-tech
akedo.gg
37.31%
AliExpress
www.aliexpress.com
34.70%
MyIpInfo
https://myipinfo.io
12.65%
discover-tech
www.remindmewhere.app
9.61%
discover-tech
www.aliexpress.com
3.57%
discover-tech
https://myipinfo.io
1.36%
discover-tech
s.taobao.com
0.79%
discover-tech
https://aliexpress.com
0.01%
discover-tech
https://king.com
0.01%
table 3
Share of MyDSP bids by the value of the “advertiser” column.
The database records that MyDSP spent approximately
$109,091
in this period, assuming the cost is recorded in micros of USD. The database appears to be set up to record information about the revenues and profits generated by MyDSP for each ad, including fields like
advertiser_revenue
,
dsp_profit
, and
margin
, but these are always set to zero except for a three-day period in June where
advertiser_revenue
is
nonzero for impressions shown for the MyIpInfo advertiser. The database also contains fields to record conversions, though these are always set to zero. A “conversion” typically refers to a purchase, app install or other action taken by a person who was exposed to an ad. It is highly unusual for an ad vendor that not a single ad leads to such an action, although it is conceivable that the bidding records might not track and record this information.
We reviewed ads for the major advertiser on this list that could hypothetically be a real external advertiser, “AliExpress.” The ads all appear to be a generic image that says “SALE” and shows a picture of miscellaneous products from Ugreen, a Chinese consumer electronics company.
We note that the landing page of some of the AliExpress ads is an AliExpress affiliate link.
https://s.click.aliexpress[.]com/e/_c3U5aNwL
We have no evidence of a business relationship between Discover-Tech and AliExpress and/or Ugreen, and we think the generic nature of the advertising content, the lack of any revenue recorded, and the lack of any conversion data recorded suggest these ads were likely not purchased on behalf of AliExpress or Ugreen.
Normally, a DSP would aim to earn money by selling ads to entities seeking to advertise goods and services. In this case, there is no good evidence that Discover-Tech’s MyDSP is earning money in this way.
Evidence of Ads With Attacker Script Tags
The MyDSP data shows that at least 718,748,885 of the bids (about
19%
), were to show ads that apparently contained a
script
tag pointing to a NOAS server. We believe that the NOAS server is, generally, tasked to return some JavaScript exactly once to specific mobile ad ID and/or browser/cookie ID values, and subsequent visits return nothing until re-tasking.
We assessed whether an ad was likely to contain such a
script
tag by searching for ads whose name included the strings “infi” (a reference to Controlium’s “Infinite FIFO” feature), “NOAS”, “ppv2”, and “pqv2”. The “ppv2” and “pqv2” strings appear to be references to a newer version of the “Infinite FIFO” feature exposed as “Authenticator Manager” in the Controlium UI. We suspect that “pqv2” is for testing and/or QA, whereas “ppv2” is for production.
MyDSP submitted bids to show these NOAS ads to users with IP addresses that geolocate to 161 countries. It is important to note that IP geolocation can be inaccurate due to the use of satellite providers, VPNs, or other reasons.
Country
Bids
Yemen
457,283,658
Pakistan
139,427,322
Montenegro
97,595,716
Brazil
76,108,495
Mexico
32,675,229
China
30,072,952
Belarus
25,122,945
Armenia
23,189,997
Czechia
19,107,486
Israel
18,477,493
TABLE 4
The top 10 countries by raw bids.
Country
Bids Per Capita
Montenegro
156.68
Yemen
13.99
Armenia
7.49
Latvia
3.14
Seychelles
3.13
Belarus
2.77
Israel
1.80
Czechia
1.75
Denmark
0.99
Azerbaijan
0.97
TABLE 5
The top 10 countries by bids per capita.
Looking at the full bidding data, without considering whether ad auctions were won, MyDSP also made a significant number of bids (> 10 million) on ad impressions geolocated to Russia, Indonesia, United Arab Emirates, Australia, United States, Sweden, Norway, Netherlands, Germany, Malaysia, and Cuba. However, we note that the Netherlands, Germany, and United States geolocation appeared to primarily be from VPNs or server IPs in these countries.
Apps and Websites That Displayed the Ads
Ads with attacker script tags were shown to users of 75,373 different Android and iOS apps and to visitors of 120,768 different websites in mobile and desktop browsers. These numbers refer to ads actually displayed to users of apps and websites rather than raw bids.
iOS apps deployed fewer of those ads than Android apps. The messenger
Viber
, which ranks second on iOS, showed only around 200,000 ads as compared to around 700,000 on Android. Still, the ads were displayed across a similarly wide range of iOS apps.
As discussed above, Discover-Tech’s ad targeting appears to focus on mobile apps. Only 23.3% of the bids we analyzed were for ad impressions in the web browser. Websites that displayed more than one million ads with attacker ad scripts include news publications from Armenia (mamul.am) and Serbia (kurir.rs). More than 100,000 of those ads were shown on news publications and other popular sites from Montenegro (dan.co.me, vijesti.me), Yemen (adngad.net), and Pakistan (whatmobile.com.pk). The site Weather.com displayed around 400,000. Larger numbers of ads were also shown on yahoo.com, AccuWeather.com, tripadvisor.com, yandex.ru, and news sites in Denmark (bt.dk), Bosnia (slobodna-bosna.ba), Egypt (almasryalyoum.com), and Kazakhstan (vesti.kz). The long tail of websites that deployed those ads included everything from 9gag.com and foxnews.com to bbc.com, cbc.ca, haaretz.co.il, and nytimes.com.
Ad Impression Data Highlights Systemic Risk
Our review of the ad bidding data indicates that Discover-Tech ads were shown on devices in national-security-sensitive networks around the world. These include the networks of various ministries of defense, armed forces, national cyber agencies, intergovernmental organizations and multilateral security organizations including NATO, and networks associated with critical infrastructure. The data also show impressions from the networks of media organizations around the world. At minimum, we assess that these ad impressions would have resulted in profiling by Discover-Tech. In some cases, the impressions could have resulted in code from Candiru or other entities running on the user’s device.
A Discover-Tech ad impression does not in and of itself confirm targeting or infection with spyware. However, the fact that Discover-Tech was able to bid on and show ads on these networks highlights the systemic risk posed by AdFection and the advertising ecosystem, and warrants urgent investigation to determine whether any users on these networks were infected with spyware. We also note that our visibility into Discover-Tech’s impressions is confined to the data on Discover-Tech’s MyDSP platform. This data does
not
include data from Beeswax and Eskimi, and covers a limited time period. This incompleteness further reinforces the need for follow-up investigation.
NATO and the United Nations
We identified impressions in NATO and United Nations networks.
European Union Entities
In Europe, we identified impressions from the networks of the European Parliament, the European Commission, and the Council of the European Union’s General Secretariat.
Nordic Government & Critical infrastructure Clusters
We identified widespread impressions in Nordic states, including Denmark, Norway and Sweden. We assess that this cluster warrants close scrutiny, and note some of the more concerning findings:
In Norway
, Discover-Tech ads were shown to users on the networks of the legislature (Stortinget), the Norwegian Digital Agency (Digitaliseringsdirektoratet), the Norwegian Communications Authority (Nasjonal kommunikasjonsmyndighet), state IT networks (Statens IT), the Norwegian Police (Politiets It-enhet) and serious crime units (Kripos), among many others. Notably, we also identified impressions in multiple county and municipal networks across northern Norway, including near key military installations (e.g. Alta, Harstad, Nordland).
In Sweden
, Discover-Tech ads were shown to users on the networks of the Armed Forces, the national grid operator (Svenska Kraftnat), the state owned power company (Vattenfall AB), the national internet exchange (Netnod AB), defense contractor Saab, Volvo Group, university networks including the Chalmers University of Technology, national research funding bodies (Verket for Innovationssystem), and Sweden’s national Meteorological and Hydrological Institute (Sveriges Meteorologiska och Hydrologiska Institut).
In Denmark
, Discover-Tech ads were shown to users at the national rail network (Banedanmark), the national post (Post Danmark), Denmark’s National Research and Education Network (Forskningsnettet), alongside multiple municipal and regional government networks and public health authorities. They were also shown on networks at Denmark’s digital infrastructure company KMD A/S, renewable energy sector firms such as Vestas Wind Systems and Ørsted, Grundfos, banks including Den Danske Bank, and Copenhagen Airports.
Australia: Critical Infrastructure, Government & University Networks
The ad impression data also reveal a substantial cluster of impressions in Australia, including on government and private-sector networks associated with critical infrastructure sectors like grid and power companies, as well as networks associated with universities and research centres, including entities working on nuclear research, like the Australian Synchrotron, and the Australian Nuclear Science and Technology Organisation.
Governmental Targets: A Global List
Numerous other geographically distinct clusters of widespread impressions appear among the data. Many of these impressions occurred in defense, foreign affairs, internal affairs, or security bodies.
Table
6
provides examples of the government networks where we found Discover-Tech impressions.
Government
Examples of networks with Discover-Tech impressions
Armenia
Central Electoral Commision
Central Bank
Office Of The Prime Minister
Czechia
Ministry of Finance
Ministry of Foreign Affairs
Ministry of the Interior
State Institute for Drug Control
Czech Telecommunication Office
Ministry of Agriculture
The Czech National Bank
Ministry of Labour and Social Affairs
Municipal Office, Prague
National Cyber and Information Security Agency
Israel
Ministry of Health
Ministry of Foreign Affairs
Government ICT Authority
Ministry Of Defence
Israeli Police
Bank of Israel
Israel Internet Association
Israel Airports Authority
Italy
Bank of Italy
Parliament (Camera dei deputati)
Ministry of Defense
Table 6
Examples of government controlled or operated networks where we identified Discover-Tech impressions.
Our investigation is ongoing. As of now, we have identified impressions in government-operated networks in the following countries:
Armenia (including the Office of the Prime Minister)
Australia
Azerbaijan
Bhutan
Brazil
Czechia
Denmark
Indonesia
Israel
Italy
Kosovo
Libya
Malaysia
Mexico
Montenegro
Norway
Pakistan
Russia
Somalia
Sweden
Thailand
The United Arab Emirates
The United States (American Samoa)
Uruguay
We also found impressions on the networks of election oversight bodies in Armenia, Indonesia, and Mexico.
Chips & Semiconductors: from research to fabrication
We found what appears to be a nexus among the advanced semiconductor industry, covering the chain from design, memory, to chip development and fabrication, with the greatest number of impressions seen in Intel networks, alongside Nvidia, Sandisk, Texas Instruments, Broadcom, Micron Technology, and ARM. We also identify numerous research entities in this category like IMEC. We also identified impressions within the networks of large U.S. tech firms including Apple, Microsoft, and Motorola.
We also identified impressions in specifically defense-sector tech entities, including Raytheon (U.S.) and Elbit Systems LTD (Israel), and the nuclear sector, including the Westinghouse Electric Company (U.S.).
Global Media Organizations
Given our identification of zero-click attacks against Al Jazeera, we scrutinized bidding records for impressions within the networks of media organizations. We found many. Often, these included the largest media organizations in a particular country, as well as public broadcasters and media conglomerates. The countries (with a count of institutions) include:
Australia: 3
Denmark: 3
France: 1
Mexico: 2
Israel: 3
Italy: 2
Norway: 2
Sweden: 3
We also identified impressions within the networks of international media services. Our investigations into these cases are ongoing.
Confiant’s Findings Underscore Dangers of AdFection
The researchers at Confiant analyzed targeting data and found signs that these ads were displayed on networks of major governmental entities, including the U.S. Department of Defense, the Dutch Ministry of Economic Affairs, Estonia’s Information System Authority (RIA), Spain’s Ministry for Digital Transformation and Civil Service, Armenia’s Office of the Prime Minister, and multiple government entities in Israel. Their research also found signs they were shown in networks of the International Atomic Energy Agency (IAEA) and the International Criminal Court.
6. How Discover-Tech Deploys Ads in the Browser
In this section we show how, beyond targeting users of mobile apps, Discover-Tech deploys a range of techniques to deliver ads and track users while they browse across websites. This involves Discover-Tech running its own code in the user’s web browser, both while deploying ads to users and independently of showing them ads. We explore Discover-Tech’s “Banner Tester” tool to show how the company generates tracking tags and pixels attached to ads, including code that connects to a NOAS server, which we identified as a vector for spyware delivery. We also document how Discover-Tech engages in “ID syncing” with other ad vendors, and how it leverages IAB Europe’s “Transparency and Consent Framework” to appear GDPR-compliant, even while facilitating unwanted and malicious activity.
An ad displayed to a website visitor consists of an image or video to be shown and a link to be clicked, but
can
also
carry
HTML and JavaScript code that connects to one or more domains in order to track users, ad impressions, clicks, and other activities. This code is typically referred to as an
ad tag
. A related concept, a so-called
tracking pixel
, also describes code running in the web browser that connects to third-party ad vendors. Ad vendors use additional tracking code for
user ID syncing
by
exchanging
user identifiers with each other in order to identify, profile, and target website visitors across sites and vendors.
Our analysis of ad tags, tracking pixels, and ID syncing activities associated with Discover-Tech’s ad delivery is based on an analysis of publicly available code, browser testing and ad transactions archived by the web investigation tool urlscan. While ads displayed in mobile apps similarly
carry code
that connects to ad vendors, this section focuses on Discover-Tech ads displayed in the web browser.
Discover-Tech’s Ad and Tracking Tags
We found two versions of another app related to Discover-Tech’s Controlium platform named “Banner Tester” published on the sites
bt.myweb3id[.]io
and
bt.platc-tester[.]com
. The apps provide the ability to generate and preview tags for banner ad campaigns in the browser.
The generated tags contain an ad creative and a link, which appear to serve testing purposes:
The tags contain additional HTML and JavaScript code that is prepared to make a number of requests to different URLs, including NOAS URLs and URLs for ad impression and click tracking. One version of the app generates tags for the “Target” platforms “Default” or “Mini Platform C”. The other version can generate tags for production, staging and testing environments, according to its source code. The generated ad tag URLs differ depending on the chosen options.
Ad tag URLs for different platforms and environments
Table 7
Ad tag URLs generated by Discover-Tech’s “Banner Tester” app.
As the impression and click logging URLs generated by the app contain the parameter “dsp=BW”, we assume that these ad tags are designed to be deployed via the DSP Beeswax.
Several records archived on urlscan show examples of how Discover-Tech actually deployed very similar ad and tracking tags during visits to websites:
During a visit to the Russian literature website
livelib[.]ru
in May 2025, Discover-Tech delivered an Akedo ad via its ad system MyDSP and Yandex, including requests to
noas.mtrtb[.]com
and
dtech.adtimizer[.]co
(
urlscan
).
During a visit to
nbcnews[.]com
in August 2025, Discover-Tech delivered an Akedo ad via its ad system MyDSP and Google, including requests to
tracker.mtrtb[.]com
and
dtech.adtimizer[.]com
(
urlscan
).
During a visit to a Spanish-language
horoscope site
in July 2025, Discover-Tech delivered a MyIPInfo ad via Beeswax DSP and Google, including requests to
infinoas.mtrtb[.]com
and
dtech.adtimizer[.]co
(
urlscan
).
User ID Syncing with Other Ad Vendors
Unlike apps on mobile devices, web browsers do not allow websites to access a universal device identifier. The process of “ID syncing”, often also referred to as “cookie syncing”, addresses this lack of a universal user identifier. Research
shows
that digital advertising firms and data brokers use sophisticated forms of ID syncing to identify, profile and target web users across vendors. They achieve this by constantly exchanging user identifiers with each other, storing them in the browser and retrieving them again while users visit different websites that embed third-party tracking code.
We found evidence showing how Discover-Tech engages in ID syncing with Comcast’s ad system Beeswax, Yandex, and Microsoft’s ad platform Xandr.
Discover-Tech appears to use its
myweb3id[.]io
domain for ID syncing with Yandex. This domain is highly prevalent as a tracking domain on a large number of websites.
Starting
in May 2025, urlscan
archived
more than 10,000 records that include third-party requests to the domain
events.myweb3id[.]io
, most of them occurring during visits to Russian websites.
A recent
urlscan record
shows an example of a typical request chain that involves ID syncing across Discover-Tech’s
events.myweb3id[.]io
domain and the following Yandex endpoint:
an.yandex.ru/mapuid/discovertechis
The URL component “discovertechis” indicates some kind of business relationship between Discover-Tech and Yandex.
Discover-Tech appears to use another domain,
tracookiepixel[.]xyz
, which is associated with
myweb3id[.]io
via DNS links and which is also highly prevalent as a tracking domain on a large number of websites, for ID syncing with Beeswax.
Starting
in July 2025, urlscan
archived
more than 10,000 records that include third-party requests to
tracookiepixel[.]xyz
, many of them occurring during visits to popular websites including
IMDb
and
New York Times
.
A recent
urlscan record
shows an example request chain that was initiated during a visit to the website of The Guardian, which involves ID syncing across Discover-Tech’s
tracookiepixel[.]xyz
domain and Beeswax’ tracking domain
bidr[.]io
. The requests contain the parameter “bee_sync_partners=dtech”, which indicates some kind of business relationship between Discover-Tech and Beeswax.
These ID syncing activities typically take place during website visits even when a user was not served a Discover-Tech ad. We are unsure how exactly Discover-Tech uses its browser ID syncing capabilities. Generally, being able to synchronize and correlate user identities across vendors is
considered
a precondition for individual-level ad targeting in the web browser. The Controlium platform, as examined in
Section 3
, offers to upload lists of Beeswax identifiers for ad targeting in its “cTargeting” module, among mobile advertising IDs, IP addresses, and other identifiers, based on our analysis of the source code.
We conclude that many websites make constant requests to Discover-Tech’s domains
events.myweb3id[.]io
and
tracookiepixel[.]xyz
in the background. These requests serve the purpose of ID syncing with Beeswax and Yandex, and Discover-Tech’s domains receive, in addition to user identifiers, at least the website visitor’s IP address and information about their browser and operating system.
Discover-Tech’s Tracking Pixel
Separately from Discover-Tech’s large-scale ID syncing on many websites, we found JavaScript code for a “tracking pixel” that was loaded during recent visits to only a few sites including
myipinfo[.]io
,
cookiesurfer[.]com
, and Discover-Tech’s corporate website,
discover-tech[.]io
(all three
archived
on
urlscan
).
These sites loaded versions of the tracking pixel code, both broadly similar, from the following URLs:
Based on our analysis of the source code, the tracking pixel serves the purpose of storing, retrieving and synchronizing user identifiers across Discover-Tech, Beeswax, Xandr, and Yandex. Once loaded on a website, the code stores user identifiers associated with Discover-Tech, Beeswax, and Xandr in the user’s web browser in order to retrieve them again during subsequent visits to websites that load the same code.
The code is designed to initiate the ID syncing process by sending Discover-Tech’s user identifier to Beeswax and Yandex in order to receive corresponding Beeswax and Yandex identifiers. Additionally, the code retrieves the user’s Xandr identifier. Request chains
archived
on urlscan show Discover-Tech’s tracking pixel in operation, including ID syncing with Yandex and the retrieval of user identifiers from Beeswax and Xandr.
When the tracking pixel code detects that a website visitor is located in a region where the GDPR applies, based on geolocating the user’s IP address, it uses IAB Europe’s
Transparency and Consent Framework (TCF)
to process user “consent” signals for the three TCF vendors Discover-Tech Ltd, Xandr Inc, and BeeswaxIO Corporation. This demonstrates how Discover-Tech utilizes its listing as a registered and approved ad vendor by IAB Europe, as discussed in
Section 9
.
The code also clearly maps the acronym “ZUID” to Xandr’s user identifier. As detailed in
Section 4
, several Controlium modules refer to an option labeled “Detect ZUID”. We are unsure how Discover-Tech’s Controlium platform exactly utilizes this identifier. As the “Detect ZUID” option is among a few “Add Ons” that can be activated when setting up an ad campaign, it may serve the retrieval of Xandr user identifiers either for ad targeting or for tracking targets. Xandr (Microsoft Advertising) did not respond to our request for comment within the timeline provided.
Generally, the purpose of Discover-Tech’s tracking pixel is unclear. As a large share of Discover-Tech ads are designed to lead users to the site
myipinfo[.]io
when clicking on those ads, the tracking pixel loaded during the site visit then correlates a target’s Discover-Tech user identifier with their Beeswax, Xandr, and Yandex identifiers.
Records
archived
on urlscan show that the MyIPInfo website loaded a version of the tracking pixel from another domain associated with Discover-Tech in the past:
Discover-Tech has been deeply embedded and interconnected with the digital advertising industry for years. In this section, we further investigate Discover-Tech, key persons affiliated with the company, related companies, and the origins of its MyDSP advertising technology.
Adtech with a Background in Spytech
Discover-Tech purports to be a typical digital advertising firm, offering a so-called Demand-Side Platform (DSP), which facilitates the delivery of targeted ads. On its website, it
claims
to have “unrestricted access to top-ranking apps with 1+ billion daily active users” via a “worldwide ad exchange”. In addition to its DSP, Discover-Tech
offers
“monetization” solutions to mobile network operators and mobile device manufacturers, which we discuss further below.
Israeli company records we reviewed link Discover-Tech’s website,
discover-tech[.]io
, to the company Discover-Tech Ltd registered in March 2020, with Dekel Boni listed as its initial director and sole shareholder. In the two months after its incorporation, Eric Banoun, who is a major figure in the Israeli surveillance technology industry, joined Discover-Tech’s board of directors, and the shareholder base was expanded. From April 2020, the company’s shareholders included Dekel Boni, Guy Lants, Yaniv Basil, Zfanya Leib, Sergei Bartashevich, and Chaia Services Ltd, a company registered in the British Virgin Islands. Eric Banoun left the company’s board of directors in January 2025 and Chaia Services Ltd ceased to be a shareholder in March 2026. As of July 2026, Discover-Tech is directed by Dekel Boni and owned by Boni, Basil, and Lants.
Eric Banoun co-founded the cyberespionage firm Circles, a close NSO Group
affiliate
, and Senpai Technologies, which is
part of
the Intellexa consortium. We could not access corporate registration information on Discover-Tech’s shareholder Chaia Services Ltd. However, a
Haaretz
investigation reported that one of Chaia’s directors was Sara Hamou. Hamou managed Intellexa’s corporate network and was
sentenced
to eight years in prison (pending appeal) by a Greek court for her role in the
Predatorgate
scandal. Eric Banoun was listed as a director of a similarly named U.S.-based company,
Chaia Services Tech LLC
, which was dissolved in 2025.
Based on the links to Eric Banoun and Chaia Services Ltd., we conclude that Discover-Tech was linked to the spyware industry for almost six years, according to Israeli company records and other publicly available information.
Discover-Tech’s other shareholders, including Dekel Boni who is now the company’s sole director, have a background in digital advertising, previously working for adtech firms like Digital Turbine and Taptica,
according
to
their
LinkedIn
profiles
.
3
Boni lists himself as Discover-Tech’s CEO, Guy Lants as its “Director of Product”. Yaniv Basil lists himself as the company’s “Chief Technology Officer” between 2020 and 2023.
Ad Vendor Registrations with Google and IAB Europe
Despite information about Discover-Tech’s links to figures in the spyware industry that could be readily obtained from a review of corporate records, major advertising industry organizations added the company to several lists of “certified” or “approved” ad vendors, which helped make the company appear to be a legitimate advertising firm and facilitated its participation in the advertising ecosystem at scale.
As discussed in
Section 9
, Google listed Discover-Tech among its “Ad Manager Certified External Vendors”, “Ad Technology Partners”, and “Ads Personalization Providers” from 2020 until 2026. The advertising industry association IAB Europe listed the company on the “Global Vendor List” for its “Transparency & Consent Framework” (TCF), also from 2020 until 2026. In
Section 9
, we examine the implications of Discover-Tech’s ad vendor registrations with Google and IAB Europe in detail.
Both the Google and IAB vendor registrations consistently refer to the Israeli company Discover-Tech Ltd and the domain
discover-tech[.]io
. In addition, Google’s list of “Ads Personalization providers” clearly links Discover-Tech to the domains
mtrtb[.]com
and
mydsp[.]io
, which it listed among “domains which can be attributed to the provider” Discover-Tech Ltd.
Tracing the Origins of Discover-Tech’s MyDSP Advertising Tech
As discussed in
Section 5
, the domain
mtrtb[.]com
and the ad system MyDSP (
mydsp[.]io
) play key roles in Discover-Tech’s ad targeting.
According to historical whois information, Discover-Tech Ltd took ownership of both domains in 2020. While domain registration data became anonymized in 2022,
mydsp[.]io
redirected
to
discover-tech[.]io
until early 2026. Both
mtrtb[.]com
and
mydsp[.]io
can be “attributed” to Discover-Tech Ltd according to Google, as discussed in
Section 9
.
MyDSP was
launched
by the Israeli adtech firm Matomy in 2016. In 2018, MyDSP was “connected” to Matomy’s MobFox subsidiary, had “access” to 50 billion daily ad impressions and was able to target 500 million users,
according
to its website. Also in 2018, Matomy
sold
MyDSP to the Cypriot firm Marketcom Technologies Ltd, which belongs to the e-commerce firm Market Group owned by the Israeli billionaire Teddy Sagi, as confirmed by
public filings
,
business data
,
media reporting
, and whois information for the domains
mydsp[.]io
and
mtrtb[.]com
. A
2019 version
of the
mydsp[.]io
site confirms that MyDSP ultimately became part of Glispa, a Berlin-based adtech firm also
acquired
by
Market Group
back in 2015.
We are not aware of any robust information that shows how Discover-Tech Ltd eventually took over MyDSP, but whois information confirms that Discover-Tech Ltd, founded in March 2020, took control of the domains
mydsp[.]io
and
mtrtb[.]com
from Marketcom Technologies Ltd at some point between June and October 2020. According to a
Google record
, the ad provider with the ID ‘3036’ changed from MarketDSP (
advertising.market[.]com
) to “Discover-Tech Ltd” (
discover-tech[.]io
) on July 31, 2020. While the company names and websites changed, the list of additional domains attributable to this Google ad provider stayed identical: (
mydsp[.]io and mtrtb[.]com
).
JavaScript code related to MyDSP’s admin interface for customers, published on
admin.mtrtb[.]com
, details a list of ad vendors MyDSP was connected to at an unspecified point in time (
archived code
). The list includes Google, Yandex, Vungle, and Sunteng. Thus, it confirms the connections with the ad vendors we found in Discover-Tech’s bidding records (
Section 5
). In addition, the list suggests that MyDSP was or is also connected to the ad vendors MobFox, Inneractive, MoPub, PulsePoint, RhythmOne, GumGum, Pubmatic, Smaato, Sonobi, NativeAds, Unity, Q1Media, and Applovin.
Offerings for Mobile Carriers and Device Vendors
Discover-Tech Ltd itself can be traced back to a company named RelevanTech Ltd (relevantech[.]com), founded by Discover-Tech shareholders Dekel Boni and Yaniv Basil in 2015, according to
their
LinkedIn
profiles
and Israeli company records we reviewed. Like MyDSP, RelevanTech was also
acquired
by Market Group’s Glispa in 2017, and became
Glispa Discover
. Boni and Basil then worked for Glispa, before creating Discover-Tech Ltd in 2020.
The descriptions of the services provided by RelevanTech (
2016
), Glispa Discover (
2017
), and Discover-Tech Ltd are very similar. The current
discover-tech.io
site
promises
to help mobile network operators and mobile device manufacturers benefit from “sponsored and tailored app recommendations”, in addition to the company’s DSP offering. The 2022 version of the site
explained
that Discover-Tech would “place” mobile apps on new mobile devices “from the moment” they are “turned on” and provide “operator certified installs” of apps on new devices.
We are not aware of any robust information that shows how Discover-Tech’s founders regained control over what was left of RelevanTech from Glispa, but whois information confirms that Discover-Tech Ltd regained control of the domain
relevantech[.]com
in July 2020.
In 2021, Discover-Tech Ltd operated a mobile app on behalf of the Serbian subsidiary of the mobile network operator A1 Telekom Austria, according to a
terms of use
agreement, which explains that the app would provide A1 customers with content from both A1 and Discover-Tech. The description on the
2021 version
of the Serbian A1 website suggests that the app, named “Moy A1” (“My A1”), enabled A1 customers to check their mobile plan, download invoices, and buy additional credits. Put differently, Discover-Tech was sitting inside the official app of the third-largest Serbian mobile operator. We do not know for how long Discover-Tech was involved in operating this app.
The
2020 version
of the Discover-Tech lists A1 and device manufacturers like Samsung, Tecno, and Wiko among the company’s customers. We did not further investigate Discover-Tech’s mobile carrier and device manufacturer business, which may or may not be active anymore.
In conclusion, we believe that Discover-Tech emerged from both RelevanTech and MyDSP, both previously owned by Glispa. While MyDSP and additional software for the delivery of malicious ads appear to be operational in 2026, an asset sale discussed in the next subsection suggests that Discover-Tech may not offer its services for mobile carriers and device manufacturers anymore.
A Sale of Assets Leaves Open Questions
In 2021, the Dubai-based firm Affle MEA FZ-LLC, part of the mobile advertising group Affle, based in Singapore and India, acquired “business assets” from Discover-Tech Ltd, according to
public filings
. Publicly available
financial statements
refer to the acquisition of a Discover-Tech “business segment” including “brand, IP, domain, business relationships and goodwill”.
Public filings
further specify that Affle acquired Discover-Tech’s “mobile device marketing platform” that provides “initial device customization” including “dynamic app discovery and recommendation at initial boot or reset of a device” through its integrations with device manufacturers and mobile network operators. An Affle
press release
quotes Discover-Tech founder Dekel Boni stating that he was “proud” that Discover-Tech’s “technology” that “powers the first interaction a user has with his new device” would become part of the “app discover offering” of Appnext, another company acquired by Affle.
Based on the information available to us, we believe that Discover-Tech Ltd sold its offerings for mobile carriers and device vendors examined in the previous subsection, to Affle. We have no reason to believe that Affle has any control over Discover-Tech’s malicious ad operations that we investigate in this report. However, the exact scope of this asset sale remains unknown to us. Affle did not respond to our request for comment within the timeline provided.
Links to Intelos and Other Websites
In a parallel
investigation
, the ad security firm Confiant found that the websites
discover-tech[.]io
and
tekma-dmp[.]ai
were published from a single user account using the website publication system Wix, which embeds the customer “userid” in each site’s page metadata.
Additionally, we found that the website
discover-tech[.]io
has been sharing a single Wix user account with the website
intelos[.]io
for years. At some point after February 2026, the site
intelos[.]io
switched to a different “userid”. This switch strongly suggests that the websites
discover-tech[.]io
and
intelos[.]io
have been published by the same entity from at least September 2023 until February 2026.
As detailed in
Section 8
, the mercenary ADINT vendor Intelos, which reportedly offers both ad-based geolocation surveillance and the delivery of spyware via ads, has additional links to Discover-Tech via Intelos shareholder Eric Banoun (2018 – present), who was also a director of Discover-Tech (2020 – 2025).
As
Table 8
shows, the Discover-Tech website shares the Wix user account with additional sites linked to Akedo (see the next subsections) and Tekma (see
Section 8
).
Table 8
Wix “userid” overlaps across Discover-Tech, Intelos, Tekma, and Akedo.
Adtimizer
We observed Discover-Tech using the domain
dtech.adtimizer[.]co
as impression and click URLs in ads. Israeli company records link the domain
adtimizer[.]co
to the Israeli firm Adtimizer Ltd, directed and owned by Oren Baranes. Baranes also appears in the HTML source code of the Controlium platform on the sites
www.controlium[.]net
and
powerium[.]net
:
Furthermore, three users, “Oren Baranes”, “Oren baranes” (lowercase B), and “Oren Baranes Admin” regularly logged into Controlium in July 2026, according to authentication logs reviewed by us (see
Section 3
).
In 2022, Baranes posted on a public web forum
4
using a Discover-Tech email address, in a forum thread that was discussing the advertising firm Beeswax:
Baranes’
LinkedIn profile
does not mention Discover-Tech but presents him as an expert in mobile advertising.
5
His appearance in the Controlium source code and his email address, which are both clearly linked to Discover-Tech, suggest that Oren Baranes is working for the company in some capacity. We consider the domain
adtimizer[.]co
and the Israeli company Adtimizer Ltd as linked to Discover-Tech. However, we do not have conclusive evidence that Adtimizer Ltd knowingly participated in the delivery of mercenary spyware attacks.
In its
response
to the Citizen Lab, Adtimizer Ltd claims that the subdomains we consider to be linked to Discover-Tech, including
dtech.adtimizer[.]co
,
myinfoback.adtimizer[.]co
,
noas.adtimizer[.]co
and
tekma.adtimizer[.]co
, were “used solely within Discover Tech’s infrastructure, which was entirely separate from ours and was not operated, managed, or controlled by Adtimizer”, and that Adtimizer “had no knowledge of, or involvement in the alleged activities” with respect to Discover-Tech’s malicious ad targeting.
MyIPInfo, Akedo, and Volasim
As discussed in
Section 4
, the sites
adv45.volasim[.]com
and
adv50.volasim[.]com
provided versions of Discover-Tech’s Controlium platform. The site
myipinfo[.]io
hosts a decryption tool linked to Controlium including keys used in conjunction with the Candiru attacks. The bidding logs reviewed in
Section 5
show that the vast majority of ads served via Discover-Tech promote the MyIPInfo site, the mobile gaming platform Akedo, and an app provided by Volasim.
The following subsections show that MyIPInfo, Akedo, and Volasim are linked to Discover-Tech and to each other in additional ways. The subsection ‘Response from Volasim Ltd’ below addresses in more detail Volasim’s response to The Citizen Lab where the company emphasizes that it has “no involvement whatsoever” in “spyware-related activities.”
Akedo
Akedo’s management team includes two Discover-Tech key executives and shareholders, Dekel Boni and Yaniv Basil, according to a promotional
pdf
published on the company’s website,
akedo[.]gg
. A person named Kfir Goldman is listed as the general manager of the Akedo platform. The document was created by a person, who is the “Chief Marketing Officer” at both Akedo (since 2022) and Discover-Tech (since 2019),
according
to their LinkedIn. Another person
refers
to themselves as the “Operations Manager” at both Akedo (since 2022) and Discover-Tech (since 2023). The fact that two persons work at both Akedo and Discover-Tech at the same time and in the same role, combined with the overlaps in the management team, indicates a relationship between the two companies.
The Akedo site does not refer to any legal entity. Israeli company records reviewed by us indicate that Eric Banoun, Dekel Boni, Yaniv Basil, and Kfir Goldman were shareholders in a firm named KYD Ltd, which in turn was a shareholder in a company named “Akedo Good Game Ltd”, which was directed by Boni. The two companies were dissolved in 2024 and 2025. As both the website and the Israeli company records refer to the same group of persons, we believe that the two legal entities were linked to Akedo’s activities until their dissolution.
Kfir Goldman, who is listed as part of Akedo’s management team and who was an indirect shareholder in Akedo Good Game Ltd, is included in a list of user accounts we found in the source code of Discover-Tech’s “Mini Platform C” app, as examined in
Section 3
. The listed accounts also include Dekel Boni, Yaniv Basil, and Guy Lants. This suggests that Kfir Goldman is or was also working for Discover-Tech in some capacity.
Volasim
The website
volasim[.]com
describes
Volasim as a “digital marketing agency”,
incorporated
in Cyprus as Volasim Ltd, which serves advertisers using “ad platforms and real-time bidding platforms”. The address mentioned on the website and the registration address of Volasim Ltd, according to company records from Cyprus, are identical. The company is directed and owned by a person who is listed as a director of many companies registered in Cyprus, likely on behalf of other parties. We were not able to access information about Volasim’s ultimate beneficial owners.
Volasim Ltd is listed as a mobile app developer by both
Google
and
Apple
. It provides the game
City Masters
, the reminder app
RemindMeWhere
and two apps named
MyIPInfo
and
Akedo
. All four app listing pages refer to Volasim Ltd as the developer of the app, using the same address as mentioned in the corporate record and on the Volasim website. The app listing page for MyIPInfo refers to the website
myipinfo[.]io
, the page for the Akedo app refers to the site
akedo[.]gg
. The page for Volasim’s game
lists
the support email address
kfir@volasim[.]com
. We are not aware of any information confirming that this email address is associated with Kfir Goldman.
In addition to Discover-Tech’s Controlium platform being available on the sites
adv45.volasim[.]com
and
adv50.volasim[.]com
, the Controlium source code contains example data for the creation of a banner ad campaign for Volasim’s
RemindMeWhere
app, with the ad linking to the app’s
website
,
remindmewhere[.]app
. A Controlium-related “Banner Tester” app, as examined in
Section 3
, contains the description “Volasim test banner” in the source code. We also
found
a YouTube channel named “DT_VLSM” that uses Discover-Tech’s logo and lists a video that advertises Volasim’s reminder app.
MyIPInfo
The site
myipinfo[.]io
hosts Controlium-related code and is often being advertised by Discover-Tech. In addition, we found the same Google Tag Manager ID, which
identifies
a specific Google customer and their third-party tracking configuration across the sites
myipinfo[.]io
and
events-ui.discover-tech[.]io
, based on source code analysis. Passive DNS data indicates that the domain qabackend.myipinfo.io was linked to
ipinfo.myweb3id.io
. Several subdomains of
myweb3id[.]io
provide Controlium-related code and NOAS services, as discussed in other sections of this report.
The website
myipinfo[.]io
predominantly displays ads for Akedo, according to browser testing and the observation that the site loads a file named “ads.json” that contains Akedo ad data (
urlscan
). Based on source code analysis and data from the analysis tool DNSlytics, we found the same Google AdSense ID, which
identifies
a specific publisher selling ads via Google, across the sites
events-ui.discover-tech[.]io
,
myipinfo[.]io
, and
akedo[.]gg
. Another AdSense ID has been observed across the sites
myipinfo[.]io
,
akedo[.]gg
, and
citymaster[.]io
,
which is
the website for Volasim’s game app “City Masters”.
The website
myipinfo[.]io
does not contain any information about its publisher. Domain registration data is anonymized. However, as discussed above, the MyIPInfo mobile app is provided by the Cypriot firm Volasim Ltd, according to Google and Apple app store information.
Response from Volasim Ltd.
In its
response
to the Citizen Lab, Volasim Ltd refers to “Akedo” and “MyIPInfo” as “legitimate digital products developed by Volasim”. The company states that Discover-Tech was among the “external advertising providers” it engaged to “promote its products”. Volasim emphasizes in its response that it “has no involvement whatsoever in the spyware-related activities” discussed in our investigation, and that it has “never commissioned, authorized, participated in, or knowingly facilitated any such activity”.
As summarized in this subsection (‘MyIPInfo, Akedo, and Volasim’), we found that Volasim and its products Akedo and MyIPInfo are linked to Discover-Tech in several ways. However, at this time, we do not have conclusive evidence that Volasim Ltd knowingly participated in the delivery of mercenary spyware attacks.
8. Intelos, Bindecy, and Candiru’s Corporate Networks
This section provides an overview of Intelos, Bindecy, and Candiru, and provides details on what we know about their corporate networks and business identities. Furthermore, we present additional links between Discover-Tech and Intelos.
Intelos and Its ADINT System AdHoc
In 2023, the trade press website Intelligence Online and Haaretz
first
reported
about Intelos, a new Israeli ADINT vendor that provides a surveillance system based on data from digital advertising named “AdHoc”. Intelos was reportedly founded by Eric Banoun, who is “one of the pioneers of offensive cyber in Israel”
according
to Haaretz. Israeli company records reviewed by us confirm that Banoun has been a shareholder in Intelos Ltd from its registration in 2018 until present, and he is listed as the company’s director. The email address he uses in corporate filings,
[email protected]
, clearly links Intelos Ltd to the website intelos.io.
The fact that Banoun was also listed as a director of Discover-Tech Ltd (see
Section 7
), already suggests a potential connection between the ADINT vendor Intelos and Discover-Tech. In addition, the websites
intelos[.]io
and
discover-tech[.]io
were published by the same entity until at least February 2026, according to technical analysis discussed in
Section 7
. While we cannot assess the exact scope of the collaboration between Intelos and Discover-Tech, the technical analysis discussed in
Section 4
indicates that the two work together.
Besides a few media articles and the company’s website, there is almost no public information available about Intelos. The company’s AdHoc product is not mentioned on its website. According to Israeli company records reviewed by us, Intelos Ltd’s shareholders include Eric Banoun, Senpai co-founder Roy Shloman, Thai businessman Charoenrath Vilailuck, and a Liechtenstein-based firm named SAR Investments International Ltd, among others.
On its
website
, Intelos purports to be a “marketing intelligence” platform that monitors “worldwide digital signals, actions, and preferences”, including “subtle changes in behaviour”, by processing 16 billion “daily data sets” across 50 countries. Much of the promotional language on the site sounds like the company’s products are built for customers in digital marketing, but could also describe an ADINT vendor. Intelos promises to “map behavioural patterns across audiences” and to build “profiles of audiences and groups” in order to “map relationships, track behavioural shifts, and anticipate collective action”. It also provides “location intelligence” based on a “proprietary index of the physical world” with “every relevant location classified, mapped, and weighted for significance”. Another system named “Nexus AI”
could
transform “raw data into structured insights” based on “live and historical datasets” in order to “map behavioural clusters” and “detect relationships”.
Haaretz
and
Intelligence Online
reported
that Intelos
provides
ad-based geolocation surveillance but
also
the delivery of spyware via ads, without providing details about the latter. Its technology was reportedly
offered
to the Shin Bet in Israel and
sold
in Thailand. According to Haaretz, Eric Banoun
presented
an ADINT product named “Havoc” that included the AdHoc logo to an Egyptian customer. An agreement related to his presentation mentioned a U.K. firm, whose director is also the director of another U.K. firm named “Havoc”, which sold an unnamed cyber system to an unnamed country over a period of three years at a cost of about $42 million. Based on the media report, it remains unclear whether AdHoc was sold in Egypt or not.
Intelos did not respond to our request for comment within the timeline provided.
Tekma
The
2025 version
of the site
intelos[.]io
shares many promotional phrases with the
2024 version
of the website
tekma-dmp[.]ai
. Both sites offered a “Data Marketing (DM) platform” and the “AI Edge” product using a number of identical sentences. According to the
current website
, Tekma purports to have access to data on 3.5 billion devices, which can be utilized “across major DSPs”, and is based in Dubai, with
regional offices
in Greece, Cyprus, and Spain. The
2024 site
includes Tekma contact information referring to “Chaia Services” and mentions another regional office in Hong Kong. Another older but also almost identical site,
tekma[.]io
, includes Tekma contact information referring to “Chaia Ltd” in “13&15 GR. Afxentiou Street, Mesa Geitonia Limassol, Limassol 4003 CY”.
Technical analysis discussed in
Section 7
shows that the websites
intelos[.]io
,
tekma-dmp[.]ai
,
discover-tech[.]io
, and
www.partners.akedo[.]gg
were published by a single entity between 2024 and 2026. The site
tekma[.]io
was also published by the same entity.
As discussed in
Section 7
, Discover-Tech Ltd’s shareholders include a company named Chaia Services Ltd. Notably, the Israeli firm Adtimizer Ltd (see
Section 7
) has the subdomain
tekma.adtimizer[.]co
. Between 2020 and 2025, this subdomain was linked to the following host name via CNAME, according to DNS telemetry:
Bindecy is “one [of] Israel’s lesser known spyware firms”, though it “develops and sells digital surveillance tools to states” with a focus on “Western clients and their close allies in the east”,
according
to Haaretz. On its website, bindecy.com, it presents itself as a cybersecurity firm founded by Israeli military intelligence alumni that analyzes apps and “critical systems”. The trade press website Intelligence Online reported that Bindecy,
founded
by Daniel Shapiro and Eylon Ben Yaakov,
has
“cyber offensive contracts from the Israeli intelligence services” and
sold
its “zero-click spyware” to Italy’s military police, the Carabinieri.
In 2021, Bindecy
acquired
part of the intellectual property of Merlinx, another Israeli cyber offensive company formerly known as Equus Technologies. In 2024, Haaretz
reported
that the founders of Bindecy recently joined the Spanish company Epsilon, which develops exploits and is “aiming for the American market”, as partners. According to its website,
epsilon-sec.com
, the company offers security research on mobile platforms and is located in Spain, France, and Canada.
Company records reviewed by us indicate that the Israeli company Bindecy Ltd was founded in 2017. Since 2025, it has a solely owned subsidiary named Shor Labs s.r.o. registered in the Czech Republic. Bindecy co-founder Daniel Shapiro is listed as a director of both Shor Labs s.r.o and Spanish Epsilon Cyber SL.
Bindecy did not respond to our request for comment within the timeline provided.
Candiru is an Israeli-founded mercenary spyware company that draws its original name from the parasitic Candiru fish, and has operated under a wide range of names throughout the years, including Saito Tech. Today, Candiru operates under the rebranded identity of Integrity Labs after acquisition by U.S.-based Integrity Partners.
Candiru: Prior Investigations, Abuses, and Discoveries
Candiru is a mercenary spyware threat actor known by multiple names, including SOURGUM and Carmel Tsunami by Microsoft.
First Candiru Abuse Discoveries: 2021
On July 15, 2021, the Citizen Lab
published
the first report exposing Candiru. That investigation included identifying a Candiru victim and recovering a copy of Candiru’s Windows spyware. We then worked with Microsoft’s Threat Intelligence Center (MSTIC) to analyze the spyware, which led to the identification of two zero-day vulnerabilities (
CVE-2021-31979
and
CVE-2021-33771
). We also identified over 750 websites linked to Candiru’s infection infrastructure that masqueraded as a wide range of civil society entities ranging from media organizations to Amnesty International.
On July 14, 2021, Google TAG
published a report
which included discussion of two Chrome exploits (
CVE-2021-21166
and
CVE-2021-30551
) that pointed to addresses matching our Candiru fingerprint. The report also linked a Microsoft Office exploit (
CVE-2021-33742
) to the same operator.
Microsoft’s own investigation into Candiru, published simultaneously with our report on July 15, 2021, identified at least
100 spyware victims
across ten countries. Microsoft reported that
the victims
included journalists, opposition politicians, dissidents, and activists.
On November 16, 2021, ESET reported on a series of watering hole attacks observed in 2020 and 2021 targeting websites in the Middle East with what they described as a “strong focus on Yemen.” They
attributed the attacks to Candiru
.
Further Investigations and Abuses: 2022-2025
In 2022, the Citizen Lab again found Candiru spyware targeting victims
among Catalan civil society groups in Spain
. In that investigation, we identified signs of a live Candiru infection on a Catalan university network, and successfully worked with system administrators to identify the victim, isolate the device, and extract the active spyware. The targeting we observed as part of this campaign included emails masquerading as official Spanish governmental messages about COVID.
On July 21, 2022, Avast
published a report
revealing that Candiru was using a Chrome zero-day exploiting WebRTC (
CVE-2022-2294
), and found evidence of targeting of users in multiple countries in the Middle East.
On December 22, 2022,
Meta disclosed
that it disrupted around 130 Facebook and Instagram accounts used by Candiru to send infection links amongst themselves to “test phishing capabilities.”
In the summer of 2024, during the parliamentary election campaign, Member of the European Parliament (MEP) Daniel Freund was
targeted with Candiru’s mercenary spyware
, according to the European Parliament’s security services.
On August 5, 2025, Recorded Future’s Insikt Group
investigated Candiru infrastructure
and identified multiple Candiru clusters linked to Hungary, Saudi Arabia, Indonesia, and Azerbaijan, among others.
On September 2, 2025, Sekoia
published an investigation
into Candiru’s spyware, highlighting how Candiru and similar companies leverage complex jurisdictional structures to avoid discovery.
Entity Listing
On November 3, 2021, Candiru
was added
to the United States Commerce Department’s Entity List for malicious cyber activities. The entity listing noted that Candiru was added because “they developed and supplied spyware to foreign governments that used this tool to maliciously target government officials, journalists, businesspeople, activists, academics, and embassy workers.”
Legal Actions Against Candiru and Users
In October 2024, Daniel Freund
filed a criminal complaint
with the assistance of German digital rights NGO
GFF
against Viktor Orbán and unnamed persons over his targeting with Candiru.
On April 30, 2025, the NGO Sentinel Alliance
filed a case
against
multiple Spanish governmental entities, NSO Group, and Candiru over the mercenary spyware attacks targeting Catalan civil society.
Candiru’s 2025 Acquisition by Integrity Partners
In April 2025,
Israeli media reported
that U.S.-based Integrity Partners acquired the operations of Candiru for $30 million in a bid to bypass the U.S. Entity Listing. Research by Recorded Future’s
Insikt Group
identified Candiru as having been rebranded to “Integrity Labs” (אינטגריטי לאבס בע~מ) in December 2024. The current status of the acquisition is unclear.
Candiru/Integrity Labs did not respond to our request for comment within the timeline provided.
9. Discover-Tech’s Relationship to the Digital Advertising Industry
This section explores how major industry organizations and ad vendors helped enable Discover-Tech’s ad operations, and notes that Discover-Tech achieved “certified” and “approved” status by Google and the major advertising industry association IAB Europe.
Our analysis indicates that Discover-Tech deployed ads via Google, Yandex, and other ad vendors including Beeswax (FreeWheel/Comcast), Vungle (Liftoff), Eskimi, and Sunteng. In addition, both Google and the advertising association IAB Europe have listed Discover-Tech as a “certified” and “approved” ad vendor since the year 2020, which helped make the company appear to be a legitimate advertising firm and facilitate its participation in the advertising ecosystem at scale.
As a result of this investigation, both Google and IAB Europe removed Discover-Tech from their ad vendor registries in early October 2026. Google, which collaborated in the investigation, terminated Discover-Tech’s access to its ad exchange platforms. Beeswax removed Discover-Tech from its ad buying platform. Vungle (Liftoff) paused Discover-Tech’s access while conducting a review. Eskimi blocked Discover-Tech’s accounts and domains.
The ad vendors identified in this section are distinct from mercenary spyware or ADINT vendors insofar as they are not necessarily aware of potential misuses of their infrastructure for non-advertising purposes.
Discover-Tech: Got “Certified” and “Approved” by Google and IAB Europe
Table
9
provides an overview of ad vendor lists maintained by Google and IAB Europe, the European branch of the major advertising industry association IAB, which included Discover-Tech from the year 2020 until early October 2026:
Ad Vendor List
Discover-Tech Entry/Vendor Metadata
Listing
IAB Europe
Transparency & Consent Framework (TCF), Global Vendor List (GVL), available in JSON format (
vendor-list.json
)
– “The providers.csv dictionary file has changed”
– Deleted line 3036,”MarketDSP”,”https://advertising.market.com/dsp-privacy-policy/”,”mtrtb.com mydsp.io tracker.mtrtb.com”
– Added line 3036,”Discover-Tech LTD”,”http://discover-tech.io/dsp-privacy-policy/”,”mtrtb.com mydsp.io tracker.mtrtb.com”
2020-07-31
Table 9
Discover-Tech in ad vendor lists maintained by Google and IAB Europe.
Google listed Discover-Tech Ltd among its roughly 2,400
Certified External Vendors
. These vendors, which Google also refers to as “allowed vendors” and “certified companies”, “undergo a business review,” the nature of which is not specified, so they “can serve third-party ads on the Google Ad Manager platform”. Google
claims
to “conduct a thorough certification process” for “vendors that are certified for third-party ads” and ensure they “meet Google’s requirements for third-party ad serving”. A listed vendor is “permitted to make third-party calls”, which may
include
tracking pixels. Google
emphasizes
that it might pause the delivery of ads when it detects “non certified vendors”. Being listed is crucial for a company that wants to interface with Google.
Google also listed Discover-Tech among its roughly 1,000
Ad Technology Providers
, who can receive data on website visitors and app users in Europe. In Google’s own words, these vendors “agreed to comply” with its “data usage policy” and “have shared certain information that is required by European regulations policy”. Website and app publishers “need to list these partners for [their] users.” Until 2025, Google
referred
to these vendors as “certified ad technology providers,” but a later redesign of the page dropped the term “certified.” In addition, Google listed Discover-Tech in its global list of roughly 1,700
ads personalization providers
, which may participate in ad auctions based on “user consent”. The list contains “domains which can be attributed to the provider.” For Discover-Tech Ltd, the domains
mtrtb[.]com
and
mydsp[.]io
are listed.
Discover-Tech Ltd was added to all these lists in 2020. Google, which collaborated in this investigation, removed Discover-Tech from its ad vendor registries and terminated the company’s access to its ad exchange platforms as of the first week of October, 2026.
Discover-Tech Ltd was also listed in the Global Vendor List (GVL) maintained by the European branch of the Interactive Advertising Bureau (IAB), a key digital advertising industry association. The
GVL
contains roughly 1,000 vendors that are “registered and approved” by IAB Europe. These vendors can participate in IAB Europe’s “Transparency & Consent Framework” (TCF), which promises to enable ad vendors to comply with European data protection and privacy law when processing personal data for digital advertising purposes. While the TCF’s ability to enable lawful data processing
is
controversially
debated
, a GVL registration has become a
de-facto requirement
for an ad vendor to participate in digital advertising, display ads and receive data in Europe. IAB Europe added Discover-Tech Ltd to the GVL on July 2, 2020. As a result of this investigation, Discover-Tech was removed from the GVL on October 8, 2026.
According to IAB Europe, it
takes
“reasonable steps to vet and approve” vendor applications,
including
the “identity of the party or parties controlling the vendor” and the vendor’s ability to “adhere” to a number of TCF policies, and then
monitors
their compliance with those policies. The TCF
is the basis
for passing user “consent” signals for personal data processing across the digital advertising supply chain, from users to publishers to intermediaries (like SSPs, DSPs, and ad exchanges) to advertisers,
including
in bid requests and tracking pixels. Most ad tags and tracking pixels that connect to third-party vendors
require
“consent” signals, including in some jurisdictions outside Europe and the U.K. like California. Google, Xandr, and most larger ad platforms
require
TCF compliance. While
several
studies
found
that
vendors are too often ignoring “consent” signals, an ad vendor that is not listed in the GVL, and thus cannot pass any signal, can hardly interface with other ad vendors in reliable ways.
While the vendor lists maintained by
Google
and the
IAB Europe
help a company appear to be a legitimate ad vendor and are the basis to participate in the digital advertising ecosystem in a reliable way at scale, they appear to be largely based on self-attestation by vendors. They are also the basis
for most
of the “consent” popups shown to European web and app users every day. Discover-Tech Ltd’s inclusion in those lists potentially means that, for almost six years, hundreds of millions of Europeans were presented with a consent request that, if the recipient clicked “Agree,” could be construed as authorizing Discover-Tech to process their data under the GDPR.
As of October 2026, Discover-Tech is additionally
listed
in a registry operated by the “Trustworthy Accountability Group” (TAG) created by major U.S. advertising associations and the IAB, which
aims to
increase trust in the digital advertising industry, eliminate fraud and fight criminal activity
including
“malware threats targeting the digital advertising supply chain”. The
Verified by TAG
badge held by Discover-Tech, which the company also displays on its website, is used across the industry to “determine trust and transparency” and let prospective partners know that a company has taken “actionable steps to verify their identities and adopt rigorous standards to fight online fraud, piracy, malware, and lack of transparency”,
according to
the TAG website.
Advertising Firms Involved in Discover-Tech’s Targeting
Our analysis of ad bidding data in
Section 5
indicates that Discover-Tech targeted users by participating in ad auctions handled by Google, Yandex, and other ad vendors including Vungle and Sunteng. The analysis of the Controlium platform in
Sections 3
and
6
indicates that Discover-Tech also uses the ad buying platforms Beeswax DSP and Eskimi DSP to target users. In addition, those sections show that Discover-Tech receives and utilizes user identifiers maintained by Microsoft’s advertising platform Xandr.
Table
10
provides a summary of ad vendors involved in Discover-Tech’s ad operations, according to the research presented in this report. The table briefly summarizes our findings with respect to their involvement. The descriptions of vendors and their offerings are based on additional research that is included in the Appendix of this report.
Ad vendor
Product offerings
Findings
Google (U.S.)
Dominates the digital advertising ecosystem in the U.S., Europe, and other regions, and operates a massive ad exchange and systems for ad sellers and buyers.
Discover-Tech Ltd. delivered ads via Google, according to ad bidding records, URL telemetry data and source code of a campaign management system reviewed by us.
Yandex (Russia)
Dominates the digital advertising ecosystem in Russia and some other regions, and operates an ad exchange and systems for ad sellers and buyers.
Discover-Tech Ltd. delivered ads via Yandex, according to ad bidding records, URL telemetry data and source code of a campaign management system reviewed by us.
Beeswax, owned by Comcast’s ad platform FreeWheel (U.S.)
Highly customizable DSP that allows clients to access granular bidding data and implement custom bidding algorithms (“bidder-as-a-service”), according to the company.
Discover-Tech used FreeWheel’s Beeswax DSP to deliver ads and it appeared to use the Beeswax user identifier for targeting, according to URL telemetry data and source code from several systems operated by Discover-Tech reviewed by us. It also retrieved Beeswax user identifiers and engaged in ID syncing with Beeswax, according to browser testing, source code analysis, and records archived on the web investigation platform urlscan.
Eskimi (Lithuania)
DSP and white-label DSP, which allow clients to target 1.5 billion “profiled users” across 60 ad exchanges, according to the company.
Our analysis of Discover-Tech’s Controlium platform indicates that the company used Eskimi as one of three DSPs for ad delivery. URL telemetry data reviewed by us confirms ad delivery via Eskimi DSP, albeit the volume is low compared to ads delivered via MyDSP and Beeswax.
Vungle, owned by Liftoff (U.S.)
Mobile SSP and ad exchange, both relying on the “Vungle SDK”, which is embedded in 150,000 apps and used by one billion people, according to the company.
Discover-Tech delivered ads via Vungle, according to ad bidding data reviewed by us.
Sunteng, also known as Shunfei Technology (China)
DSP, SSP, and ad exchange, which processes 50 billion ad bid requests a day across 10,000 mobile apps and 60 ad vendor partners, according to the company. Corporate websites reviewed by us suggest that Sunteng is associated with BiddingX and Bidex.
Discover-Tech delivered ads via Sunteng, according to ad bidding data reviewed by us.
Xandr, aka Microsoft Advertising (U.S.)
Xandr, in 2023 rebranded Microsoft Advertising, offers a SSP and identity graph/syncing services. Its “Invest” DSP was shut down in early 2026.
Discover-Tech retrieved user identifiers from Xandr and engaged in ID syncing with the vendor, according to browser testing and our analysis of source code and records archived on the web investigation platform urlscan. Discover-Tech’s Controlium platform provides an extra option to “detect” the Xandr user identifier.
Table 10
Ad vendors involved in Discover-Tech’s ad operations.
Google, which collaborated in the investigation, terminated Discover-Tech’s access to its ad exchange platforms in early October 2026. As detailed in their responses to the Citizen Lab, Beeswax removed Discover-Tech from its ad buying platform, Vungle (Liftoff) paused Discover-Tech’s access while conducting a review, and Eskimi blocked Discover-Tech’s accounts and domains. Sunteng and Xandr (Microsoft Advertising) did not respond to our requests for comment within the timeline provided.
10. Discussion: AdFection Shows that Online Ads Are a Cybersecurity and Privacy Crisis
This report provides the first-ever technical evidence of zero-click mercenary spyware attacks delivered via targeted advertising. We also confirm that AdFection was used to infect devices at international media organization Al Jazeera.
These attacks were facilitated by Discover-Tech, which presents itself as a legitimate advertising business but actually serves as a bridge between mercenary spyware companies and the advertising ecosystem. Discover-Tech not only helps companies like Candiru use ads to mass-profile unwitting phone users, their ads directly enable these companies to silently infect selected targets’ devices.
The combination of advertising intelligence and the delivery of spyware is extremely concerning, for several reasons. First, both the digital advertising and mercenary spyware industry are very poorly regulated, with the latter featuring numerous firms notorious for deception, a lack of transparency, and even unlawful activities. To see entities from those two industries forming an alliance should be a wakeup call to regulators and policymakers around the world. Dozens of reports by numerous organizations, including the Citizen Lab, have shown incontrovertible proof of the harms caused by mercenary spyware vendors on civil society around the globe. With the addition of the type of advertising intelligence capabilities we have documented, those firms’ capabilities will now be supercharged.
Second, the combination of advertising intelligence and spyware infections provide government security agencies with highly invasive systems that span both mass
and
highly targeted types of user surveillance. As we show in this report, millions of devices were likely unwittingly profiled as a form of preliminary reconnaissance to enable targeting with spyware tailored to those device’s specific characteristics. Ominously, many of these infections took place without any visible indication of tampering or other clues that might have alerted them to the compromise. Also ominous is the fact that the services of Discover-Tech appear to span multiple regions around the globe. It is not known at this time exactly which governments are capitalizing on these new capabilities, but if past evidence is any indication it seems highly likely that some proportion of them are abusing those capabilities to target individuals outside of strictly criminal or national security purposes.
ADINT: Journalism in the Crosshairs
The hacking of Al Jazeera with AdFection is part of a longstanding pattern:
mercenary spyware attacks against the media
. Journalists and newsrooms are a
constant target for spyware attacks
, and this latest case highlights how well-resourced operators consistently seek new ways to access their private, protected communications.
The use of spyware to target the media directly interferes with the ability of the free press to hold power to account. It also threatens the privacy of journalists’ sources, and can chill reporting. Foreknowledge of movements, reporting topics, meetings, and sources does not just help powerful interests try to frustrate coverage and reporting, it can put people at physical risk. This is especially true for a news organization with reporters, freelancers, stringers, fixers and sources working in conflict zones around the world.
Investigations into mercenary spyware operations have repeatedly surfaced targeting against the media, including in the context of governmental and cartel killings of reporters. Journalists have been confirmed
spyware targets
, from the Citizen Lab’s earliest findings of Pegasus spyware in Mexico
almost a decade ago
, to cases across Africa from
Angola
to
Morocco
and
Togo
, to
Jordan
,
Serbia
,
El Salvador, and
Italy
, among many others. Organizations like Reporters Without Borders provide helpful overviews of the
scale of the threat
which, as Access Now points out, is sometimes coupled with laws designed to
authorize government access
to journalists’ communications. The International Federation of Journalists, meanwhile, has a recent overview of how spyware is situated within a
broader set of digital threats
against journalists.
Recently, reporting from the Committee to Protect Journalists outlined the
dangers posed to journalists
from ADINT
-style tracking. The combination of this tracking with zero-click mercenary spyware targeting presents an even more serious danger to journalists’ safety.
This investigation should also serve as a clear warning signal to news organizations around the world that they may be being actively targeted via this new threat. This targeting may happen both in newsrooms and to individual journalists, editors, and other staff members. We urge news organizations to immediately seek expert assistance and ensure that their systems are protected against these attacks to the fullest extent possible. We provide some guidance in
Section 11
, however we urge all news organizations to systematically review their security posture (and logs) for signs of AdFection style spyware targeting and infection.
The Advertising Industry: A Dangerous Lack of Due Diligence
Our findings also reveal a troubling lack of due diligence within the digital advertising industry that helped enable this inappropriate activity. Discover-Tech, which presented itself as a legitimate ad vendor but served as a bridge between the online advertising ecosystem and the spyware industry, has been deeply embedded and interconnected with the online advertising ecosystem for years. Multiple ad vendors let the company utilize their systems. The two key industry organizations, Google and IAB Europe, have helped Discover-Tech appear as a legitimate ad vendor from the year 2020 until 2026, despite information about the company’s links to figures in the spyware industry being readily accessible in corporate records. Our findings show that the digital advertising industry is ill-prepared to prevent malicious actors from exploiting its infrastructure for the distribution of spyware via targeted ads.
This case should serve as an alarm to the advertising industry that business as usual is no longer acceptable. The online advertising industry must get serious about tackling the distribution of mercenary spyware via targeted ads, alongside other malicious advertising practices including financially motivated
fraud
and
cybercrime
. Technical and organizational measures currently implemented by the industry, such as the
SafeFrame
specification or standards for
supply
chain
transparency are insufficient or
not even adopted
in a meaningful way.
Fix a Broken Digital Infrastructure
More broadly, the distribution of spyware via targeted ads depends on the way digital advertising – and the web economy at large – currently operate.
Many mobile apps and websites
contain
tracking
software
operated by dozens of third parties, which themselves may include code by additional third parties within apps and browsers. Also required for the targeted deployment of spyware, ad targeting at the individual level
depends on
uncontrolled data sharing via RTB auctions and third-party tracking.
Automated ad selling and buying via RTB, which
connects
large numbers of publishers, advertisers and intermediaries across opaque supply chains, is
designed to
minimize human intervention. When combined with a lack of oversight and accountability, it is generally prone to abuse. This is further aggravated by the assumption that at least some ad vendors benefit from malicious and fraudulent advertising. Leaked internal documents from Meta
reported by
Reuters
suggest that Meta estimated that it earns between five and ten percent of its annual revenue from running fraudulent ads. Industry sources
suggest
that
ad fraud accounts for one fifth of all online advertising spend.
AdFection: A Threat to States, Civil Society, and Everyone Else
The distribution of spyware via targeted ads represents a security risk not only for potential victims but also for states and civil society at large. Two major U.S. security agencies, the National Security Agency (NSA) and the Cybersecurity and Infrastructure Security Agency (CISA), have warned already in
2018
and
2020
that adversaries may leverage malicious ads to deploy malware on devices, and thus both recommended that government agencies and other organizations use ad-blocking software.
Given the current threat posed by Discover-Tech’s AdFection vectors, and the evidence of wide-scale targeting, we judge that the most feasible protection is for defenders to block targeted ads at the gateway. This defensive recommendation (see
Section 11
) holds until the industry has shown that it is reliably able to block all AdFection style vectors.
At the very time that state actors may be employing offensive cyber attacks, malicious ads can be deployed via apps and websites used by defense personnel, political leaders, and people maintaining critical infrastructure alike, creating national security risks for those very same states. The same structural deficits that endanger civil society, journalists, and opposition figures are potentially exploited by both foreign adversaries and cybercriminals, creating systemic risks for everyone.
These security risks make it apparent that there is an urgent public-interest need to reform digital advertising.
The same risks apply to the private sector and to civil society. Indeed, as prior research has made clear, a large number of governments will use these potent capabilities to undermine political opposition, stealthily target journalists and lawyers, and target refugees, immigrants, and other vulnerable populations. The mercenary spyware industry is already notorious for widespread harms; fueling that industry with digital advertising capabilities will multiply those harms immeasurably.
11. Recommendations: How to Stop AdFection Attacks
The AdFection attacks and espionage described in this report impact millions of people in dozens of countries. Existing laws and self-regulation by the industry failed to catch or prevent them. In this section, we provide guidance to regulators, defenders, and the advertising industry on how to stop AdFection and ADINT-style espionage.
Advertising Vendors: Time to Get Serious
The advertising industry uses terms like “certified” and “approved” to try and convey a veneer of effective self regulation. However, the industry appears to perform no meaningful due diligence on participating vendors, instead improperly relying on self-attestation where vendors check a box on an online form. This process allows widespread privacy abuses, including failing to prevent mass espionage via targeted ads.
Ad vendors must significantly level up their cybersecurity and threat detection capacity to effectively cut off malicious advertisers across the supply chain. They must rigorously and regularly vet, screen, and audit their business partners and hold them accountable for their own supply chains. This type of more robust due diligence applies in particular to key industry organizations and dominant players who must introduce rigorous and regular audits for companies listed in ad vendor registries which they maintain and provide to many other actors in the supply chain. Business partners from countries with opaque corporate registries or where known malicious actors operate deserve specific attention.
Technical and organizational measures to be taken must include both vendor-specific and industry-wide efforts. Cybersecurity agencies and other regulators in the U.S., Canada, Europe, and other regions must support these efforts by investigating risks, calling out shortcomings and taking action to ensure the implementation of effective measures by the advertising industry.
Detect and block malicious ads:
Ad vendors must radically increase their capacity to identify AdFection-style attacks in real-time, alongside other forms of malicious advertising such as ad fraud, across their supply chain.
Share threat data:
Develop better threat sharing and clearinghouses for sharing information about malicious actors and recklessly permissive jurisdictions.
Vet and screen partners
: Implement mandatory know-your-customer, including due diligence and recurring vetting for all partners and other firms who transact over the provided ad and data services.
Audit vendor registries:
Major advertising organizations must introduce mandatory third-party audits for “certified” or “approved” vendors.
Ban vendors in problem jurisdictions
: Adopt a default-deny policy for vendors operating in jurisdictions known to be highly permissive of abuse, or without accountability mechanisms.
Fix systemic vulnerabilities:
Implement industry-wide measures to improve ad delivery security and to introduce full supply chain transparency, and support their adoption.
Zero-Click AdFection
We urge regulators to take immediate action to ensure that advertising platforms and partners stop facilitating AdFection-style attacks, and secure their populations from the security, cybersecurity, and privacy threats posed by the advertising ecosystem.
Investigation and Enforcement
Immediately investigate Discover-Tech and Candiru:
Our research showed large-scale data collection from millions of devices involving Discover-Tech and Candiru. The data was apparently collected for the purposes of AdFection. We urge competent authorities in all jurisdictions to investigate whether the rights of their citizens, as well as applicable privacy and security laws were violated.
Enforce existing laws:
It is unlikely that Discover-Tech is the only enabler of AdFection-style zero-click attacks. Authorities should more closely scrutinize the advertising ecosystem to determine whether other companies are leveraging it for espionage and spyware delivery, and determine whether they have violated applicable laws and regulations.
Enforcement and sanctions
: Use all necessary domestic enforcement and sanctions authorities to discourage AdFection abuse. These measures can include the use of sanctions and entity-listing powers against firms that deploy mercenary spyware and conduct espionage via targeted ads, the companies that enable them, and the individuals who work in the AdFection domain.
Legal and Regulatory Improvements
Commission investigations:
Enlist the assistance of cybersecurity agencies and regulatory bodies to evaluate the security, privacy, and national security risks from the current advertising ecosystem.
Tighten privacy regulations around ad tracking and targeting data:
Evaluate legislation to remove personal data from RTB auctions and work with international partners to adopt similar measures.
Real regulation of the advertising industry:
It is time for regulators and lawmakers to develop frameworks based on mandatory oversight with clear enforcement mechanisms and penalties for violation.
Independent audits and KYC:
Require that the advertising industry implement third-party audits and know-your-customer standards for all their business partners, as well as companies included in “certified” vendor registries. Develop meaningful penalties for failure to comply or misrepresentation.
Securing National Infrastructure Requires Blocking Ads and Tracking on Official Devices
Mandatory ad-blocking on government devices:
Issue policy guidance aligned with relevant cybersecurity agencies (e.g., CISA and NSA in the U.S.) recommendations requiring ad-blocking software on edge devices, and ad-blocking at the gateway for all government-owned devices. (See, for example, U.S. Senator Ron Wyden’s
letter
to the CIO of the U.S. Department of Defense, as well as Senator Wyden and Rep. Harrigon’s joint
letter
to the Inspector General of the U.S. Department of Defense).
Opt-out of ad targeting
: Mandate the disabling of unique advertising IDs on all government mobile devices (such as through MDM), and issue guidance and policy recommendations for personal devices used in governmental spaces.
Ban browsers that facilitate data harvesting:
Evaluate the security risks of browsers with impossible-to-disable tracking, and consider provisionally banning them from governmental networks and devices.
Defenders: Ad-Blocking Is A Cybersecurity Best Practice
AdFection attacks demonstrate that online advertising is now a vector for zero-click spyware infection into your organization. Taken together with research showing that data from targeted advertising is
already being used for mass espionage
, and potentially for
corporate espionage
, this makes it clear
there is currently no consistently safe way to expose your users and networks to targeted ads
. You can directly block Discover-Tech’s
current
methods by blocking advertising identifiers, however we suspect that the AdFection attack surface may be larger, requiring more systematic measures.
Block ads and tracking on devices and at the gateway:
Where possible, block online advertising at the gateway to your organization, and on work-issued and edge devices. Opting out of ad targeting (such as through MDM) on company-issued devices is also advisable. We also encourage you to develop guidance and easily actionable tools to help your personnel protect their devices.
Transition towards browsers with less tracking:
Browsers with built-in anti-tracking features, ad-blocking, and support for the Global Privacy Control (GPC) will improve your security posture and protect your IP.
Scrutinize targeted ads:
We encourage defenders to monitor traffic linked to advertising impressions for signs of malicious requests.
Protecting Yourself from AdFection
AdFection is a complex threat, and if you face elevated risk because of who you are or what you do, we strongly recommend seeking expert help. However, there are certain actions you can take to reduce some AdFection risks.
Increase your overall security by following personalized instructions from the
Security Planner
.
Consider using a privacy-respecting browser that blocks tracking and data-harvesting.
Regularly reset your Mobile Advertising
ID
,
disable ad-tracking
, and use opt-out features of apps.
Consider using an ad-blocking service on your network, such as at your home router, or use a trusted commercial VPN service that offers ad-blocking.
Further Research
Our investigation found that an attacker that we call
DARK CARTOGRAPHER
used Discover-Tech ads and a number of additional vendors to deanonymize users at scale since at least 2019. As these efforts rely on the exploitation of widespread security issues across numerous mobile providers, disclosure to providers is in progress. We will release a subsequent report delving into technical analysis and attribution of these attacks once the disclosure process is complete.
Based on our findings, we believe that further research would be fruitful with respect to:
customers and victims of the ad-based spyware deployment capabilities provided by Discover-Tech and the companies linked to it, including Candiru, Bindecy, and Intelos;
additional vendors and vendor networks that deploy ad-based spyware; and,
technical, organizational, regulatory, and political measures that effectively prevent the distribution of spyware via digital advertising.
This report is part of an ongoing series of investigations we are doing on surveillance technologies that rely on digital advertising. We will be publishing subsequent investigations that explore areas for further research we have flagged in this report.
Discover-Tech Ltd, Candiru (Integrity Labs), Bindecy, Intelos, Xandr (Microsoft Advertising), Sunteng, IAB Europe, and Affle did not respond to our request for comment within the timeline provided.
On October 11, 2026, we received a
response
from Adtimizer Ltd. In its response, Adtimizer Ltd claims that the adtimizer.[co] subdomains we consider to be linked to Discover-Tech were “used solely within Discover Tech’s infrastructure, which was entirely separate from ours and was not operated, managed, or controlled by Adtimizer”, and that Adtimizer “had no knowledge of, or involvement in the alleged activities” with respect to Discover-Tech’s malicious ad targeting. The company’s full response is available
here
.
On October 12, 2026 we received a
response
from Volasim Ltd. In its response, Volasim states that Discover-Tech was among the “external advertising providers” it engaged to “promote its products”. Volasim emphasizes in its response that it “has no involvement whatsoever in the spyware-related activities” discussed in our investigation, and that it has “never commissioned, authorized, participated in, or knowingly facilitated any such activity”. The company’s full response is available
here
.
On October 12, 2026, we received a
response
from Vungle (Liftoff), stating: “We have paused all Discover-Tech Ltd. access while we conduct our own review. Because this review is ongoing, we are not currently in a position to confirm or comment on the specific factual assertions in your letter. We will take any further action warranted.”
On October 13, 2026, we received a
response
from Beeswax (FreeWheel / Comcast), stating as follows: “Beeswax constantly monitors traffic quality and security threats to its Buyer Cloud platform through internal controls and third-party detection tools. Based on activity we observed recently, and after independent third-party security specialist validation, Beeswax already acted to remove Discover-Tech from Buyer Cloud. Malicious advertising of any kind is prohibited on our platform, and we will keep working with our security partners and the wider industry to detect and remove bad actors.”
On October 14, 2026, we received a
response
from Eskimi, stating: “Eskimi has clear rules and controls designed to detect and stop advertisers who try to misuse our platform. Campaigns and creative tags are screened by independent third-party ad-verification vendors as well as by our own monitoring tools. In this case, the advertiser’s tags were built to evade automated scanning. They loaded different code depending on who was viewing the ad, including the device, IP address and location, and campaigns were often restricted to very narrow IP target lists. This is how they passed third-party verification. Our own monitoring flagged this behaviour, and campaigns and individual tags were stopped as our controls detected them. We have since shared the relevant technical indicators with our supply partners. In the interest of supporting your research, the indicators we identified include creative tags calling remote “getAd” loaders hosted on dtech.adtimizer.co, several mtrtb.com subdomains (noas, infinoas and ppv2), and events.myweb3id.io. Because these loaders served different code depending on the viewer and targeting, they were not detected by third-party ad-verification scanning. Additional technical information can be provided where it is useful for your research. Discover-Tech had been a self-service advertiser on the Eskimi DSP since 2022, under our standard advertiser terms. Because of our campaign and individual tag blocks, its activity remained small, amounting to only a few hundred dollars in media spend. Its last campaign through the Eskimi DSP was stopped on 6 August 2026, and no impressions have been served since. Once the full pattern of the advertiser’s behaviour became clear, we permanently blocked all of its accounts, users and associated domains. We are working with independent ad-security specialists to help identify similar behaviour across the industry. As I mentioned, happy to contribute with anything that can help with further investigation and ensuring compliance in the ad-tech market.”
Google, which collaborated in the investigation, informed us that it “terminated Discover-Tech’s access to its ad exchange platforms, blocking them from bidding or serving ads across our ecosystem. Google has also deployed Safe Browsing protections to warn users that may encounter known actor-controlled domains”.
While IAB Europe did not respond to our request for comment within the timeline provided, we received a response on October 15 which we have published
here
.
Note on Research Ethics
All research involving human subjects conducted at the Citizen Lab is governed under research ethics protocols reviewed and approved by the University of Toronto’s Research Ethics Board.
Acknowledgements
We thank the teams at Al Jazeera for graciously consenting to our investigating this case, and agreeing to be named in the report.
We thank the teams at Confiant, Google, and additional researchers for their assistance and collaboration in this investigation. We would also like to thank Rebekah Brown, Maia Scott, and Krzysztof Franaszek (Adalytics Research) for peer reviewing this work, as well as other anonymous peer reviewers. Thanks to Adam Senft, Aly Bruce, Anna Mackay, and Claire Posno for editorial and communications support.
Appendix A. Ad Vendors Involved in Discover-Tech’s Ad Operations
Google and Yandex
Google dominates the digital advertising ecosystem in the
U.S.
,
Europe
, and other regions. It
operates
a massive ad exchange and systems for ad sellers (Ad Manager, AdSense, AdMob) and ad buyers (Google Ads, DV360). Its “Authorized Buyers” program
allows
third-party ad vendors to deliver ads by participating in ad auctions on Google’s ad exchange.
Yandex, although much smaller in revenue, similarly dominates the digital advertising ecosystem in
Russia
and some other regions. It also
provides
both
an ad exchange and systems for ad sellers and buyers.
Beeswax, Owned by Freewheel/Comcast
Beeswax is a major US-based ad buying platform, since 2021
owned by
Comcast’s ad platform FreeWheel. It
offers
a Demand-Side Platform (DSP) that helps advertisers and other ad vendors deliver targeted ads to users by participating in ad auctions. Its “bidder-as-a-service” product is
considered
highly customizable and imposes fewer restrictions on its clients than other DSPs.
The FreeWheel website
states
that, by using Beeswax’ ad buying platform rather than other DSPs, clients could “access the full, unfiltered stream of RTB events, in much the same way [they] would if [they] were building a bidder from scratch”. Clients can
augment
the stream of ad bidding data they receive, for example, by “mapping” users to “rich profiles”, and they can
use
custom bidding algorithms and targeting attributes.
While this appears to offer great flexibility to clients to an extent that may come close to operating their own DSP, FreeWheel takes care of the integrations with ad exchanges and Supply-Side Platforms (SSPs) that help app and website publishers sell ads. As of July 2026, the FreeWheel website
lists
integrations with 36 “supply partners” including Google, Amazon, Microsoft, Index Exchange, and many others.
Beeswax is listed as an approved TCF ad vendor by IAB Europe (
vendor list
). Google lists Beeswax as a
certified ad vendor
and among its “common” European
ad technology partners
which Google will use by default when publishers do not set up a custom list of ad vendors. For its ad serving and third-party tracking, Beeswax uses the
domain bidr[.]io
and the cookie identifier
bito
(
devicedisclosure.json
).
Eskimi, a White-Label DSP Based in Lithuania
Eskimi is a digital advertising group based in Lithuania with offices in Greece, Turkey, Japan, United Arab Emirates, Indonesia, Bangladesh, Nigeria, and Kenya, according to its website, eskimi.com. Its ad buying platform
Eskimi DSP
, which
allows
its clients to target 1.5 billion “profiled users” across 60 ad exchanges, according to the company, is also
offered
as a “white-label” version that “enables agencies, ad networks, and businesses to offer ‘Eskimi DSP’ under their own brand”. Eskimi also
provides
a data management platform (DMP) that “collects and stores data” it receives from 50 ad exchanges, amounting to two2 billion profiles, according to a 2025 version of the company’s website. Its website and Lithuanian company records show that it is incorporated as “UAB Eskimi”, also known as “UAB Aktyvus sektorius”.
Eskimi is much lesser known than Beeswax. Except for two
paid
posts
, we did not find any articles discussing the company on digital advertising trade press sites like Adweek, Digiday, and AdExchanger. Eskimi was, however, prominently discussed when US-based data broker Datastream Group
told
U.S. Senator Ron Wyden that Eskimi was the source of 3.6 billion location data records revealing the exact movements of millions of people, including U.S. military and intelligence personnel, as reported in a joint investigation by German
netzpolitik.org
and other outlets. This investigation has helped spark extensive debates about ad surveillance.
While German netzpolitik.org
found
several additional links between the analyzed data and the company, Eskimi
denied
that it was the source of the data. Google
told
404 Media that Eskimi is “part of Google’s Authorized Buyer program and must abide by our policies”. It added that it “regularly audits its Authorized Buyers program participants”. Eskimi is closely linked to the location data broker Redmob, which claims to sell data on one billion people across 150 countries according to its website, redmob.io. While Redmob is incorporated in Dubai, netzpolitik.org
found
that Eskimi and Redmob share the same CEO, who responded to their questions about Eskimi from a Redmob email address.
Vungle was a mobile advertising firm that
merged with
the U.S.-based mobile advertising firm Liftoff, which
went public
in June 2026. Since the merger, Liftoff offers several Vungle-branded products including a Supply-Side Platform (SSP) named
Monetize
, which helps app publishers sell ads, and the mobile ad exchange
Vungle Exchange
, which helps marketers buy ads served in mobile apps.
Both the SSP and the ad exchange rely on the
Vungle SDK
, which is a piece of advertising and tracking software embedded in many Android, iOS, Amazon, Windows, and Unity apps. The Vungle SDK is embedded in 150,000 mobile apps used by one billion people across 150 countries, which also describes the number of users that can be targeted via the Vungle ad exchange,
according to
the company.
Guidelines for the Vungle ad exchange
contain
a rule that asks clients to “refrain from” using the platform for the distribution of “malware, spyware, and files that can harm or gain unauthorized access to a device or user information”. We did not find an explanation of how the company monitors and enforces this rule.
Vungle has been controversially discussed in
several
papers and reports on mobile tracking and privacy. The Norwegian Consumer Council
found in 2020
that Vungle received GPS coordinates and other personal data on users of Grindr and another mobile app, seemingly without a legal basis under the GDPR.
As of July 2026, Liftoff’s “Monetize” and “Vungle Exchange” products are listed as approved TCF ad vendors by IAB Europe (
vendor list
). Google lists Liftoff’s DSP and Monetize products as
certified ad vendors
and it lists Liftoff among its “common” European
ad technology partners
that Google will use by default when publishers do not choose a custom list of ad vendors.
Google has been deeply interconnected with Vungle from its inception. Google Ventures was an
investor
in Vungle’s seed, series A, and series B funding rounds. The Norwegian Consumer Council
pointed out
in 2020 that Google’s mobile advertising system AdMob “provides Vungle with access to extra features that allow Vungle to bypass data filters, and thus send more data to its partners than what would ordinarily be possible through Google’s regular advertising tools”. As of July 2026, Liftoff’s Vungle product Monetize is
listed
among a few “premium bidding partners” in Google’s mobile advertising system
AdMob
and among a few “ad sources” for AdMob’s advertising services on
Android
and
iOS
.
Sunteng, a Chinese SSP, DSP, and Ad Exchange
The Chinese digital advertising firm Sunteng provides ad buying and selling services for both advertisers and publishers, as well as a “programmatic marketplace”, i.e. an ad exchange,
according to
its website, sunteng.com. The site also
refers to
the company as “Shunfei Technology”. The link to Sunteng’s DSP offering
leads
site visitors to biddingx.com (“BiddingX”), an entity that
promotes itself
as China’s largest DSP. Sunteng
appears to
operate also under the brand Bidex (bidex.cn), which
focuses
on “overseas programmatic”, i.e. on digital advertising services for non-Chinese clients. We assume that Sunteng, Shunfei, Bidex and BiddingX are part of the same Chinese group of companies with
offices
in Singapore and the US. Sunteng
claims
to process 50 billion ad bid requests a day across 10,000 mobile apps and 60 ad vendor partners, and it
lists
Eskimi as a partner.
As of July 2026, Google lists biddingx.com (“Shunfei Infomation Technology Corporatio” [sic]) as a
certified ad vendor
. IAB Europe listed bidex.cn (“Sunteng Hong Kong Holdings Limited”) as an approved TCF ad vendor until December 2025 (
vendor list
).
Xandr, aka Microsoft Advertising
Xandr,
formerly
known as AppNexus, has long been a major player in digital advertising. After Microsoft
acquired
it from AT&T in 2022, it
became
part of Microsoft Advertising in 2023. While Microsoft
shut down
Xandr’s ad buying system, the “Invest” DSP, in early 2026, it continues to offer Xandr’s ad selling system, the “Monetize” SSP. Ad buyers who used the former Xandr DSP were “handed” to Amazon DSP,
according to
trade press reporting.
As shown in
Section 6
, Microsoft’s user ID syncing in the browser via the domain
adnxs[.]com
,
which
assigns
a Microsoft user ID to people who visit the sites of ad sellers and maps it to user IDs assigned by other ad vendors, appears to remain operational as of June 2026. Xandr has long been operating massive identity databases. In 2020, when Xandr was still owned by AT&T, it
reportedly
operated an identity graph linking 5 billion identifiers.
As of July 2026, Microsoft’s ad system Xandr is listed as an approved TCF ad vendor by IAB Europe (
vendor list
). Google’s list of
certified ad vendors
contains four records for Xandr. Google also lists Xandr among its “common” European
ad technology partners
which Google will use by default when publishers do not choose a custom list of ad vendors.
Appendix B. Glossary
Adtech vendor, ad vendor.
Advertising technology intermediary such as a Demand-Side Platform (DSP), Supply-Side Platform (SSP) (both defined below) or ad exchange.
Ad Slot.
Designated space or position on a website or mobile app reserved to display an ad.
Demand-Side Platform (DSP).
System operated by an adtech intermediary that helps advertisers buy ad placements across many different websites or mobile apps in an automated way by participating in real-time auctions hosted by ad exchanges.
Supply-Side Platform (SSP).
System operated by an adtech intermediary that helps publishers of websites or mobile apps sell ad slots in an automated way by participating in real-time auctions hosted by an ad exchange, which is often operated by the same ad vendor as the SSP.
Ad Exchange.
Automated marketplace operated by an adtech intermediary that hosts real-time auctions which facilitate the selling of ad slots and the buying of ad placements across many publishers, advertisers and intermediaries like DSPs and SSPs. Ad exchanges are often operated by SSPs.
Real-Time Bidding (RTB).
Automated high-frequency auctions hosted by ad exchanges where advertisers (or DSPs on their behalf) bid on ad placements offered by website and mobile app publishers (or their SSPs). When a user visits a website or uses an app that sells targeted ads via RTB, the publisher’s SSP initiates a bid request that transmits data about the user and the ad slot to several DSPs, who submit bids on behalf of advertisers. The ad exchange determines the winner of the auction and pushes the ad to the user.
Bid Request.
RTB auction record that describes an ad slot and the user who currently visits a website or uses a mobile app. Bid requests are initiated by publishers and sent via an SSP and an ad exchange to several DSPs, which place bids in order to show ads to specific users on behalf of advertisers. Bid requests typically contain personal data about users in order to facilitate targeted advertising.
Mobile Advertising ID (MAID).
Unique identifier for a mobile device used for advertising and tracking purposes, assigned by the device’s operating system such as Google Android or Apple iOS. While users can reset or delete mobile ad IDs in the settings, they are activated by default. Advertising and data companies use mobile ad IDs to link user data across contexts and vendors in order to track, follow, profile and target users.
Cookie ID.
Unique identifier for a user’s web browser, typically stored and retrieved in the browser by third-party code operated by adtech vendors during website visits.
Appendix C. Domains linked to Discover-Tech and Controlium
General
We assess that the following domains are – or have been – linked to Discover-Tech and Controlium:
Note that the “\r?” after the date header is due to a 2022 Censys bug and does not relate to server behaviour. Anyone seeking to write signatures over HTTP banners on Censys, who wishes those signatures to be applicable to the 2022 timeframe, should make a similar modification to their signatures.
↩︎
We also submitted several of the bundle.js files containing the frontend to the Internet Archive’s Wayback Machine (
1
,
2
,
3
,
4
) to assist in future investigations by other researchers.
↩︎
Abstract:
How can we build an agent that thinks beyond human language, yet still acts through it in the external environment? Modern LLM agents still reason and interact through text, while latent reasoning offers an efficient internal medium but lacks native tool access and reasoning transparency. We bridge these two directions with Hybrid Reasoning Agents (HybridAgents), which dynamically navigate between latent reasoning and text-based interaction throughout a unified generation process. Architecturally, a lightweight HybridLink enables seamless transitions between text and latent modes, while the agent's continuous working memory preserves lossless hybrid context across multiple turns. These designs preserve tool-integrated agentic capabilities while making latent thoughts directly inspectable. Building on this architecture, we further develop dedicated post-training algorithms for hybrid reasoning: HybridSFT stabilizes tool-integrated hybrid generation by teaching the backbone to coordinate with HybridLink, then HybridRL scales reasoning by learning when to think in latent space and when to act through text. We evaluate HybridAgent at 3 model scales across 11 benchmarks covering mathematics, science, medicine, search, and agentic reasoning. Compared with frontier LLM Agents and agentic frameworks spanning both text-based and latent methods, HybridAgent consistently improves performance by 10.4%, while delivering 35.5%-54.7% token reduction, 1.8x-2.6x faster inference, and 2.7x-3.7x cost savings. Code and data are available at
this https URL
.
Submission history
From: Jiaru Zou [
view email
]
[v1]
Tue, 13 Oct 2026 17:59:31 UTC (8,500 KB)
Netflix vmaf: Perceptual video quality assessment based on multi-method fusion
VMAF is an
Emmy-winning
perceptual video quality assessment algorithm developed by Netflix. This software package includes a stand-alone C library
libvmaf
and its wrapping Python library. The Python library also provides a set of tools that allows a user to train and test a custom VMAF model.
Read
this
tech blog post for an overview,
this
post for the tips of best practices, and
this
post for our latest efforts on speed optimization, new API design and the introduction of a codec evaluation-friendly
NEG mode
.
Also included in
libvmaf
are implementations of several other metrics: PSNR, PSNR-HVS, SSIM, MS-SSIM and CIEDE2000.
News
(2026-06) We are releasing a new set of VMAF models (
v1
). See
tech blog
for more information on v1. See
models_v1.md
for details and model selection guidance. The previous generation of models (v0) remains documented in
models_v0.md
. We are open to user feedback on VMAF v1 and will continue to improve and update the models over time.
(2023-12-07) We are releasing
libvmaf v3.0.0
. It contains several optimizations and bug fixes, and a full removal of the APIs which were deprecated in
v2.0.0
.
(2021-12-15) We have added to CAMBI the
full_ref
input parameter to allow running CAMBI as a full-reference metric, taking into account the banding that was already present on the source. Check out the
usage
page.
(2021-12-1) We have added to CAMBI the
max_log_contrast
input parameter to allow to capture banding with higher contrasts than the default. We have also sped up CAMBI (e.g., around 4.5x for 4k). Check out the
usage
page.
(2021-10-7) We are open-sourcing CAMBI (Contrast Aware Multiscale Banding Index) - Netflix's detector for banding (aka contouring) artifacts. Check out the
tech blog
for an overview and the
technical paper
published in PCS 2021 (note that the paper describes an initial version of CAMBI that no longer matches the code exactly, but it is still a good introduction). Also check out the
usage
page.
(2020-12-7) Check out our
latest tech blog
on speed optimization, new API design and the introduction of a codec evaluation-friendly NEG mode.
(2020-12-3) We are releasing
libvmaf v2.0.0
. It has a new fixed-point and x86 SIMD-optimized (AVX2, AVX-512) implementation that achieves 2x speed up compared to the previous floating-point version. It also has a
new API
that is more flexible and extensible.
(2020-7-13) We have created a
memo
to share our thoughts on VMAF's property in the presence of image enhancement operations, its impact on codec evaluation, and our solutions. Accordingly, we have added a new mode called
No Enhancement Gain (NEG)
.
(2020-2-27) We have changed VMAF's license from Apache 2.0 to
BSD+Patent
, a more permissive license compared to Apache that also includes an express patent grant.
Documentation
There is an
overview of the documentation
with links to specific pages, covering FAQs, available models and features, software usage guides, and a list of resources.
Usage
The software package offers a number of ways to interact with the VMAF implementation.
The command-line tool
vmaf
provides a complete algorithm implementation, such that one can easily deploy VMAF in a production environment. Additionally, the
vmaf
tool provides a number of auxillary features such as PSNR, SSIM and MS-SSIM.
The
C library
libvmaf
provides an interface to incorporate VMAF into your code, and tools to integrate other feature extractors into the library.
The
Python library
offers a full array of wrapper classes and scripts for software testing, VMAF model training and validation, dataset processing, data visualization, etc.
VMAF is now included as a filter in FFmpeg, and can be configured using:
./configure --enable-libvmaf
. Refer to the
Using VMAF with FFmpeg
page.
To build VMAF on Windows, follow
these
instructions.
AOM CTC: AOM has specified vmaf to be the standard implementation metrics tool according to the AOM common test conditions (CTC). Refer to
this page
for usage compliant with AOM CTC.
Apple Issues Statement on Duo Demand Far Outstripping Supply
Daring Fireball
www.ft.com
2026-10-18 16:04:44
The Financial Times:
Apple had originally promised delivery of the Duo by October 23,
but within hours of orders opening, delivery times through Apple’s
website had slipped into late January. US mobile carriers also saw
delivery times for new orders pushed back.
“The pre-order demand for iPhone...
For help please visit
help.ft.com
. We
apologise for any inconvenience.
The following information can help our support team to resolve this issue.
Error Code
CG000 / 403
Request ID
a4ca2f953f2c3992
Dirk Eddelbuettel: myman 0.12.0 on CRAN: Two new waves!
PlanetDebian
dirk.eddelbuettel.com
2026-10-18 16:00:00
Another new and exciting version of our still-new package myman reached CRAN this morning, and has been
built for r2u and on
r-universe. The
matching Python package
has also been updated. The package offers twenty one hundred eighty four
“My man …” posts by Kevin Kruse
made on bsky during the summer...
Another new and exciting version of our still-new package
myman
reached
CRAN
this morning, and has been
built for
r2u
and on
r-universe
. The
matching
Python package
has also been updated. The package offers twenty one hundred eighty four
“My man …”
posts by
Kevin Kruse
made on
bsky
during the summer of 2026.
Each wave picked at one particular public persona. This package wrapse
these up in the style of packages like
fortunes
or
gaussfacts
.
This release regroups two new waves of posts mocking, respectively,
Peter Thiel and Michael Tracy, and make a small update to continuous
integration. The short NEWS entry for this release follows.
Changes in version 0.12.0
(2026-10-18)
New waves eleven (100 posts) and twelve (100 posts) made last
week; total is now 2184 posts
Comments (0) Trackbacks (0) Leave a comment Trackback