10 interesting stories served every morning and every evening.
It may be just me, but I read this as “I don’t want to 😜 😜 but I’ll kill AdBlockers in Firefox for buckerinos 😂”. This disappoints and saddens me a lot, and I hope I’m wrong.
...
Read the original on infosec.press »
Gemini 3 Flash is our latest model with frontier intelligence built for speed that helps everyone learn, build, and plan anything — faster.
Senior Director, Product Management, on behalf of the Gemini team
Google is releasing Gemini 3 Flash, a fast and cost-effective model built for speed. You can now access Gemini 3 Flash through the Gemini app and AI Mode in Search. Developers can access it via the Gemini API in Google AI Studio, Google Antigravity, Gemini CLI, Android Studio, Vertex AI and Gemini Enterprise.
Summaries were generated by Google AI. Generative AI is experimental.
It’s great for coding, complex analysis, and quick answers in interactive apps.
Gemini 3 Flash is now the default model in the Gemini app and AI Mode in Search.
Developers and everyday users can access Gemini 3 Flash via various Google platforms.
Summaries were generated by Google AI. Generative AI is experimental.
...
Read the original on blog.google »
AWS CEO Matt Garman outlined 3 solid reasons why companies should not focus on cutting junior developer roles, noting that they “are actually the most experienced with the AI tools”.
In a tech world obsessed with AI replacing human workers, Matt Garman, CEO of Amazon Web Services (AWS), is pushing back against one of the industry’s most popular cost-cutting ideas.
Speaking on WIRED’s The Big Interview podcast, Garman has a bold message for companies racing to cut costs with AI.
He was asked to explain why he once called replacing junior employees with AI “one of the dumbest ideas” he’d ever heard, and to expand on how he believes agentic AI will actually change the workplace in the coming years.
First, junior employees are often better with AI tools than senior staff.
Fresh grads have grown up with new technology, so they can adapt quickly. Many of them learn AI-powered tools while studying or during internships. They tend to explore new features, find quick methods to write code, and figure out how to get the best results from AI agents.
According to the 2025 Stack Overflow Developer Survey, 55.5% of early-career developers reported using AI tools daily in their development process, higher than for the experienced folks.
This comfort with new tools allows them to work more efficiently. In contrast, senior developers have established workflows and may take more time to adopt. Recent research shows that over half of Gen Z employees are actually helping senior colleagues upskill in AI.
Second, junior staff are usually the least expensive employees.
Junior employees usually get much less in salary and benefits, so removing them does not deliver huge savings. If a company is trying to save money, it doesn’t make that much financial sense.
So, when companies talk about increasing profit margins, junior employees should not be the default or only target. True optimization, Real cost-cutting means looking at the whole company because there are plenty of other places where expenses can be trimmed.
In fact, 30% of companies that laid off workers expecting savings ended up increasing expenses, and many had to rehire later.
Think of a company like a sports team. If you only keep veteran players and never recruit rookies, what happens when those veterans retire? You are left with no one who knows how to play the game.
Also, hiring people straight out of college brings new ways of thinking into the workplace. They have fresh ideas shaped by the latest trends, motivation to innovate.
More importantly, they form the foundation of a company’s future workforce. If a company decides to stop hiring junior employees altogether, it cuts off its own talent pipeline. Over time, that leads to fewer leaders to promote from within.
A Deloitte report also notes that the tech workforce is expected to grow at roughly twice the rate of the overall U. S. workforce, highlighting the demand for tech talent. Without a strong pipeline of junior developers coming in, companies might face a tech talent shortage.
When there are not enough junior hires being trained today, teams struggle to fill roles tomorrow, especially as projects scale.
This isn’t just corporate talk. As the leader of one of the world’s largest cloud computing platforms, serving everyone from Netflix to the U. S. intelligence agencies, Garman has a front-row seat to how companies are actually using AI.
And what he is seeing makes him worried that short-term thinking could damage businesses for years to come. Garman’s point is grounded in long-term strategy. A company that relies solely on AI to handle tasks without training new talent could find itself short of people.
Still, Garman admits the next few years will be bumpy. “Your job is going to change,” he said. He believes AI will make companies more productive as well as the employees.
When technology makes something easier, people want more of it. AI enables the creation of software faster, allowing companies to develop more products, enter new markets, and serve more customers.
Developers will be responsible for more than just writing code, with faster adaptation to new technologies becoming essential. But he has a hopeful message in the end.
That’s why Geoffrey Hinton has advised that Computer Science degrees remain essential. This directly supports Matt Garman’s point. Fresh talent with a strong understanding of core fundamentals becomes crucial for filling these higher-value roles of the future.
“I’m very confident in the medium to longer term that AI will definitely create more jobs than it removes at first,” Garman said.
...
Read the original on www.finalroundai.com »
Containers are the universal path to production for most developers, and Docker has always been the steward of the ecosystem. Docker Hub has over 20 billion monthly pulls, with nearly 90% of organizations now relying on containers in their software delivery workflows. That gives us a responsibility: to help secure the software supply chain for the world.
Why? Supply-chain attacks are exploding. In 2025, they caused more than $60 billion in damage, tripling from 2021. No one is safe. Every language, every ecosystem, every build and distribution step is a target.
For this reason, we launched Docker Hardened Images (DHI), a secure, minimal, production-ready set of images, in May 2025, and since then have hardened over 1,000 images and helm charts in our catalog. Today, we are establishing a new industry standard by making DHI freely available and open source to everyone who builds software. All 26 Million+ developers in the container ecosystem. DHI is fully open and free to use, share, and build on with no licensing surprises, backed by an Apache 2.0 license. DHI now gives the world a secure, minimal, production-ready foundation from the very first pull.
If it sounds too good to be true, here’s the bottom line up front: every developer and every application can (and should!) use DHI without restrictions. When you need continuous security patching, applied in under 7 days, images for regulated industries (e.g., FIPS, FedRAMP), you want to build customized images on our secure build infrastructure, or you need security patches beyond end-of-life, DHI has commercial offerings. Simple.
Since the introduction of DHI, enterprises like Adobe and Qualcomm have bet on Docker for securing their entire enterprise to achieve the most stringent levels of compliance, while startups like Attentive and Octopus Deploy have accelerated their ability to get compliance and sell to larger businesses.
Now everyone and every application can build securely from the first docker build. Unlike other opaque or proprietary hardened images, DHI is compatible with Alpine and Debian, trusted and familiar open source foundations teams already know and can adopt with minimal change. And while some vendors suppress CVEs in their feed to maintain a green scanner, Docker is always transparent, even when we’re still working on patches, because we fundamentally believe you should always know what your security posture is. The result: dramatically reduced CVEs (guaranteed near zero in DHI Enterprise), images up to 95 percent smaller, and secure defaults without ever compromising transparency or trust.
There’s more. We’ve already built Hardened Helm Charts to leverage DHI images in Kubernetes environments; those are open source too. And today, we’re expanding that foundation with Hardened MCP Servers. We’re bringing DHI’s security principles to the MCP interface layer, the backbone of every agentic app. And starting now, you can run hardened versions of the MCP servers developers rely on most: Mongo, Grafana, GitHub, and more. And this is just the beginning. In the coming months, we will extend this hardened foundation across the entire software stack with hardened libraries, hardened system packages, and other secure components everyone depends on. The goal is simple: be able to secure your application from main() down.
Base images define your application’s security from the very first layer, so it’s critical to know exactly what goes into them. Here’s how we approach it.
First: total transparency in every part of our minimal, opinionated, secure images.
DHI uses a distroless runtime to shrink the attack surface while keeping the tools developers rely on. But security is more than minimalism; it requires full transparency. Too many vendors blur the truth with proprietary CVE scoring, downgraded vulnerabilities, or vague promises about reaching SLSA Build Level 3.
DHI takes a different path. Every image includes a complete and verifiable SBOM. Every build provides SLSA Build Level 3 provenance. Every vulnerability is assessed using transparent public CVE data; we won’t hide vulnerabilities when we haven’t fixed them. Every image comes with proof of authenticity. The result: a secure foundation you can trust, built with clarity, verified with evidence, and delivered without compromise.
Second: Migrating to secure images takes real work, and no one should pretend otherwise. But as you’d expect from Docker, we’ve focused on making the DX incredibly easy to use. As we mentioned before, DHI is built on the open source foundations the world already trusts, Debian and Alpine, so teams can adopt it with minimal friction. We’re reducing that friction even more: Docker’s AI assistant can scan your existing containers and recommend or even apply equivalent hardened images; the feature is experimental as this is day one, but we’ll quickly GA it as we learn from real world migrations.
Lastly: we think about the most aggressive SLAs and longest support times and make certain that every piece of DHI can support that when you need it.
DHI Enterprise, the commercial offering of DHI, includes a 7-day commitment for critical CVE remediation, with a roadmap toward one day or less. For regulated industries and mission-critical systems, this level of trust is mandatory. Achieving it is hard. It demands deep test automation and the ability to maintain patches that diverge from upstream until they are accepted. That is why most organizations cannot do this on their own. In addition, DHI Enterprise allows organizations to easily customize DHI images, leveraging Docker’s build infrastructure which takes care of the full image lifecycle management for you, ensuring that build provenance and compliance is maintained. For example, typically organizations need to add certificates and keys, system packages, scripts, and so on. DHI’s build service makes this trivial.
Because our patching SLAs and our build service carry real operational cost, DHI has historically been one commercial offering. But our vision has always been broader. This level of security should be available to everyone, and the timing matters. Now that the evidence, infrastructure, and industry partnerships are in place, we are delivering on that vision. That is why today we are making Docker Hardened Images free and open source.
This move carries the same spirit that defined Docker Official Images over a decade ago. We made them free, kept them free, and backed them with clear docs, best practices, and consistent maintenance. That foundation became the starting point for millions of developers and partners.
Now we’re doing it again. DHI being free is powered by a rapidly growing ecosystem of partners, from Google, MongoDB, and the CNCF delivering hardened images to security platforms like Snyk and JFrog Xray integrating DHI directly into their scanners. Together, we are building a unified, end-to-end supply chain that raises the security bar for the entire industry.
Everyone now has a secure foundation to start from with DHI. But businesses of all shapes and sizes often need more. Compliance requirements and risk tolerance may demand CVE patches ahead of upstream the moment the source becomes available. Companies operating in enterprise or government sectors must meet strict standards such as FIPS or STIG. And because production can never stop, many organizations need security patching to continue even after upstream support ends.
That is why we now offer three DHI options, each built for a different security reality.
Docker Hardened Images: Free for Everyone. DHI is the foundation modern software deserves: minimal hardened images, easy migration, full transparency, and an open ecosystem built on Alpine and Debian.
Docker Hardened Images (DHI) Enterprise: DHI Enterprise delivers the guarantees that organizations, governments, and institutions with strict security or regulatory demands rely on. FIPS-enabled and STIG-ready images. Compliance with CIS benchmarks. SLA-backed remediations they can trust for critical CVEs in under 7 days. And those SLAs keep getting shorter as we push toward one-day (or less) critical fixes.
For teams that need more control, DHI Enterprise delivers. Change your images. Configure runtimes. Install tools like curl. Add certificates. DHI Enterprise gives you unlimited customization, full catalog access, and the ability to shape your images on your terms while staying secure.
DHI Extended Lifecycle Support (ELS): ELS is a paid add-on to DHI Enterprise, built to solve one of software’s hardest problems. When upstream support ends, patches stop but vulnerabilities don’t. Scanners light up, auditors demand answers, and compliance frameworks expect verified fixes. ELS ends that cycle with up to five additional years of security coverage, continuous CVE patches, updated SBOMs and provenance, and ongoing signing and auditability for compliance.
You can learn more about these options here.
Securing the container ecosystem is something we do together. Today, we’re giving the world a stronger foundation to build on. Now we want every developer, every open source project, every software vendor, and every platform to make Docker Hardened Images the default.
* Join our launch webinar to get hands-on and learn what’s new.
* Explore the docs and bring DHI into your workflows
* Join our partner program and help raise the security bar for everyone.
Lastly, we are just getting started, and if you’re reading this and want to help build the future of container security, we’d love to meet you. Join us.
Today’s announcement marks a watershed moment for our industry. Docker is fundamentally changing how applications are built-secure by default for every developer, every organization, and every open-source project.
This moment fills me with pride as it represents the culmination of years of work: from the early days at Atomist building an event-driven SBOM and vulnerability management system, the foundation that still underpins Docker Scout today, to unveiling DHI earlier this year, and now making it freely available to all. I am deeply grateful to my incredible colleagues and friends at Docker who made this vision a reality, and to our partners and customers who believed in us from day one and shaped this journey with their guidance and feedback.
Yet while this is an important milestone, it remains just that, a milestone. We are far from done, with many more innovations on the horizon. In fact, we are already working on what comes next.
Security is a team sport, and today Docker opened the field to everyone. Let’s play.
I joined Docker to positively impact as many developers as possible. This launch gives every developer the right to secure their applications without adding toil to their workload. It represents a monumental shift in the container ecosystem and the digital experiences we use every day.
I’m extremely proud of the product we’ve built and the customers we serve every day. I’ve had the time of my life building this with our stellar team and I’m more excited than ever for what’s to come next.
...
Read the original on www.docker.com »
The reliability and robustness of SQLite is achieved in part by thorough and careful testing.
As of version 3.42.0 (2023-05-16), the SQLite library consists of approximately 155.8 KSLOC of C code. (KSLOC means thousands of “Source Lines Of Code” or, in other words, lines of code excluding blank lines and comments.) By comparison, the project has 590 times as much test code and test scripts - 92053.1 KSLOC.
Extensive use of assert() and run-time checks
There are four independent test harnesses used for testing the core SQLite library. Each test harness is designed, maintained, and managed separately from the others.
The TCL Tests are the original tests for SQLite. They are contained in the same source tree as the SQLite core and like the SQLite core are in the public domain. The TCL tests are the primary tests used during development. The TCL tests are written using the
TCL scripting language. The TCL test harness itself consists of 27.2 KSLOC of C code used to create the TCL interface. The test scripts are contained in 1390 files totaling 23.2MB in size. There are 51445 distinct test cases, but many of the test cases are parameterized and run multiple times (with different parameters) so that on a full test run millions of separate tests are performed.
The TH3 test harness is a set of proprietary tests, written in C that provide 100% branch test coverage (and 100% MC/DC test coverage) to the core SQLite library. The TH3 tests are designed to run on embedded and specialized platforms that would not easily support TCL or other workstation services. TH3 tests use only the published SQLite interfaces. TH3 consists of about 76.9 MB or 1055.4 KSLOC of C code implementing 50362 distinct test cases. TH3 tests are heavily parameterized, though, so a full-coverage test runs about 2.4 million different test instances. The cases that provide 100% branch test coverage constitute a subset of the total TH3 test suite. A soak test prior to release does about 248.5 million tests. Additional information on TH3 is available separately.
The SQL Logic Test
or SLT test harness is used to run huge numbers of SQL statements against both SQLite and several other SQL database engines and verify that they all get the same answers. SLT currently compares SQLite against PostgreSQL, MySQL, Microsoft SQL Server, and Oracle 10g. SLT runs 7.2 million queries comprising 1.12GB of test data.
The dbsqlfuzz engine is a proprietary fuzz tester. Other fuzzers for SQLite
mutate either the SQL inputs or the database file. Dbsqlfuzz mutates both the SQL and the database file at the same time, and is thus able to reach new error states. Dbsqlfuzz is built using the
libFuzzer framework of LLVM with a custom mutator. There are 336 seed files. The dbsqlfuzz fuzzer runs about one billion test mutations per day. Dbsqlfuzz helps ensure that SQLite is robust against attack via malicious SQL or database inputs.
In addition to the four main test harnesses, there are many other small programs that implement specialized tests. Here are a few examples:
The “speedtest1.c” program
estimates the performance of SQLite under a typical workload.
The “mptester.c” program is a stress test for multiple processes
concurrently reading and writing a single database.
The “threadtest3.c” program is a stress test for multiple threads using
SQLite simultaneously.
The “fuzzershell.c” program is used to
run some fuzz tests.
The “jfuzz” program is a libfuzzer-based fuzzer for
JSONB inputs to the JSON SQL functions.
All of the tests above must run successfully, on multiple platforms and under multiple compile-time configurations, before each release of SQLite.
Prior to each check-in to the SQLite source tree, developers typically run a subset (called “veryquick”) of the Tcl tests consisting of about 304.7 thousand test cases. The veryquick tests include most tests other than the anomaly, fuzz, and soak tests. The idea behind the veryquick tests are that they are sufficient to catch most errors, but also run in only a few minutes instead of a few hours.
Anomaly tests are tests designed to verify the correct behavior of SQLite when something goes wrong. It is (relatively) easy to build an SQL database engine that behaves correctly on well-formed inputs on a fully functional computer. It is more difficult to build a system that responds sanely to invalid inputs and continues to function following system malfunctions. The anomaly tests are designed to verify the latter behavior.
SQLite, like all SQL database engines, makes extensive use of malloc() (See the separate report on
dynamic memory allocation in SQLite for additional detail.) On servers and workstations, malloc() never fails in practice and so correct handling of out-of-memory (OOM) errors is not particularly important. But on embedded devices, OOM errors are frighteningly common and since SQLite is frequently used on embedded devices, it is important that SQLite be able to gracefully handle OOM errors.
OOM testing is accomplished by simulating OOM errors. SQLite allows an application to substitute an alternative malloc() implementation using the sqlite3_config(SQLITE_CONFIG_MALLOC,…) interface. The TCL and TH3 test harnesses are both capable of inserting a modified version of malloc() that can be rigged to fail after a certain number of allocations. These instrumented mallocs can be set to fail only once and then start working again, or to continue failing after the first failure. OOM tests are done in a loop. On the first iteration of the loop, the instrumented malloc is rigged to fail on the first allocation. Then some SQLite operation is carried out and checks are done to make sure SQLite handled the OOM error correctly. Then the time-to-failure counter on the instrumented malloc is increased by one and the test is repeated. The loop continues until the entire operation runs to completion without ever encountering a simulated OOM failure. Tests like this are run twice, once with the instrumented malloc set to fail only once, and again with the instrumented malloc set to fail continuously after the first failure.
I/O error testing seeks to verify that SQLite responds sanely to failed I/O operations. I/O errors might result from a full disk drive, malfunctioning disk hardware, network outages when using a network file system, system configuration or permission changes that occur in the middle of an SQL operation, or other hardware or operating system malfunctions. Whatever the cause, it is important that SQLite be able to respond correctly to these errors and I/O error testing seeks to verify that it does.
I/O error testing is similar in concept to OOM testing; I/O errors are simulated and checks are made to verify that SQLite responds correctly to the simulated errors. I/O errors are simulated in both the TCL and TH3 test harnesses by inserting a new
Virtual File System object that is specially rigged to simulate an I/O error after a set number of I/O operations. As with OOM error testing, the I/O error simulators can be set to fail just once, or to fail continuously after the first failure. Tests are run in a loop, slowly increasing the point of failure until the test case runs to completion without error. The loop is run twice, once with the I/O error simulator set to simulate only a single failure and a second time with it set to fail all I/O operations after the first failure.
In I/O error tests, after the I/O error simulation failure mechanism is disabled, the database is examined using
PRAGMA integrity_check to make sure that the I/O error has not introduced database corruption.
Crash testing seeks to demonstrate that an SQLite database will not go corrupt if the application or operating system crashes or if there is a power failure in the middle of a database update. A separate white-paper titled
Atomic Commit in SQLite describes the defensive measures SQLite takes to prevent database corruption following a crash. Crash tests strive to verify that those defensive measures are working correctly.
It is impractical to do crash testing using real power failures, of course, and so crash testing is done in simulation. An alternative
Virtual File System is inserted that allows the test harness to simulate the state of the database file following a crash.
In the TCL test harness, the crash simulation is done in a separate process. The main testing process spawns a child process which runs some SQLite operation and randomly crashes somewhere in the middle of a write operation. A special VFS randomly reorders and corrupts the unsynchronized write operations to simulate the effect of buffered filesystems. After the child dies, the original test process opens and reads the test database and verifies that the changes attempted by the child either completed successfully or else were completely rolled back. The
integrity_check PRAGMA is used to make sure no database corruption occurs.
The TH3 test harness needs to run on embedded systems that do not necessarily have the ability to spawn child processes, so it uses an in-memory VFS to simulate crashes. The in-memory VFS can be rigged to make a snapshot of the entire filesystem after a set number of I/O operations. Crash tests run in a loop. On each iteration of the loop, the point at which a snapshot is made is advanced until the SQLite operations being tested run to completion without ever hitting a snapshot. Within the loop, after the SQLite operation under test has completed, the filesystem is reverted to the snapshot and random file damage is introduced that is characteristic of the kinds of damage one expects to see following a power loss. Then the database is opened and checks are made to ensure that it is well-formed and that the transaction either ran to completion or was completely rolled back. The interior of the loop is repeated multiple times for each snapshot with different random damage each time.
The test suites for SQLite also explore the result of stacking multiple failures. For example, tests are run to ensure correct behavior when an I/O error or OOM fault occurs while trying to recover from a prior crash.
Fuzz testing
seeks to establish that SQLite responds correctly to invalid, out-of-range, or malformed inputs.
SQL fuzz testing consists of creating syntactically correct yet wildly nonsensical SQL statements and feeding them to SQLite to see what it will do with them. Usually some kind of error is returned (such as “no such table”). Sometimes, purely by chance, the SQL statement also happens to be semantically correct. In that case, the resulting prepared statement is run to make sure it gives a reasonable result.
The concept of fuzz testing has been around for decades, but fuzz testing was not an effective way to find bugs until 2014 when Michal Zalewski invented the first practical profile-guided fuzzer,
American Fuzzy Lop or “AFL”. Unlike prior fuzzers that blindly generate random inputs, AFL instruments the program being tested (by modifying the assembly-language output from the C compiler) and uses that instrumentation to detect when an input causes the program to do something different - to follow a new control path or loop a different number of times. Inputs that provoke new behavior are retained and further mutated. In this way, AFL is able to “discover” new behaviors of the program under test, including behaviors that were never envisioned by the designers.
AFL proved adept at finding arcane bugs in SQLite. Most of the findings have been assert() statements where the conditional was false under obscure circumstances. But AFL has also found a fair number of crash bugs in SQLite, and even a few cases where SQLite computed incorrect results.
Because of its past success, AFL became a standard part of the testing strategy for SQLite beginning with version 3.8.10 (2015-05-07) until it was superseded by better fuzzers in version 3.29.0 (2019-07-10).
Beginning in 2016, a team of engineers at Google started the
OSS Fuzz project. OSS Fuzz uses a AFL-style guided fuzzer running on Google’s infrastructure. The Fuzzer automatically downloads the latest check-ins for participating projects, fuzzes them, and sends email to the developers reporting any problems. When a fix is checked in, the fuzzer automatically detects this and emails a confirmation to the developers.
SQLite is one of many open-source projects that OSS Fuzz tests. The
test/ossfuzz.c source file in the SQLite repository is SQLite’s interface to OSS fuzz.
OSS Fuzz no longer finds historical bugs in SQLite. But it is still running and does occasionally find issues in new development check-ins. Examples:
[1]
[2]
[3].
Beginning in late 2018, SQLite has been fuzzed using a proprietary fuzzer called “dbsqlfuzz”. Dbsqlfuzz is built using the
libFuzzer framework of LLVM.
The dbsqlfuzz fuzzer mutates both the SQL input and the database file at the same time. Dbsqlfuzz uses a custom
Structure-Aware Mutator
on a specialized input file that defines both an input database and SQL text to be run against that database. Because it mutates both the input database and the input SQL at the same time, dbsqlfuzz has been able to find some obscure faults in SQLite that were missed by prior fuzzers that mutated only SQL inputs or only the database file. The SQLite developers keep dbsqlfuzz running against trunk in about 16 cores at all times. Each instance of dbsqlfuzz program is able to evalutes about 400 test cases per second, meaning that about 500 million cases are checked every day.
The dbsqlfuzz fuzzer has been very successful at hardening the SQLite code base against malicious attack. Since dbsqlfuzz has been added to the SQLite internal test suite, bug reports from external fuzzers such as OSSFuzz have all but stopped.
Note that dbsqlfuzz is not the Protobuf-based structure-aware fuzzer for SQLite that is used by Chromium and described in the
Structure-Aware Mutator article. There is no connection between these two fuzzers, other than the fact that they are both based on libFuzzer
The Protobuf fuzzer for SQLite is written and maintained by the Chromium team at Google, whereas dbsqlfuzz is written and maintained by the original SQLite developers. Having multiple independently-developed fuzzers for SQLite is good, as it means that obscure issues are more likely to be uncovered.
Near the end of January 2024, a second libFuzzer-based tool called “jfuzz” came into use. Jfuzz generates corrupt JSONB blobs and feeds them into the JSON SQL functions to verify that the JSON functions are able to safely and efficiently deal with corrupt binary inputs.
SQLite seems to be a popular target for third-parties to fuzz. The developers hear about many attempts to fuzz SQLite and they do occasionally get bug reports found by independent fuzzers. All such reports are promptly fixed, so the product is improved and that the entire SQLite user community benefits. This mechanism of having many independent testers is similar to
Linus’s law: “given enough eyeballs, all bugs are shallow”.
One fuzzing researcher of particular note is
Manuel Rigger. Most fuzzers only look for assertion faults, crashes, undefined behavior (UB), or other easily detected anomalies. Dr. Rigger’s fuzzers, on the other hand, are able to find cases where SQLite computes an incorrect answer. Rigger has found
many such cases. Most of these finds are obscure corner cases involving type conversions and affinity transformations, and a good number of the finds are against unreleased features. Nevertheless, his finds are still important as they are real bugs, and the SQLite developers are grateful to be able to identify and fix the underlying problems.
Historical test cases from AFL, OSS Fuzz, and dbsqlfuzz are collected in a set of database files in the main SQLite source tree and then rerun by the “fuzzcheck” utility program whenever one runs “make test”. Fuzzcheck only runs a few thousand “interesting” cases out of the billions of cases that the various fuzzers have examined over the years. “Interesting” cases are cases that exhibit previously unseen behavior. Actual bugs found by fuzzers are always included among the interesting test cases, but most of the cases run by fuzzcheck were never actual bugs.
Fuzz testing and 100% MC/DC testing are in tension with one another. That is to say, code tested to 100% MC/DC will tend to be more vulnerable to problems found by fuzzing and code that performs well during fuzz testing will tend to have (much) less than 100% MC/DC. This is because MC/DC testing discourages defensive code with unreachable branches, but without defensive code, a fuzzer is more likely to find a path that causes problems. MC/DC testing seems to work well for building code that is robust during normal use, whereas fuzz testing is good for building code that is robust against malicious attack.
Of course, users would prefer code that is both robust in normal use and resistant to malicious attack. The SQLite developers are dedicated to providing that. The purpose of this section is merely to point out that doing both at the same time is difficult.
For much of its history SQLite has been focused on 100% MC/DC testing. Resistance to fuzzing attacks only became a concern with the introduction of AFL in 2014. For a while there, fuzzers were finding many problems in SQLite. In more recent years, the testing strategy of SQLite has evolved to place more emphasis on fuzz testing. We still maintain 100% MC/DC of the core SQLite code, but most testing CPU cycles are now devoted to fuzzing.
While fuzz testing and 100% MC/DC testing are in tension, they are not completely at cross-purposes. The fact that the SQlite test suite does test to 100% MC/DC means that when fuzzers do find problems, those problems can be fixed quickly and with little risk of introducing new errors.
There are numerous test cases that verify that SQLite is able to deal with malformed database files. These tests first build a well-formed database file, then add corruption by changing one or more bytes in the file by some means other than SQLite. Then SQLite is used to read the database. In some cases, the bytes changes are in the middle of data. This causes the content of the database to change while keeping the database well-formed. In other cases, unused bytes of the file are modified, which has no effect on the integrity of the database. The interesting cases are when bytes of the file that define database structure get changed. The malformed database tests verify that SQLite finds the file format errors and reports them using the SQLITE_CORRUPT return code without overflowing buffers, dereferencing NULL pointers, or performing other unwholesome actions.
The dbsqlfuzz fuzzer also does an excellent job of verifying that SQLite responds sanely to malformed database files.
SQLite defines certain limits on its operation, such as the maximum number of columns in a table, the maximum length of an SQL statement, or the maximum value of an integer. The TCL and TH3 test suites both contains numerous tests that push SQLite right to the edge of its defined limits and verify that it performs correctly for all allowed values. Additional tests go beyond the defined limits and verify that SQLite correctly returns errors. The source code contains testcase macros to verify that both sides of each boundary have been tested.
Whenever a bug is reported against SQLite, that bug is not considered fixed until new test cases that would exhibit the bug have been added to either the TCL or TH3 test suites. Over the years, this has resulted in thousands and thousands of new tests. These regression tests ensure that bugs that have been fixed in the past are not reintroduced into future versions of SQLite.
Resource leak occurs when system resources are allocated and never freed. The most troublesome resource leaks in many applications are memory leaks - when memory is allocated using malloc() but never released using free(). But other kinds of resources can also be leaked: file descriptors, threads, mutexes, etc.
Both the TCL and TH3 test harnesses automatically track system resources and report resource leaks on every test run. No special configuration or setup is required. The test harnesses are especially vigilant with regard to memory leaks. If a change causes a memory leak, the test harnesses will recognize this quickly. SQLite is designed to never leak memory, even after an exception such as an OOM error or disk I/O error. The test harnesses are zealous to enforce this.
The SQLite core, including the unix VFS, has 100% branch test coverage under TH3 in its default configuration as measured by
gcov. Extensions such as FTS3 and RTree are excluded from this analysis.
There are many ways to measure test coverage. The most popular metric is “statement coverage”. When you hear someone say that their program as “XX% test coverage” without further explanation, they usually mean statement coverage. Statement coverage measures what percentage of lines of code are executed at least once by the test suite.
Branch coverage is more rigorous than statement coverage. Branch coverage measures the number of machine-code branch instructions that are evaluated at least once on both directions.
To illustrate the difference between statement coverage and branch coverage, consider the following hypothetical line of C code:
Such a line of C code might generate a dozen separate machine code instructions. If any one of those instructions is ever evaluated, then we say that the statement has been tested. So, for example, it might be the case that the conditional expression is always false and the “d” variable is never incremented. Even so, statement coverage counts this line of code as having been tested.
Branch coverage is more strict. With branch coverage, each test and each subblock within the statement is considered separately. In order to achieve 100% branch coverage in the example above, there must be at least three test cases:
Any one of the above test cases would provide 100% statement coverage but all three are required for 100% branch coverage. Generally speaking, 100% branch coverage implies 100% statement coverage, but the converse is not true. To reemphasize, the
TH3 test harness for SQLite provides the stronger form of test coverage - 100% branch test coverage.
A well-written C program will typically contain some defensive conditionals which in practice are always true or always false. This leads to a programming dilemma: Does one remove defensive code in order to obtain 100% branch coverage?
In SQLite, the answer to the previous question is “no”. For testing purposes, the SQLite source code defines macros called ALWAYS() and NEVER(). The ALWAYS() macro surrounds conditions which are expected to always evaluate as true and NEVER() surrounds conditions that are always evaluated to false. These macros serve as comments to indicate that the conditions are defensive code. In release builds, these macros are pass-throughs:
During most testing, however, these macros will throw an assertion fault if their argument does not have the expected truth value. This alerts the developers quickly to incorrect design assumptions.
When measuring test coverage, these macros are defined to be constant truth values so that they do not generate assembly language branch instructions, and hence do not come into play when calculating the branch coverage:
The test suite is designed to be run three times, once for each of the ALWAYS() and NEVER() definitions shown above. All three test runs should yield exactly the same result. There is a run-time test using the sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, …) interface that can be used to verify that the macros are correctly set to the first form (the pass-through form) for deployment.
Another macro used in conjunction with test coverage measurement is the macro. The argument is a condition for which we want test cases that evaluate to both true and false. In non-coverage builds (that is to say, in release builds) the
macro is a no-op:
But in a coverage measuring build, the macro generates code that evaluates the conditional expression in its argument. Then during analysis, a check is made to ensure tests exist that evaluate the conditional to both true and false. macros are used, for example, to help verify that boundary values are tested. For example:
...
Read the original on sqlite.org »
I got hacked, my server started mining Monero this morning.
Edit: A few people on HN have pointed out that this article sounds a little LLM generated. That’s because it’s largely a transcript of me panicking and talking to Claude. Sorry if it reads poorly, the incident really happened though!
Or: How I learned that “I don’t use Next.js” doesn’t mean your dependencies don’t use Next.js
I woke up to this beauty from Hetzner:
We have indications that there was an attack from your server. Please take all necessary measures to avoid this in the future and to solve the issue.
We also request that you send a short response to us. This response should contain information about how this could have happened and what you intend to do about it. In the event that the following steps are not completed successfully, your server can be blocked at any time after the 2025-12-17 12:46:15 +0100.
Attached was evidence of network scanning from my server to some IP range in Thailand. Great. Nothing says “good morning” like an abuse report and the threat of getting your infrastructure shut down in 4 hours.
Background: I run a Hetzner server with Coolify. It runs all my stuff, like my little corner of the internet:
First thing I did was SSH in and check the load average:
For context, my load average is normally around 0.5-1.0. Fifteen is “something is very wrong.”
I ran ps aux to see what was eating my CPU:
819% CPU usage. On a process called javae running from /tmp/.XIN-unix/. And multiple xmrig processes - that’s literally cryptocurrency mining software (Monero, specifically).
I’d been mining cryptocurrency for someone since December 7th. For ten days. Brilliant.
My first thought was “I’m completely fucked.” Cryptominers on the host, running for over a week - time to nuke everything from orbit and rebuild, right?
But then I noticed something interesting. All these processes were running as user 1001. Not root. Not a system user. UID 1001.
Let me check what’s actually running:
I’ve got about 20 containers running via Coolify (my self-hosted PaaS). Inventronix (my IoT platform), some monitoring stuff, Grafana, a few experiments.
And Umami - a privacy-focused analytics tool I’d re-deployed 9 days ago to track traffic on my blog.
Let me check which container has user 1001:
There it is. Container a42f72cb1bc5 - that’s my Umami analytics container. And it’s got a whole xmrig-6.24.0
directory sitting in what should be Next.js server internals.
The mining command in the process list confirmed it:
Someone had exploited my analytics container and was mining Monero using my CPU. Nice.
Here’s the kicker. A few days ago I saw a Reddit post about a critical Next.js/Puppeteer RCE vulnerability ( CVE-2025-66478). My immediate reaction was “lol who cares, I don’t run Next.js.”
Except… Umami is built with Next.js. I did not know this, nor did I bother looking. Oops.
The vulnerability (CVE-2025-66478) was in Next.js’s React Server Components deserialization. The “Flight” protocol that RSC uses to serialize/deserialize data between client and server had an unsafe deserialization flaw. An attacker could send a specially crafted HTTP request with a malicious payload to any App Router endpoint, and when deserialized, it would execute arbitrary code on the server.
No Puppeteer involved - just broken deserialization in the RSC protocol itself. The attack flow:
So much for “I don’t use Next.js.”
The Panic: Has It Escaped the Container?
This is where I started to properly panic. Looking at that process list:
That path - /tmp/.XIN-unix/javae - looks like it’s on the host filesystem, not inside a container. If the malware had escaped the container onto my actual server, I’d need to:
1
2
3
4
5
$ crontab -l
no crontab for root
$ systemctl list-unit-files | grep enabled
# … all legitimate system services, nothing suspicious
No malicious cron jobs. No fake systemd services pretending to be nginxs or apaches (common trick to blend in). That’s… good?
But I still needed to know: Did the malware actually escape the container or not?
Here’s the test. If /tmp/.XIN-unix/javae exists on my host, I’m fucked. If it doesn’t exist, then what I’m seeing is just Docker’s default behavior of showing container processes in the host’s ps output, but they’re actually isolated.
1
2
$ ls -la /tmp/.XIN-unix/javae
ls: cannot access ‘/tmp/.XIN-unix/javae’: No such file or directory
The malware was entirely contained within the Umami container. When you run ps aux on a Docker host, you see processes from all containers because they share the same kernel. But those processes are in their own mount namespace - they can’t see or touch the host filesystem.
Let me verify what user that container was actually running as:
This is why I’m not fucked:
The malware could NOT:
Why This Matters: Dockerfiles vs. Auto-Generated Images
Here’s the thing that saved me. I write my own Dockerfiles for my applications. I don’t use auto-generation tools like Nixpacks (which Coolify supports) that default to USER root in containers.
The Reddit post I’d seen earlier? That guy got completely owned because his container was running as root. The malware could:
Write anywhere on the filesystem
His fix required a full server rebuild because he couldn’t trust anything anymore. Mine required… deleting a container.
What I did not do, was keep track of the tolling I was using and what tooling that was using. In fact, I installed Umami from Coolify’s services screen. I didn’t even configure it.
Obviously none of this is Umami’s fault by the way. They released a fix for their free software like a week ago. I just didn’t think to do anything about it.
1
2
3
4
5
6
7
# Stop and remove the compromised container
$ docker stop umami-bkc4kkss848cc4kw4gkw8s44
$ docker rm umami-bkc4kkss848cc4kw4gkw8s44
# Check CPU usage
$ uptime
08:45:17 up 55 days, 17:43, 1 user, load average: 0.52, 1.24, 4.83
CPU back to normal. All those cryptomining processes? Gone. They only existed inside the container.
I also enabled UFW (which I should have done ages ago):
1
2
3
4
5
6
$ sudo ufw default deny incoming
$ sudo ufw default allow outgoing
$ sudo ufw allow ssh
$ sudo ufw allow 80/tcp
$ sudo ufw allow 443/tcp
$ sudo ufw enable
This blocks all inbound connections except SSH, HTTP, and HTTPS. No more exposed PostgreSQL ports, no more RabbitMQ ports open to the internet.
The container ran as non-root user with no privileged access or host mounts, so the compromise was fully contained. Container has been removed and firewall hardened.
They closed the ticket within an hour.
1. “I don’t use X” doesn’t mean your dependencies don’t use X
I don’t write Next.js applications. But I run third-party tools that are built with Next.js. When CVE-2025-66478 was disclosed, I thought “not my problem.” Wrong.
Know what your dependencies are actually built with. That “simple analytics tool” is a full web application with a complex stack.
This could have been so much worse. If that container had been running as root, or had volume mounts to sensitive directories, or had access to the Docker socket, I’d be writing a very different blog post about rebuilding my entire infrastructure.
Instead, I deleted one container and moved on with my day.
Write your own Dockerfiles. Understand what user your processes run as. Avoid USER root unless you have a very good reason. Don’t mount volumes you don’t need. Don’t give containers –privileged access.
This malware wasn’t like those people who auto-poll for /wpadmin every time I make a DNS change. This was spicy.
Used process names that blend in (javae, runnv)
According to other reports, even had “killer scripts” to murder competing miners
But it was still limited by container isolation. Good security practices beat sophisticated malware.
Even though the container isolation held, I still should have:
Had a firewall enabled from day one (not “I’ll do it later”)
...
Read the original on blog.jakesaunders.dev »
Everyone’s using AI wrong. Including me, until last month.
We ask AI to write emails, generate reports, create content. But that’s like using a supercomputer as a typewriter. The real breakthrough happened when I flipped my entire approach.
Here’s how most people use AI:
Makes sense. These tasks save time. But they’re thinking too small.
My Obsidian vault contains: → 3 years of daily engineering notes → 500+ meeting reflections → Thousands of fleeting observations about building software → Every book highlight and conference insight I’ve captured
No human could read all of this in a lifetime. AI consumes it in seconds.
Last month I connected my Obsidian vault to AI. The questions changed completely:
Instead of “Write me something new” I ask “What have I already discovered?”
“What patterns emerge from my last 50 one-on-ones?”
AI found that performance issues always preceded tool complaints by 2-3 weeks. I’d never connected those dots.
“How has my thinking about technical debt evolved?”
Turns out I went from seeing it as “things to fix” to “information about system evolution” around March 2023. Forgotten paradigm shift.
“Find connections between Buffer’s API design and my carpeta.app architecture”
Surfaced 12 design decisions I’m unconsciously repeating. Some good. Some I need to rethink.
Every meeting, every shower thought, every debugging session teaches you something. But that knowledge is worthless if you can’t retrieve it.
Traditional search fails because you need to remember exact words. Your brain fails because it wasn’t designed to store everything.
AI changes the retrieval game: → Query by concept, not keywords → Find patterns across years, not just documents → Connect ideas that were separated by time and context
The constraint was never writing. Humans are already good at creating when they have the right inputs.
The constraint was always consumption. Reading everything. Remembering everything. Connecting everything.
Everything goes into Obsidian (meetings, thoughts, reflections)
AI has access to the entire vault
I query my past self like a research assistant
But the magic isn’t in the tools. It’s in the mindset shift.
Stop thinking of AI as a creator. Start thinking of it as the ultimate reader of your experience.
Every note becomes a future insight. Every reflection becomes searchable wisdom. Every random observation might be the missing piece for tomorrow’s problem.
After two months of this approach:
→ I solve problems faster by finding similar past situations → I make better decisions by accessing forgotten context → I see patterns that were invisible when scattered across time
Your experience is your competitive advantage. But only if you can access it.
Most people are sitting on goldmines of insight, locked away in notebooks, random files, and fading memories. AI turns that locked vault into a queryable database of your own expertise.
We’re still thinking about AI like it’s 2023. Writing assistants. Code generators. Content creators.
The real revolution is AI as the reader of everything you’ve ever thought.
And that changes everything about how we should capture knowledge today.
Start documenting. Not for others. For your future self and the AI that will help you remember what you’ve forgotten you know.
This piece originally appeared in my weekly newsletter. Subscribe for insights on thinking differently about work, technology, and what’s actually possible.
...
Read the original on msanroman.io »
Doublespeed, a startup backed by Andreessen Horowitz (a16z) that uses a phone farm to manage at least hundreds of AI-generated social media accounts and promote products has been hacked. The hack reveals what products the AI-generated accounts are promoting, often without the required disclosure that these are advertisements, and allowed the hacker to take control of more than 1,000 smartphones that power the company.
The hacker, who asked for anonymity because he feared retaliation from the company, said he reported the vulnerability to Doublespeed on October 31. At the time of writing, the hacker said he still has access to the company’s backend, including the phone farm itself. Doublespeed did not respond to a request for comment.
...
Read the original on www.404media.co »
Demonstration that natural bacteria isolated from amphibian and reptile intestines achieve complete tumor elimination with single administration
Combines direct bacterial killing of cancer cells with immune system activation for comprehensive tumor destruction
Outperforms existing chemotherapy and immunotherapy with no adverse effects on normal tissues
Expected applications across diverse solid tumor types, opening new avenues for cancer treatment
A research team of Prof. Eijiro Miyako at the Japan Advanced Institute of Science and Technology (JAIST) has discovered that the bacterium Ewingella americana, isolated from the intestines of Japanese tree frogs (Dryophytes japonicus), possesses remarkably potent anticancer activity. This groundbreaking research has been published in the international journal Gut Microbes.
While the relationship between gut microbiota and cancer has attracted considerable attention in recent years, most approaches have focused on indirect methods such as microbiome modulation or fecal microbiota transplantation. In contrast, this study takes a completely different approach: isolating, culturing, and directly administering individual bacterial strains intravenously to attack tumors–- representing an innovative therapeutic strategy.
The research team isolated a total of 45 bacterial strains from the intestines of Japanese tree frogs, Japanese fire belly newts (Cynops pyrrhogaster), and Japanese grass lizards (Takydromus tachydromoides). Through systematic screening, nine strains demonstrated antitumor effects, with E. americana exhibiting the most exceptional therapeutic efficacy.
Remarkable Therapeutic Efficacy
In a mouse colorectal cancer model, a single intravenous administration of E. americana achieved complete tumor elimination with a 100% complete response (CR) rate. This dramatically surpasses the therapeutic efficacy of current standard treatments, including immune checkpoint inhibitors (anti-PD-L1 antibody) and liposomal doxorubicin (chemotherapy agent) (Figure 1).
Figure 1. Anticancer efficacy: Ewingella americana versus conventional therapies. Tumor response: single i.v. dose of E. americana (200 µL, 5 × 10⁹ CFU/mL); four doses of doxorubicin or anti-PD-L1 (200 µL, 2.5 mg/kg per dose); PBS as control. Data: mean ± SEM (n = 5). ****, p < 0.0001 (Student’s two-sided t-test).
Direct Cytotoxic Effect: As a facultative anaerobic bacterium, E. americana selectively accumulates in the hypoxic tumor microenvironment and directly destroys cancer cells. Bacterial counts within tumors increase approximately 3,000-fold within 24 hours post-administration, efficiently attacking tumor tissue.
Immune Activation Effect: The bacterial presence powerfully stimulates the immune system, recruiting T cells, B cells, and neutrophils to the tumor site. Pro-inflammatory cytokines (TNF-α, IFN-γ) produced by these immune cells further amplify immune responses and induce cancer cell apoptosis.
E. americana selectively accumulates in tumor tissues with zero colonization in normal organs. This remarkable tumor specificity arises from multiple synergistic mechanisms:
Zero bacterial colonization in normal organs including liver, spleen, lung, kidney, and heart
This research has established proof-of-concept for a novel cancer therapy using natural bacteria. Future research and development will focus on:
Expansion to Other Cancer Types: Efficacy validation in breast cancer, pancreatic cancer, melanoma, and other malignancies
Optimization of Administration Methods: Development of safer and more effective delivery approaches including dose fractionation and intratumoral injection
Combination Therapy Development: Investigation of synergistic effects with existing immunotherapy and chemotherapy
This research demonstrates that unexplored biodiversity represents a treasure trove for novel medical technology development and holds promise for providing new therapeutic options for patients with refractory cancers.
Facultative Anaerobic Bacteria: Bacteria capable of growing in both oxygen-rich and oxygen-depleted environments, enabling selective proliferation in hypoxic tumor regions.
Complete Response (CR): Complete tumor elimination confirmed by diagnostic examination following treatment.
Immune Checkpoint Inhibitor: Drugs that release cancer cell-mediated immune suppression, enabling T cells to attack cancer cells.
CD47: A cell surface protein that emits “don’t eat me” signals; cancer cells overexpress this to evade immune attack.
Discovery and characterization of antitumor gut microbiota from amphibians and reptiles: Ewingella americana as a novel therapeutic agent with dual cytotoxic and immunomodulatory properties
This research was supported by:
Japan Society for the Promotion of Science (JSPS) KAKENHI Grant-in-Aid for Scientific Research (A) (Grant No. 23H00551)
Japan Science and Technology Agency (JST) Program for Co-creating Startup Ecosystem (Grant No. JPMJSF2318)
...
Read the original on www.jaist.ac.jp »
It’s now late into 2025, and just over a year since I wrote my last post on Passkeys. The prevailing dialogue that I see from thought leaders is “addressing common misconceptions” around Passkeys, the implication being that “you just don’t understand it correctly” if you have doubts. Clearly I don’t understand Passkeys in that case.
And yet, I am here to once again say - yep, it’s 2025 and Passkeys still have all the issues I’ve mentioned before, and a few new ones I’ve learnt! Let’s round up the year together then.
* Passkeys have flaws - learn about them and use them on your terms. Don’t write them off wholesale based on this blog. I, the author of this blog, use Passkeys!!!
* DO engage with and learn about Credential Managers (aka Password Managers). This is where the Passkey is stored.
* DO use a Credential Manager you control and can backup. I recommend Bitwarden or Vaultwarden which allow backups to be taken easily.
* AVOID using a platform (Apple, Google) Credential Manager as your only Passkey repository - these can’t easily backed up and you CAN be locked out permanently.
IF you use a platform Passkey manager, frequently sync it with FIDO Credential Exchange to an external Credential Manager you can backup/control.
OR use both the platform Passkey manager AND a Credential Manager you control in parallel.
* IF you use a platform Passkey manager, frequently sync it with FIDO Credential Exchange to an external Credential Manager you can backup/control.
* OR use both the platform Passkey manager AND a Credential Manager you control in parallel.
* For high value accounts such as email which are on the account recovery path
DO use Yubikeys for your email account as the Passkey store.
DO keep strong machine generated passwords + TOTP in your Credential Managers as alternatives to Passkeys for your email accounts.
* DO use Yubikeys for your email account as the Passkey store.
* DO keep strong machine generated passwords + TOTP in your Credential Managers as alternatives to Passkeys for your email accounts.
* DO a thought experiment - if I lost access to my Credential Manager what is the recovery path? Ensure you can rebuild from disaster.
The major change in the last 12 months has been the introduction of the
FIDO Credential Exchange Specification.
Most people within the tech community who have dismissed my claim that “Passkeys are a form of vendor lockin” are now pointing at this specification as proof that this claim is now wrong.
“See! Look! You can export your credentials to another Passkey provider if you want! We aren’t locking you in!!!”
I have to agree - this is great if you want to change which walled-garden you live inside. However it doesn’t assist with the day to day usage of Passkeys when you have devices from different vendor ecosystems. Nor does it make it easier for me to use a Passkey provider outside of my vendors platform provider.
Example: Let’s say that I have an Windows Desktop and a Macbook Pro - I can sign up a Passkey on the Macbook Pro but I can’t then use it on the Windows Desktop.
FIDO Credential Exchange
lets me copy from Apple’s Keychain to whatever provider I use on the Windows machine. But now I have to do that exchange every time I enrol a new Passkey. Similar I would need to do the reverse from Windows to Mac every time that I sign up on the Windows machine.
So day to day, this changes very little - but if I want to go from “all in on Apple” to “all in on Google” then I can do a big-bang migration and jump from once garden to the next. But if you have mixed device ecosystems (like uhhh … you know. Most of the world does) then very little will change for you with this.
But if I use my own Credential Manager (e.g. Vaultwarden) then I can happily work between multiple ecosystems.
Today I saw this excellent quote in the context of why Passkeys are better than Password+TOTP in a Password Manager:
Individuals having to learn to use password management software and be vigilant against phishing is an industry failure, not a personal success.
Even giving as much benefit of the doubt to this statement, and that the “and” might be load bearing we have to ask - Where are passkeys stored?
So we still have to teach individuals about password (credential) managers, and how Passkeys work so that people trust them. That fundamental truth hasn’t changed.
But not only this - if a person is choosing a password+TOTP over a Passkey, we have to ask “why is that”? Do we think that it’s truly about arrogance? Do we think that this user believes they are more important? Or is there and underlying usability issue at play? Why might we be recommending this to others? Do we really think that Passkeys come without a need of education?
Maybe I’m fundamentally missing the original point of this comment. Maybe I am completely misinterpretting it. But I still think we need to say if a person chooses password and TOTP over a Passkey even once they are informed of the choices, then Passkeys have failed that user. What could we have done better?
Perhaps one could interpret this statement as you don’t need to teach users about Passkeys if they are using their ✨ m a g i c a l ✨ platform Passkey manager since it’s so much nicer than a password and TOTP. And that leads to …
In economics, vendor lock-in, […] makes a customer dependent on a vendor for products, unable to use another vendor without substantial switching costs.
See, the big issue that the thought leaders seem to get wrong is that they believe that if you can use FIDO Credential Exchange, then you aren’t locked in because you can move between Passkey providers.
But if we aren’t teaching our users about credential management, didn’t we just silently lock them into to our platform Passkey manager?
Not only that, when you try to go against the platform manager, it’s the continual friction at each stage of the users experience. It makes the cost to switch high because at each point you encounter friction if you deviate from the vendors intended paths.
For example, consider the Apple Passkey modal:
The majority of this modal is dedicated to “you should make a Passkey in your Apple Keychain”. If you want to use your Android phone or a Security Key, where would I click? Oh yes, Other Options.
Make buttons easy for people to use. It’s essential to include enough space around a button so that people can visually distinguish it from surrounding components and content. Giving a button enough space is also critical for helping people select or activate it, regardless of the method of input they use.
When you select Other Options this is what you see - see how Touch ID is still the default, despite the fact that I already indicated I don’t want to use it by selecting Other Options? At this point I would need to select Security Key and then click again to use my key. Similar for Android Phone.
And guess what - my preferences and choices are never remembered. I guess it’s true what they say.
Google Chrome has a similar set of Modals and nudges (though props to Chrome, they at least implicitly
activate your security key from the first modal so a power user who knows the trick can use it). So they are just as bad here IMO.
This is what I mean by “vendor lockin”. It’s not just about where the private keys are stored. It’s the continual friction at each step of the interaction when you deviate from the vendors intended path. It’s about making it so annoying to use anything else that you settle into one vendors ecosystem. It’s about the lack of communication about where Passkeys are stored that tricks users into settling into their vendor ecosystem. That’s vendor lock-in.
We still get reports of people losing Passkeys from Apple Keychain. We similarly get reports of Android phones that one day just stop creating new Passkeys, or stop being able to use existing ones. One
exceptional story we saw recently was of an Android device that stopped using it’s onboard Passkeys and also stopped accepting NFC key. USB CTAP would still function, and all the historical fixes we’ve seen (such as full device resets) would not work. So now what? I’m not sure of the outcome of this story, but my assumption is there was not a happy ending.
If someone ends up locked out of their accounts because their Passkeys got nuked silently, what are we meant to do to help them?
Dr Paris Buttfield-Addison was locked out of their Apple account.
I recommend you read the post, but the side effect - every Passkey they had in an Apple keychain is now unrecoverable.
There is just as much evidence about the same practices with Google / Android.
I honestly don’t think I have to say much else, this is terrifying that every account you own could be destroyed by a single action where you have no recourse.
We still have issues where services that are embracing Passkeys are communicating badly about them. The gold standard of miscommunication came to me a few months ago infact (2025-10-29) when a company emailed me this statement:
Passkeys use your unique features — known as biometrics — like your facial features, your fingerprint or a PIN to let us know that it’s really you. They provide increased security because unlike a password or username, they can’t be shared with anyone, making them phishing resistant.
As someone who is deeply aware of how webauthn works I know that my facial features or fingerprint never really leave my device. However asking my partner (context: my partner is a veternary surgeon, and so I feel justified in claiming that she is a very intelligent and educated woman) to read this, her interpretation was:
So this means a Passkey sends my face or fingerprint over the internet for the service to verify? Is that also why they believe it is phishing resistant because you can’t clone my face or my fingerprint?
This is a smart, educated person, with the title of doctor, and even she is concluding that Passkeys are sending biometrics over the internet. What are people in other disciplines going to think? What about people with a cognitive impairment or who not have access to education about Passkeys?
This kind of messaging that leads people to believe we are sending personal physical features over the internet is harmful because most people will not want to send these data to a remote service. This completely undermines the trust in Passkeys because we are establishing to people that they are personally invasive in a way that username and passwords are not!
And guess what - platform Passkey provider modals/dialogs don’t do anything to counter this information and often leave users with the same feeling.
A past complaint was that I had encountered services that only accepted a single Passkey as they assumed you would use a synchronised cloud keychain of some kind. In 2025 I still see a handful of these services, but mostly the large problem sites have now finally allowed you to enrol multiple Passkeys.
But that doesn’t stop sites pulling tricks on you.
I’ve encountered multiple sites that now use authenticatorAttachment options to force you to use a platform bound Passkey. In other words, they force you into Google or Apple. No password manager, no security key, no choices.
I won’t claim this one as an attempt at “vendor lockin” by the big players, but it is a reflection of what developers believe a Passkey to be - they believe it means a private key stored in one of those vendors devices, and nothing else. So much of this comes from the confused historical origins of Passkeys and we aren’t doing anything to change it.
When I have confronted these sites about the mispractice, they pretty much shrugged and said “well no one else has complained so meh”. Guess I won’t be enrolling a Passkey with you then.
One other site that pulled this said “instead of selecting continue, select this other option and you get the authenticatorAttachment=cross-platform setting. Except that they could literally do
nothing with authenticatorAttachment and leave it up to the platform modals allowing me the choice (and fewer friction burns) of choosing where I want to enrol my Passkey.
Another very naughty website attempts to enroll a Passkey on your device with no prior warning or consent when you login, which is very surprising to anyone and seems very deceptive as a practice. Ironically same vendor doesn’t use your passkey when you go to sign in again anyway.
But it’s not all doom and gloom.
Most of the issues are around platform Passkey providers like Apple or Google.
The best thing you can do as a user, and for anyone in your life you want to help, is to be educated about Credential Managers. Regardless of Passwords, TOTP, Passkeys or anything else, empowering people to manage and think about their online security via a Credential Manager they feel they control and understand is critical - not an “industry failure”.
Using a Credential Manager that you have control over shields you from the account lockout and platform blow-up risks that exist with platform Passkeys. Additionally most Credential Managers will allow you to backup your credentials too. It can be a great idea to do this every few months and put the content onto a USB drive in a safe location.
If you do choose to use a platform Passkey provider, you can “emulate” this backup ability by using the credential export function to another Passkey provider, and then do the backups from there.
You can also use a Yubikey as a Credential Manager if you want - modern keys (firmware version 5.7 and greater) can store up to 150 Passkeys on them, so you could consider skipping software Credential Managers entirely for some accounts.
The most critical accounts you own though need some special care. Email is one of those - email generally is the path by which all other credential resets and account recovery flows occur. This means losing your email access is the most devastating loss as anything else could potentially be recovered.
For email, this is why I recommend using hardware security keys (yubikeys are the gold standard here) if you want Passkeys to protect your email. Always keep a strong password and TOTP as an extra recovery path, but don’t use it day to day since it can be phished. Ensure these details are physically secure and backed up - again a USB drive or even a print out on paper in a safe and secure location so that you can “bootstrap your accounts” in the case of a major failure.
If you are an Apple or Google employee - change your dialogs to allow remembering choices the user has previously made on sites, or wholesale allow skipping some parts - for example I want to skip straight to Security Key, and maybe I’ll choose to go back for something else. But let me make that choice. Similar, make the choice to use different Passkey providers a first-class citizen in the UI, not just a tiny text afterthought.
If you are a developer deploying Passkeys, then don’t use any of the pre-filtering Webauthn options or javascript API’s. Just leave it to the users platform modals to let the person choose. If you want people to enroll a passkey on sign in, communicate that before you attempt the enrolment. Remember kids, consent is paramount.
But of course - maybe I just “don’t understand Passkeys correctly”. I am but an underachiving white man on the internet after all.
...
Read the original on fy.blackhats.net.au »
To add this web app to your iOS home screen tap the share button and select "Add to the Home Screen".
10HN is also available as an iOS App
If you visit 10HN only rarely, check out the the best articles from the past week.
If you like 10HN please leave feedback and share
Visit pancik.com for more.