<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: RC</title>
    <description>The latest articles on DEV Community by RC (@randomchaos).</description>
    <link>https://dev.to/randomchaos</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3888972%2F5343f536-62c9-4a99-8876-4ba9cde038ef.png</url>
      <title>DEV Community: RC</title>
      <link>https://dev.to/randomchaos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/randomchaos"/>
    <language>en</language>
    <item>
      <title>Rust solved the compatibility trap with editions</title>
      <dc:creator>RC</dc:creator>
      <pubDate>Tue, 27 Oct 2026 22:25:32 +0000</pubDate>
      <link>https://dev.to/randomchaos/rust-solved-the-compatibility-trap-with-editions-1goi</link>
      <guid>https://dev.to/randomchaos/rust-solved-the-compatibility-trap-with-editions-1goi</guid>
      <description>&lt;p&gt;Delete a user from a stock SQLite database, forget to delete their posts, and nothing complains. Insert a new user afterward and, because SQLite recycles ROWIDs, that account can take the integer ID the deleted user held. The orphaned posts then join cleanly to the new account. The author's example runs it end to end: Bob writes "Hello, I am Bob" and deletes his account, Alice signs up and gets Bob's recycled ID, and a join across the users and posts tables returns "Alice | Hello, I am Bob." No error fires at any step.&lt;/p&gt;

&lt;p&gt;The cause is the first of several SQLite defaults the author argues are simply wrong: foreign key constraints are ignored unless you enable them with &lt;code&gt;PRAGMA foreign_keys = ON&lt;/code&gt;. As far as the author knows, SQLite is the only RDBMS that doesn't enforce them out of the box. With the pragma on, that stray &lt;code&gt;DELETE&lt;/code&gt; fails with "FOREIGN KEY constraint failed (19)" instead of quietly corrupting the join.&lt;/p&gt;

&lt;p&gt;Type affinity is the second. A column declared INTEGER isn't restricted to integers. SQLite stores a valid numeric string as a number and leaves anything else as-is, so an INTEGER column accepts the text 'Way too long, I mean come on' and keeps it verbatim. The author once cleaned up a project where code had written the strings '1' and '0' into a column meant to hold the integers 1 and 0. STRICT tables turn the mismatch into "cannot store TEXT value in INTEGER column" at insert time, and the ANY type still covers a column that should genuinely hold any value. There is no pragma to make every table strict, so you tag each &lt;code&gt;CREATE TABLE&lt;/code&gt; by hand.&lt;/p&gt;

&lt;p&gt;Third is concurrency. SQLite allows many readers but one writer, and by default a second process reaching for the write lock gets an immediate &lt;code&gt;SQLITE_BUSY&lt;/code&gt; instead of waiting. The author traces real-world bugs to this default, systems that would sometimes just crash, and wrote retry loops by hand to work around it. &lt;code&gt;PRAGMA busy_timeout = 5000&lt;/code&gt; makes the writer wait up to five seconds for the lock first. Concurrent writers are never fast, but interactive cleanup with the &lt;code&gt;sqlite3&lt;/code&gt; tool or an occasional admin script shouldn't be able to crash the main process by colliding with it.&lt;/p&gt;

&lt;p&gt;Fourth is performance, where the big one is that the write-ahead log is off by default. &lt;code&gt;PRAGMA journal_mode = WAL&lt;/code&gt; gives a large write speed-up in most cases, and &lt;code&gt;PRAGMA synchronous = NORMAL&lt;/code&gt; cuts disk syncs further without risking corruption under WAL.&lt;/p&gt;

&lt;p&gt;Each of these has a one-line fix, and the reason usually cited for why they stay wrong by default is backwards compatibility. Flip a default and you break software that quietly relied on the old behaviour, and you teach people to fear upgrading the library at all. The author draws the parallel to being afraid to upgrade Python because every upgrade breaks something. Not breaking your dependents is a real and uncommon virtue, which is also what keeps SQLite stuck. Until that changes, you apply it yourself: enable the settings with their pragmas and add STRICT to every table.&lt;/p&gt;

&lt;p&gt;Rust's editions are the escape the author proposes. A single opt-in pragma would set a whole generation of defaults at once. The sketch is &lt;code&gt;PRAGMA edition = 2026&lt;/code&gt;, standing in for &lt;code&gt;foreign_keys = ON&lt;/code&gt;, &lt;code&gt;busy_timeout = 5000&lt;/code&gt;, &lt;code&gt;journal_mode = WAL&lt;/code&gt;, and &lt;code&gt;synchronous = NORMAL&lt;/code&gt;, plus strict tables as the default. A database that never sets an edition keeps today's behaviour, so nothing breaks; new code opts into the sane set in one line.&lt;/p&gt;

&lt;p&gt;The year in the name does real work. The author takes it straight from Rust editions and prefers it to a flat switch like JavaScript's &lt;code&gt;"use strict"&lt;/code&gt; because sensible defaults shift over time. If Hctree's WAL2 reaches the main branch around 2034, &lt;code&gt;PRAGMA edition = 2034&lt;/code&gt; could set &lt;code&gt;journal_mode = WAL2&lt;/code&gt; while &lt;code&gt;edition = 2026&lt;/code&gt; stays on plain WAL. Each edition is a snapshot of what good defaults looked like that year, and code records which snapshot it was written against.&lt;/p&gt;

&lt;p&gt;Making strict tables the default would cost one genuinely useful quirk, which the lobste.rs user 'zie' raised. Non-strict SQLite decides a column's affinity from substrings in the declared type: anything containing "INT" gets INTEGER affinity, "CHAR", "CLOB" or "TEXT" gets TEXT affinity, and so on. That lets you invent type names like DATETIME, KEY_VALUE_SET or COLOR and have a connector read them back to serialize and deserialize the column, or just use them as documentation. Strict tables drop that. The author's answer is type aliases, something like &lt;code&gt;CREATE TYPE KEY_VALUE_SET = TEXT&lt;/code&gt; usable inside a strict table. As the lobste.rs user 'masklinn' pointed out, SQL 99 already specifies exactly this as &lt;code&gt;CREATE DOMAIN&lt;/code&gt;, constraints included, so SQLite wouldn't have to invent anything, only implement the standard statement.&lt;/p&gt;

</description>
      <category>sqlite</category>
      <category>rust</category>
      <category>database</category>
    </item>
    <item>
      <title>Microsoft pushed an emergency .NET patch Sunday</title>
      <dc:creator>RC</dc:creator>
      <pubDate>Tue, 27 Oct 2026 06:25:17 +0000</pubDate>
      <link>https://dev.to/randomchaos/microsoft-pushed-an-emergency-net-patch-sunday-407d</link>
      <guid>https://dev.to/randomchaos/microsoft-pushed-an-emergency-net-patch-sunday-407d</guid>
      <description>&lt;p&gt;Brotli's streaming decoder holds an eight-byte internal buffer for input it has not finished reading. A specially crafted Brotli stream can trigger an invalid block switch that the decoder treats as a temporary request for more input instead of a permanent format error. It keeps appending input bytes to that eight-byte buffer, the write runs past the buffer's bounds, and nearby memory gets corrupted. That is CVE-2026-111497, and depending on which stack it was found in, it goes by HTTP2Shell, Broccoli2Shell, or Node2Shell.&lt;/p&gt;

&lt;p&gt;The three names come from one bug surfacing in different places. Researchers first identified it in Node.js, where Brotli ships as a built-in C decoder library, then realized the flaw lived in the Brotli decoder itself and so reached any software that decompresses attacker-controlled Brotli data. Brotli is Google's open-source lossless compression library, which makes the reach wide. Affected versions run from 1.0.3 through 1.0.9, plus 1.1.0 and 1.2.0.&lt;/p&gt;

&lt;p&gt;Beyond Node.js, the Python HTTP clients are in scope: urllib3[brotli], requests, httpx, and aiohttp[speedups], when configured with a vulnerable Brotli decoder. Microsoft pushed an emergency update for .NET on Sunday, warning that exploitation allows privilege escalation on systems running a vulnerable version. Any application that links a vulnerable Brotli implementation is a candidate.&lt;/p&gt;

&lt;p&gt;The name HTTP2Shell points at HTTP clients and servers, but the bug has nothing to do with HTTP/2 specifically. An attacker needs an application to decompress malicious Brotli data. One route is a server returning a compressed HTTP response to a client fetching a URL; another is a client sending a compressed request directly to a server. Node.js says the result can be a crashed process, exposed memory, or remote code execution. Imperva's analysis confirms the RCE path is real. Proof-of-concept exploits are public, and no in-the-wild exploitation has been reported.&lt;/p&gt;

&lt;p&gt;The fix landed upstream well before most people heard about it. Google committed the Brotli repairs in February, but stable releases came on October 21 from Google and Node.js, with public disclosure the next day. PyPI packages followed on October 23. Patched versions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google Brotli 1.0.10, 1.1.1, 1.2.1&lt;/li&gt;
&lt;li&gt;Node.js 22.23.4, 24.22.1, 26.12.1&lt;/li&gt;
&lt;li&gt;Python Brotli 1.2.1&lt;/li&gt;
&lt;li&gt;Python brotlicffi 1.2.1.0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two patching traps are worth calling out. Updating your system Brotli library does nothing for a Node.js deployment, or any other application that bundles its own copy; you update the application, not the OS package. Restarting matters too: after updating, processes need a restart, and container images have to be rebuilt and redeployed rather than patched in place.&lt;/p&gt;

&lt;p&gt;Blocking inbound Brotli-compressed requests at your proxy or firewall still leaves the HTTP-response route exposed, where your own client fetches a URL and decompresses what comes back. If you cannot patch right away, the recommendation is to remove Brotli support from Python applications and block incoming Brotli requests at the proxy or firewall, with the understanding that this does not close the HTTP-response path.&lt;/p&gt;

</description>
      <category>brotli</category>
      <category>cve2026111497</category>
      <category>node</category>
      <category>bufferoverflow</category>
    </item>
    <item>
      <title>Your browser tab runs as root on Omarchy</title>
      <dc:creator>RC</dc:creator>
      <pubDate>Mon, 26 Oct 2026 22:25:54 +0000</pubDate>
      <link>https://dev.to/randomchaos/your-browser-tab-runs-as-root-on-omarchy-21df</link>
      <guid>https://dev.to/randomchaos/your-browser-tab-runs-as-root-on-omarchy-21df</guid>
      <description>&lt;p&gt;On an Omarchy install before 4.0.1, the default user could read &lt;code&gt;/etc/shadow&lt;/code&gt; with a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; /:/hostroot alpine &lt;span class="nb"&gt;cat&lt;/span&gt; /hostroot/etc/shadow
root:&lt;span class="nv"&gt;$6$.&lt;/span&gt;..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;cat /etc/shadow&lt;/code&gt; directly and you get permission denied. Route the same read through Docker and the hashes come back. The gap comes from one line of default configuration: Omarchy added its default user to the Linux &lt;code&gt;docker&lt;/code&gt; group.&lt;/p&gt;

&lt;p&gt;On Arch the Docker daemon runs as root and listens on &lt;code&gt;/var/run/docker.sock&lt;/code&gt;. Any member of the &lt;code&gt;docker&lt;/code&gt; group can talk to that socket, and anyone who can talk to the socket can ask the root-owned daemon to launch a container, mount arbitrary parts of the host filesystem into it, and act on those files as root. Docker's own documentation states plainly that membership of the &lt;code&gt;docker&lt;/code&gt; group grants root-level privileges. The container in the proof of concept mounts &lt;code&gt;/&lt;/code&gt; and reads the shadow file; it could just as easily write to it.&lt;/p&gt;

&lt;p&gt;What makes this more than a clever one-liner is how Linux handles supplementary groups. Child processes inherit them. The researcher walked the process tree below the user's &lt;code&gt;systemd --user&lt;/code&gt; instance and found the &lt;code&gt;docker&lt;/code&gt; group present on essentially every normal process in the session. The escalation path is open from anything the user runs: web browsers, editors and IDEs, AI coding agents and their harnesses, npm scripts, assorted development tools, background daemons. Any one of those running untrusted code, a malicious dependency, a compromised extension, a prompt-injected agent, goes straight from user-level code execution to full root on the box.&lt;/p&gt;

&lt;p&gt;The configuration was opt-out, not opt-in. A user who never ran a single container still had the membership applied to their default account, and nothing in the install explained the tradeoff. Omarchy's development-tools documentation did mention it, describing "the user group changes needed for you to run Docker as the normal user and not as root." A reasonable reader takes "not as root" to mean rootless mode. It meant the opposite: the user had a standing, passwordless path to root.&lt;/p&gt;

&lt;p&gt;The membership landed on June 1, 2025, was disabled a day later, then re-enabled on June 17, 2025, and was finally removed from the default configuration on August 24, 2026. Everything before 4.0.1 is affected, including the 3.8.4 ISO the researcher tested. The issue was reported through the project's responsible-disclosure process and patched before the writeup went public.&lt;/p&gt;

&lt;p&gt;If you run Omarchy, update to 4.0.1. If you spent time on an affected version with a browser, an editor, or an agent that pulls arbitrary code, treat the machine as having carried a root-equivalent exposure for the whole period, and rotate anything that lived on it: SSH keys, cloud credentials, tokens in dotfiles. Developer machines are a worthwhile target precisely because they hoard that access, and a distro aimed at developers is the wrong place to disable a guardrail silently.&lt;/p&gt;

&lt;p&gt;For containers without the standing root grant, Podman is the straightforward swap. It is daemonless, so there is no root-owned socket to join a group for; containers run as ordinary child processes in their own user namespaces and need no root access. The researcher reports running it as a complete replacement for their Docker workflows for months.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>containers</category>
      <category>privilegeescalation</category>
    </item>
    <item>
      <title>Forever Security found a malicious AGENTS.md in Downloads</title>
      <dc:creator>RC</dc:creator>
      <pubDate>Mon, 26 Oct 2026 06:25:03 +0000</pubDate>
      <link>https://dev.to/randomchaos/forever-security-found-a-malicious-agentsmd-in-downloads-15j3</link>
      <guid>https://dev.to/randomchaos/forever-security-found-a-malicious-agentsmd-in-downloads-15j3</guid>
      <description>&lt;p&gt;Forever Security found a malicious AGENTS.md file sitting in a customer's ~/Downloads folder, and the AI coding agent running there had already tried to install a rogue npm package called &lt;code&gt;function-color&lt;/code&gt;. The file was plain-text project instructions, the kind these agents read to learn which tools to use, how to run tests, and which conventions to follow. The agent loaded it because Downloads was its working directory, and it did what the file told it to.&lt;/p&gt;

&lt;p&gt;There is no bug to patch. The researchers put it plainly: "There is nothing here for OpenAI or Anthropic to patch. An agent that follows the AGENTS.md in its folder is doing exactly what it was built to do." Agents load applicable instruction files from their working directory automatically. The files aren't executables, but instructions inside them can get an agent to run commands, install packages, or change settings using whatever tools and permissions it already has.&lt;/p&gt;

&lt;p&gt;The delivery path is what makes it work. ~/Downloads is the one folder a web page can write to on its own. By default Chrome, Edge, and Firefox save downloads there with no per-file save prompt. Forever built a proof-of-concept page that drops a file into Downloads without user interaction; when BleepingComputer tested it, the page downloaded an AGENTS.md containing harmless strings ("sensitive data here", "line 2"). Brave prompts before saving, which would tip off the user. Chrome, Edge, and Firefox at least show a download notification, though a notification for a markdown file is easy to let slide.&lt;/p&gt;

&lt;p&gt;Dropping the file is only half of it. The attacker still needs the target to launch an agent in Downloads so it loads the instructions. That is less of a reach than it sounds. Gal Weizman told BleepingComputer that people routinely point agents at Downloads to organize the folder or to act on something they just pulled down. Forever's internal numbers put hundreds of customers running Claude Code, Codex, and Cursor CLI from ~/Downloads, with Claude Code alone logging more than 1,300 sessions started there.&lt;/p&gt;

&lt;p&gt;The researchers rebuilt the chain and measured it. Against Codex, a benign payload that opened the calculator app succeeded 90% of the time. The Claude Code variant went further: a malicious CLAUDE.md redirected the agent's API traffic to a server the researchers controlled, which exposed the OAuth token and let that server impersonate the model, returning tool calls that executed code in roughly half the tests. A leaked OAuth token also means the account itself can be hijacked.&lt;/p&gt;

&lt;p&gt;The fix sits with the operator, because both the browser behavior and the agent behavior are working as intended. Don't run an agent with ~/Downloads as its working directory. OpenAI and Anthropic both recommend starting an agent in the root of the specific project it should work on, not your home directory or a broad parent. The working directory sets the agent's default context and, depending on the tool, its filesystem access boundary, so keep it as narrow as the task allows and widen only when you need to.&lt;/p&gt;

&lt;p&gt;Beyond that, read any unfamiliar AGENTS.md, CLAUDE.md, or similar file before letting an agent act on it, keep approval prompts and sandbox protections turned on, and run anything you don't trust in an isolated environment first.&lt;/p&gt;

</description>
      <category>aicodingagents</category>
      <category>promptinjection</category>
      <category>npmsupplychain</category>
    </item>
    <item>
      <title>The session that never expired</title>
      <dc:creator>RC</dc:creator>
      <pubDate>Sun, 25 Oct 2026 22:25:55 +0000</pubDate>
      <link>https://dev.to/randomchaos/the-session-that-never-expired-1jc4</link>
      <guid>https://dev.to/randomchaos/the-session-that-never-expired-1jc4</guid>
      <description>&lt;p&gt;A dark web service called Nexus went live this week selling digital scans of more than 153 million drivers licenses from people in the United States and Canada. Brian Krebs traced the images to IDScan.net, an identity verification company in Louisiana whose customers include Hertz, FedEx, Target and thousands of cannabis dispensaries. The operators of Nexus describe the source only as "a major identity verification company" and say the pipeline is still running: "We have been continuously exfiltrating new data for over a year into our private database." The FBI's New Orleans field office has opened an inquiry into where the images came from.&lt;/p&gt;

&lt;p&gt;The duration is what should bother anyone running a data pipeline. The feed stayed live for more than a year. In the 24 hours around disclosure, Nexus added nearly 400,000 records, so fresh scans were still arriving while the breach was being written up. It appears no one inside the company noticed.&lt;/p&gt;

&lt;p&gt;An identity verification vendor exists to take a government ID, check it, and return a yes or no. The whole job is careful handling of sensitive records. A company in exactly that business had copies of every scan leaving for more than a year, and that matters more to its customers than whatever route the attackers used to get in.&lt;/p&gt;

&lt;p&gt;Nexus lets buyers preview records with "pertinent information redacted" and shows the customer's photo when one is attached. Krebs found the sitting Secretary of Defense's license listed for $100. The leak is not tied to a single customer: Krebs cross-referenced the dates people were added against their own calendars and matched them to IDs handed over at places like a dispensary, which is how the trail led back to IDScan rather than to one business.&lt;/p&gt;

&lt;p&gt;Larry Baldwin, a security researcher at Cybera, laid out the downstream damage. A state drivers license is standard proof of identity when opening a new line of credit, so the scans feed straight into account fraud. The service also exposes people who do not want to be found and cannot change how they look well enough to fool current AI image matching: those fleeing domestic violence, and people given a new identity under federal witness protection. "Just when it seems like we're making some headway in improving authentication controls through drivers license verification systems, this happens and the very thing those improvements are dependent on are compromised," Baldwin said.&lt;/p&gt;

&lt;p&gt;IDScan.net's Trust Center page, describing how it protects data and earns customer confidence, was still up days after the breach surfaced. The company claims compliance with GDPR, CCPA and the rest, and has written approvingly of age verification mandates including KOSA.&lt;/p&gt;

&lt;p&gt;For anyone building or buying into this kind of system, Krebs's reporting does not pin down the breach technique. Every ID that passes through becomes a record, and every record is a standing target. The only scan that cannot leak is the one you did not keep.&lt;/p&gt;

&lt;p&gt;Unlike a password, this data does not rotate. A leaked credential gets reset; the face and the license number on these scans stay valid for years, which is why 153 million of them are worth standing up a storefront to sell.&lt;/p&gt;

</description>
      <category>databreach</category>
      <category>identityverification</category>
      <category>ageverification</category>
    </item>
    <item>
      <title>Google wants your ID to ship Android apps</title>
      <dc:creator>RC</dc:creator>
      <pubDate>Sun, 25 Oct 2026 06:25:43 +0000</pubDate>
      <link>https://dev.to/randomchaos/google-wants-your-id-to-ship-android-apps-4one</link>
      <guid>https://dev.to/randomchaos/google-wants-your-id-to-ship-android-apps-4one</guid>
      <description>&lt;p&gt;In August 2025 Google announced that, starting in 2027, every Android app developer has to register centrally with Google before their software can be installed on a certified Android device. Registration means paying a fee ($25), accepting Google's terms, handing over a government-issued ID, providing evidence of your private app-signing key, and listing every application identifier you ship now and intend to ship later. The requirement does not stop at the Play Store. It covers apps distributed through F-Droid, apps passed directly between people, and builds that a hobbyist makes for personal use. A developer who does not register has their apps blocked on Android devices worldwide. The keepandroidopen.org campaign organizing the opposition is counting down to the first enforcement, which it puts roughly 70 days out.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the check actually verifies
&lt;/h2&gt;

&lt;p&gt;Google is verifying the developer rather than the code. Registration binds a legal identity to a signing key and a declared set of package names. Google already runs Play Protect, which scans app binaries for malware regardless of who signed them, so the new program adds an identity axis on top of the existing code-scanning one.&lt;/p&gt;

&lt;p&gt;That is where the stated security rationale gets thin. Knowing who wrote an app does not tell you whether the app is safe. Cory Doctorow (Pluralistic) makes the point that certifying developers rather than code assumes Google can predict whether someone will later ship something malicious. Maya Posch (Hackaday) notes the operational gap: identity checks do nothing against the common practice of scammers buying up existing verified developer accounts. F-Droid points out that Google Play has repeatedly hosted malware under its own gatekeeping.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fallback flow runs through Play Services, not the OS
&lt;/h2&gt;

&lt;p&gt;The detail that matters most if you reason about trust boundaries: the fallback install flow runs through Google Play Services, a proprietary component, not through AOSP. Google can change, tighten, or remove it without shipping an OS update and without the device owner's involvement. The policy applies retroactively to hardware already sold.&lt;/p&gt;

&lt;p&gt;Google points users who want to install an unverified app to an "advanced flow." It runs to nine steps: enable Developer Mode by tapping the build number seven times, dismiss warning screens, enter your PIN, restart, wait a mandatory 24 hours, return, dismiss more warnings, then choose to allow the install for 7 days or indefinitely. Google describes this as making sideloading "high-friction" to better warn users about risk (XDA). For planning purposes, treat that flow as unavailable to non-technical users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rollout and regulatory context
&lt;/h2&gt;

&lt;p&gt;Google is starting the program in Brazil, Indonesia, Singapore and Thailand rather than the US or EU.&lt;/p&gt;

&lt;p&gt;The timing tracks Google's antitrust losses. Doctorow reads the change as malicious compliance with the court orders from the Epic Games case. Aptoide has filed a fresh lawsuit alleging monopoly and anticompetitive conduct. In the EU, MEP Christel Schaldemose has formally asked whether mandatory central registration is compatible with the Digital Markets Act, the same law that has been pushing Apple in the other direction.&lt;/p&gt;

&lt;p&gt;Opposition is organized. F-Droid calls the change existential, says it would end the project, and advises developers never to sign up. An open letter has drawn 71 organizations from 23 countries. Brave, Nextcloud, KDE, the EFF and the Free Software Foundation have each published objections. A change.org petition has passed 100,000 signatures.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means if you ship Android software
&lt;/h2&gt;

&lt;p&gt;If you distribute outside the Play Store, your distribution now depends on Google holding a record that maps your legal identity to your signing key and your package IDs. For teams shipping internal betas or enterprise tooling, that is a new external dependency to account for. For anyone building privacy software (VPNs, encrypted messengers, Tor-based tools), the concern Brave raised is direct: the people most likely to distrust Google are now required to upload ID to Google to keep shipping. Developers in sanctioned countries or without Play access cannot verify at all, which, as Termux's maintainer puts it, gates distribution on birthplace rather than conduct.&lt;/p&gt;

&lt;p&gt;Two parts of the registration are the awkward ones to live with. Listing all future application identifiers means registering package names before anything exists under them. Providing evidence of your private signing key means handing that proof to a company with a documented record of complying with government takedown demands.&lt;/p&gt;

&lt;p&gt;F-Droid's own guidance, worth knowing even if you disagree with it, is that developers should not sign up "now or ever."&lt;/p&gt;

</description>
      <category>android</category>
      <category>google</category>
      <category>sideloading</category>
    </item>
    <item>
      <title>fortnew.py scraped 70,000 credentials from exposed appliances</title>
      <dc:creator>RC</dc:creator>
      <pubDate>Sat, 24 Oct 2026 22:25:55 +0000</pubDate>
      <link>https://dev.to/randomchaos/fortnewpy-scraped-70000-credentials-from-exposed-appliances-3ka4</link>
      <guid>https://dev.to/randomchaos/fortnewpy-scraped-70000-credentials-from-exposed-appliances-3ka4</guid>
      <description>&lt;p&gt;Group-IB and NyxLab have linked more than 70,000 credentials, harvested from network edge devices and LDAP dumps, to a single campaign run by a threat actor they track as k0t (also CryptoFeel, Member19, and QazWsxShop). The targets are internet-facing Fortinet and Palo Alto appliances. The researchers describe how k0t picks them: he does not research organizations, he enumerates exposed appliances at scale through the scanning engines FOFA and ZoomEye, filters by product, and builds target lists from whatever responds.&lt;/p&gt;

&lt;p&gt;That shows in the victim spread, which tracks exposure rather than sector. Nearly 38% sit in Asia Pacific, 31.9% in Latin America, 15.8% in Europe, and 12.7% in the Middle East and North Africa. k0t's stated priorities start with the United States and Canada, then Europe and selected APAC markets, but the compromises landed wherever the vulnerable boxes were. In the researchers' words, "the product and location of an exposed device therefore appear to matter more than the industry of the organization operating it."&lt;/p&gt;

&lt;h2&gt;
  
  
  The attack chain
&lt;/h2&gt;

&lt;p&gt;The exploitation uses known vulnerabilities. Two are named in the report: CVE-2025-64446, a path traversal flaw in FortiWeb, and CVE-2026-0257, an authentication bypass in Palo Alto's PAN-OS and Prisma Access. To get initial access, k0t runs bespoke Python against them, scripts named fortnew.py and exploit_2026_0257.py, or brute-forces with common username and password pairs.&lt;/p&gt;

&lt;p&gt;With initial access in hand, the foothold is an OpenConnect VPN connection into the environment. A VPN concentrator is built to carry exactly that kind of traffic, so the entry blends with normal use. From there the post-exploitation is conventional and Active Directory focused: enumeration of AD, SMB, and the installed antivirus, then the usual offensive toolbox of NetExec, Impacket, noPac, Kerbrute, PetitPotam, Mimikatz, and SoftPerfect. Persistence rides on legitimate remote access software: MeshCentral Agent, Atera, Teramind, and AnyDesk, alongside the open-source adversary-emulation framework AdaptixC2. Exfiltration runs through Rclone into Wasabi S3 buckets and MEGA cloud drives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who k0t works for
&lt;/h2&gt;

&lt;p&gt;Group-IB and NyxLab assess k0t as an initial access broker or affiliate rather than the end of the chain. The evidence is overlap: many victims of this campaign later appeared on the data leak sites of the ransomware groups Qilin and The Gentlemen. The researchers do not claim a direct relationship beyond that, and call the exact nature of the connection unclear. k0t first surfaced on 22 October 2025, and his dark-web activity shows interest in buying exploit code and premium FOFA and ZoomEye accounts.&lt;/p&gt;

&lt;p&gt;The campaign also sits next to FortiBleed, a separate credential-harvesting cluster. The two have "negligible overlap" in compromised data, which the researchers read as a separate dataset or operator subset within the broader FortiBleed activity. Most of the compromises here cluster between February and June 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to look
&lt;/h2&gt;

&lt;p&gt;The researchers' own advice is to remediate the vulnerabilities named in the report. Starting points that follow from the facts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Patch state on the two CVEs: FortiWeb for CVE-2025-64446, PAN-OS and Prisma Access for CVE-2026-0257.&lt;/li&gt;
&lt;li&gt;OpenConnect VPN sessions you did not provision. The foothold runs over an OpenConnect VPN connection, so a session you cannot account for is worth investigating.&lt;/li&gt;
&lt;li&gt;Remote access agents installed outside your approved inventory. MeshCentral, Atera, Teramind, or AnyDesk that IT did not deploy are persistence.&lt;/li&gt;
&lt;li&gt;Egress to Wasabi and MEGA endpoints, which is where Rclone sends the harvested data.&lt;/li&gt;
&lt;li&gt;Credential exposure. With 70,000-plus credentials and LDAP dumps in play, treat any account reachable from a compromised edge device as burned, and rotate device-local and LDAP-bound credentials rather than only the obvious admin accounts.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>edgedevicesecurity</category>
      <category>credentialtheft</category>
      <category>initialaccessbrokers</category>
    </item>
    <item>
      <title>Node.js patched a code-execution Brotli bug October 21</title>
      <dc:creator>RC</dc:creator>
      <pubDate>Fri, 23 Oct 2026 22:25:39 +0000</pubDate>
      <link>https://dev.to/randomchaos/nodejs-patched-a-code-execution-brotli-bug-october-21-4obk</link>
      <guid>https://dev.to/randomchaos/nodejs-patched-a-code-execution-brotli-bug-october-21-4obk</guid>
      <description>&lt;p&gt;Imperva's researchers ran attacker-supplied code on an official Node.js 24.22.0 image for Linux arm64, with no debugger and no custom build, by feeding crafted data to the Brotli decoder that Node bundles. The proof of concept, which they call Node2Shell, targets CVE-2026-111497. Node.js disclosed the flaw and shipped fixes on October 21.&lt;/p&gt;

&lt;p&gt;The result comes with limits worth stating up front. The exploit did not land on every attempt; code execution took several tries in that arm64 setup. Imperva tested one build and one application configuration, and did not test other architectures or the 22.x and 26.x release lines. On the fixed build, 24.22.1, the same input was rejected and nothing ran.&lt;/p&gt;

&lt;p&gt;That still clears a bar the earlier public work did not. The first public proof of concept achieved code execution only on a deliberately weakened test build. On a standard build, its author reported a crash and a limited read of process memory, and said no working attack on a normal build was achieved. Node2Shell reaches code execution on a stock image.&lt;/p&gt;

&lt;p&gt;No exploitation in the wild had been reported as of October 22.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the bug works
&lt;/h2&gt;

&lt;p&gt;A Brotli stream announces the block types it will use as decoding proceeds. Imperva's input reached a block change that the stream's own structure had already ruled out, a transition the format does not allow. The vulnerable decoder treated that as a request for more input and kept going in an invalid state. In a separate run under a memory sanitizer, continuing from that state wrote past the intended buffer. That out-of-bounds write is the flaw. Node fixed it by importing an upstream Brotli patch that makes the decoder stop with a format error at that point rather than carry on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which applications are exposed
&lt;/h2&gt;

&lt;p&gt;The decoder is bundled, so every current line carries it: 22.x, 24.x and 26.x. An application touches the decoder from either side of an HTTP exchange. It decodes a Brotli-compressed response when it reads one through Node's built-in fetch(). It decodes a Brotli-compressed request body when middleware does so.&lt;/p&gt;

&lt;p&gt;Express 5's body parsers now handle Brotli. express.json(), express.urlencoded(), express.text() and express.raw() decode Brotli request bodies alongside gzip and deflate when applied to a route. A plain Node HTTP server does not decode a Brotli request body just because one arrives; that path needs the middleware or an explicit call. Imperva reproduced code execution through both the request-body and the response paths, against Express 5.0.0 through 5.3.0 and body-parser 2.0.0 through 2.3.0 at pinned versions, not every release in between.&lt;/p&gt;

&lt;p&gt;The response path matters because it does not depend on an attacker reaching your request handlers. A service that fetches from an upstream it does not fully control, and lets that upstream return Brotli, is exposed through the same decoder.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do
&lt;/h2&gt;

&lt;p&gt;Move to a patched release. The advisory lists no in-runtime workaround, so an application that cannot update has no fallback inside Node itself. The update has to reach everything that bundles a Node binary, including container images and other artifacts that a package inventory can miss. Lines 20.x and earlier are end of life and do not get the fix; those need to move to a supported line regardless.&lt;/p&gt;

&lt;p&gt;Where updating has to wait, Imperva suggested limiting untrusted Brotli traffic on the affected paths where that is practical, and was clear that only the update removes the flaw. It added rules to its own web application firewall and tested them against the attacks it reproduced. Vercel, which runs Node.js for its customers, said it added rules on October 21 that block the attack in inbound requests. Those rules do not cover Brotli responses an application fetches from other servers, and they do not replace updating.&lt;/p&gt;

</description>
      <category>node</category>
      <category>brotli</category>
      <category>remotecodeexecution</category>
    </item>
    <item>
      <title>SafePay routed 600 ransomware hits through Mullvad</title>
      <dc:creator>RC</dc:creator>
      <pubDate>Fri, 23 Oct 2026 06:25:10 +0000</pubDate>
      <link>https://dev.to/randomchaos/safepay-routed-600-ransomware-hits-through-mullvad-1ph4</link>
      <guid>https://dev.to/randomchaos/safepay-routed-600-ransomware-hits-through-mullvad-1ph4</guid>
      <description>&lt;p&gt;CISA, the FBI, the U.S. Secret Service, Germany's Landeskriminalamt Rheinland-Pfalz, and the UK's National Crime Agency and North West Regional Organised Crime Unit have published a joint advisory on SafePay, a ransomware group that has hit at least 600 critical infrastructure organizations across North America, South America, Europe, and Australia since August 2024. The 600 figure spans multiple sectors and undercounts the real total: SafePay only names victims who refuse to pay on its dark web leak site, so the number of organizations actually breached and extorted is higher.&lt;/p&gt;

&lt;p&gt;SafePay appeared in August 2024 as a private operation that runs without affiliates, which is what makes the volume worth paying attention to. Most groups that rack up hundreds of victims do it by recruiting affiliates and splitting the proceeds. SafePay did it in-house, and since the start of 2025 it has absorbed much of the activity that BlackCat (ALPHV) and LockBit used to own, moving into one of the top active slots.&lt;/p&gt;

&lt;h2&gt;
  
  
  How they get in
&lt;/h2&gt;

&lt;p&gt;Initial access comes from the usual places, with one detail the agencies flag specifically. SafePay actors use exposed credentials, brute force against passwords, and VPN access. The advisory calls out that they route through IP addresses belonging to the commercial VPN provider Mullvad. They also work with phished account profiles and run automated scripts that exploit known CVEs in edge devices and other internet-exposed systems.&lt;/p&gt;

&lt;p&gt;That last point is the practical one. Edge devices are the recurring entry vector, and the agencies direct defenders to CISA's Known Exploited Vulnerabilities catalog, with emphasis on flaws in VPNs, firewalls, and similar appliances. These are the systems SafePay's automated scripts exploit, and the ones that tend to lag on patching.&lt;/p&gt;

&lt;p&gt;Once inside, the group behaves like a competent intruder planning for extortion. It steals documents before encrypting anything, the standard double-extortion play, and threatens to publish the stolen data if the ransom goes unpaid. It also targets your ability to recover: the advisory describes SafePay deleting shadow copies and resetting network-attached storage devices that hold backups. If your recovery plan assumes local snapshots or an on-network NAS will survive the incident, this group is built to defeat exactly that assumption.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do about it
&lt;/h2&gt;

&lt;p&gt;The mitigations in the advisory are specific and follow directly from the access pattern. Restrict administrative tools and privileges so that a single compromised account cannot move laterally through the environment. Put MFA on everything, and implement identity, credential, and access management (ICAM) policies rather than leaving account security to passwords alone. Given the Mullvad detail, review whether your VPN and remote access endpoints should be accepting connections from commercial VPN exit ranges at all.&lt;/p&gt;

&lt;p&gt;Keep edge devices patched, and treat anything in the KEV catalog affecting VPNs and firewalls as urgent rather than routine. Those are the appliances SafePay is actively exploiting for initial access.&lt;/p&gt;

&lt;p&gt;For backups, the shadow copy deletion and NAS reset behavior means on-network, online backups are not a recovery plan against this actor. Backups need to be offline or otherwise isolated from the credentials and network paths an intruder would have after compromise, and the restore process needs to be tested against the assumption that everything reachable from a domain admin account is gone.&lt;/p&gt;

&lt;p&gt;The agencies also repeat the line that gets ignored every time: paying the ransom does not guarantee you get your files back. They urge victims to report incidents to law enforcement.&lt;/p&gt;

&lt;p&gt;The advisory carries indicators of compromise and TTPs drawn from FBI, USSS, and Landeskriminalamt Rheinland-Pfalz investigations into SafePay activity observed between November 2024 and August 2026. If you run critical infrastructure in any of the affected regions, that IOC and TTP set is the part to pull into detection tooling now.&lt;/p&gt;

</description>
      <category>ransomware</category>
      <category>criticalinfrastructure</category>
      <category>cisa</category>
    </item>
    <item>
      <title>OpenJev benchmarks against a value it never explains</title>
      <dc:creator>RC</dc:creator>
      <pubDate>Thu, 22 Oct 2026 22:25:07 +0000</pubDate>
      <link>https://dev.to/randomchaos/openjev-benchmarks-against-a-value-it-never-explains-4ng</link>
      <guid>https://dev.to/randomchaos/openjev-benchmarks-against-a-value-it-never-explains-4ng</guid>
      <description>&lt;p&gt;OpenJev runs a local language model in your browser and does one specific thing with it. Given a prompt and a fixed set of options, it reads the model's logits for those option tokens and applies a softmax across only them. There is no decoding and no generated text; a single forward pass yields a probability distribution over the answers you allowed. The site calls these "semantic ifs": a branch decided by the model's weighting of your options instead of a hand-written condition.&lt;/p&gt;

&lt;p&gt;The demo exists to measure that readout against the obvious alternative. The second method hands the same prompt and the same options to the same model and asks it to write the distribution as JSON, options and probabilities, token by token. Both run sequentially on one loaded model so they do not contend for the GPU; the direct readout runs first, then generation. Setup, warmup, prompt preparation, direct execution, first generated token and completion are all timed with performance.now(), and the page shows nothing canned.&lt;/p&gt;

&lt;p&gt;The result an engineer cares about is the timing gap. Reading logits over your options is a single forward pass. Generating JSON is autoregressive: you pay first-token latency and then every token of the output. For anything that is genuinely a constrained choice (routing, classification, a yes/no gate), the model does not need to produce prose that you then parse. The distribution is already in the logits, and reading the right tokens off it is cheaper than making the model spell it out.&lt;/p&gt;

&lt;p&gt;OpenJev is clear about what the direct numbers are. They are a softmax over only the displayed option tokens, which makes them conditional probabilities rather than calibrated confidence, and they exclude any answer the model might have preferred outside your list. The option labels shown run A through T, twenty slots. Weights come from pinned GGUF builds served through wllama; quantization can shift both quality and speed, and the browser build may not match the native checkpoint. MiniCPM5 2B is the default, Qwen3 0.6B is there for phones, and the 4B option needs substantially more memory. The model is about 1.56 GB, it loads from Hugging Face into the browser cache, and inputs never leave the page.&lt;/p&gt;

&lt;p&gt;The quality table is less forthcoming. It scores the local models on balanced accuracy against two reference columns. One is "TypeSafe," defined as equal-case agreement on a 102-row public subset. The other is "Jev," listed only as "the published value," and the caveats add that none of the local tiers is claimed to match it. TypeSafe comes with a definition; Jev gets none. The page never says what that published value measures or where it comes from.&lt;/p&gt;

&lt;p&gt;That matters if you are deciding whether to lean on this. The readout method is clear and testable on your own hardware, which is the entire point of shipping it as a live demo; you can watch the two latencies for yourself. The accuracy numbers are harder to check. Measured quality, the page says, comes from native checkpoints against owned and public benchmarks, but one of those reference columns is never more than "the published value." Run the timing comparison and trust what your GPU reports, because the quantized browser weights can diverge from the native checkpoint. Treat the Jev column with caution until the page says what that published value actually is.&lt;/p&gt;

</description>
      <category>localllm</category>
      <category>logits</category>
      <category>browserml</category>
    </item>
    <item>
      <title>A malicious LiteLLM release stole credentials on install</title>
      <dc:creator>RC</dc:creator>
      <pubDate>Thu, 22 Oct 2026 06:25:13 +0000</pubDate>
      <link>https://dev.to/randomchaos/a-malicious-litellm-release-stole-credentials-on-install-2mj</link>
      <guid>https://dev.to/randomchaos/a-malicious-litellm-release-stole-credentials-on-install-2mj</guid>
      <description>&lt;p&gt;The malicious LiteLLM 1.107.0 release on PyPI did not wait for you to import it. Installing the wheel dropped three files into &lt;code&gt;site-packages&lt;/code&gt;, and two of them (&lt;code&gt;cook.pth&lt;/code&gt; and &lt;code&gt;sitecustomize.py&lt;/code&gt;) are the kind Python executes at interpreter startup. The credential stealer and the backdoor ran in every Python process on the host: the application, &lt;code&gt;pip&lt;/code&gt;, an IDE language server, a CI job. The upstream GitHub source never contained any of it, and PyPI has since pulled the release.&lt;/p&gt;

&lt;p&gt;Python runs any line in a &lt;code&gt;.pth&lt;/code&gt; file that begins with &lt;code&gt;import&lt;/code&gt;. &lt;code&gt;cook.pth&lt;/code&gt; is twelve bytes: &lt;code&gt;import cook&lt;/code&gt;. That pulls in &lt;code&gt;cook.py&lt;/code&gt;, about 61 KB of Python hidden behind one layer of &lt;code&gt;exec(zlib.decompress(base64.b64decode(...)))&lt;/code&gt;. It walks a fixed module list (SSH keys, cloud credentials, CI/CD secrets, AI tool tokens, browser passwords, shell history, GPG keys, TLS private keys, and the LLM provider keys sitting in a LiteLLM proxy database), encrypts the results with a random AES-256-CBC key, wraps that key with an RSA-4096 OAEP public key baked into the file, and POSTs a tar.gz to &lt;code&gt;www.litellm[.]dev/healthcheck&lt;/code&gt; with a hardcoded &lt;code&gt;X-Token&lt;/code&gt; header. After a successful upload it writes &lt;code&gt;/tmp/.pc_once_72129118c59f5636c0bb&lt;/code&gt; so it exfiltrates only once per host.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sitecustomize.py&lt;/code&gt; is the persistent half. Python imports &lt;code&gt;sitecustomize&lt;/code&gt; automatically at startup, so this one also fires everywhere. It takes an exclusive lock, forks, calls &lt;code&gt;setsid()&lt;/code&gt;, redirects stdio to &lt;code&gt;/dev/null&lt;/code&gt;, and detaches into a daemon. Every hour it reads a single line from a GitHub raw URL (&lt;code&gt;letters9813/pythonclient-test/main/domain.txt&lt;/code&gt;), runs its own embedded copy of the stealer (this one with no once-per-host marker), then downloads &lt;code&gt;http://&amp;lt;domain&amp;gt;/codepy&lt;/code&gt; and runs it through &lt;code&gt;exec()&lt;/code&gt;. Whatever that server returns is what runs. The operator repoints the whole fleet by editing one text file.&lt;/p&gt;

&lt;h2&gt;
  
  
  The injection is one line
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;[tool.maturin]&lt;/code&gt; section of &lt;code&gt;pyproject.toml&lt;/code&gt; in the sdist gained &lt;code&gt;data = "cook"&lt;/code&gt;. maturin copies a &lt;code&gt;cook/&lt;/code&gt; folder into the wheel's data tree, and &lt;code&gt;pip&lt;/code&gt; lands it in &lt;code&gt;site-packages&lt;/code&gt;. The sdist itself omits the &lt;code&gt;cook/&lt;/code&gt; folder, so that single config line is the only visible change in the source distribution. No public BerriAI commit contains &lt;code&gt;data = "cook"&lt;/code&gt; or a &lt;code&gt;cook/&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;SafeDep compared every sdist file against the git history by blob hash. The tag &lt;code&gt;v1.107.0&lt;/code&gt; points to commit 66c8f5b, whose &lt;code&gt;pyproject.toml&lt;/code&gt; already reads &lt;code&gt;version = "1.108.0"&lt;/code&gt;, so the sdist does not match its own tag. It matches a later &lt;code&gt;main&lt;/code&gt; commit (a8113b0) plus five edited files and the planted folder. Four of the edits are harmless &lt;code&gt;readme = "README.md"&lt;/code&gt; lines in &lt;code&gt;Cargo.toml&lt;/code&gt; that also appear in the legitimate 1.106.2 build. The fifth edit, to &lt;code&gt;pyproject.toml&lt;/code&gt;, rolls the version back to 1.107.0 and pins &lt;code&gt;litellm-proxy-extras&lt;/code&gt; and &lt;code&gt;litellm-enterprise&lt;/code&gt; to the rc2 values. Because the pins match rc2, a dependency diff against rc2 shows nothing unusual, and the injected &lt;code&gt;data = "cook"&lt;/code&gt; rides along in the same edit.&lt;/p&gt;

&lt;h2&gt;
  
  
  The wheels look pipeline-built
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;WHEEL&lt;/code&gt; metadata names maturin 1.9.4, the same version as the clean releases. The &lt;code&gt;RECORD&lt;/code&gt; entries for the three implant files are correct, so nothing was edited after the build. Zip timestamps show three separate native builds (macOS 11:20, Linux 11:21, Windows 11:37 UTC), and the Windows wheel carries CRLF line endings across all 2,804 &lt;code&gt;.py&lt;/code&gt; files including the implants, the signature of a git checkout on Windows with line-ending conversion. No public GitHub Actions run produced it; SafeDep checked all 539 runs in the window. &lt;code&gt;litellm-dispatcher[bot]&lt;/code&gt; published the GitHub release about ten minutes after the PyPI upload, the same lag seen for 1.106.2, and PyPI holds no provenance attestations for 1.107.0, 1.106.2, or rc2.&lt;/p&gt;

&lt;p&gt;SafeDep's read, at moderate to high confidence, is that BerriAI's own private release pipeline built these wheels from an attacker-modified git source. A compromised maintainer or bot credential, a private branch or mirror, or a tampered build reference all fit. A stolen PyPI token uploaded from an attacker's own machine fits worse, because the wheels carry the pipeline's fingerprints. Only BerriAI's pipeline logs settle it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do
&lt;/h2&gt;

&lt;p&gt;The clean versions are 1.106.2, 1.107.0rc1, and 1.107.0rc2, with companion pins &lt;code&gt;litellm-proxy-extras==0.4.110&lt;/code&gt; and &lt;code&gt;litellm-enterprise==0.1.78&lt;/code&gt;. If 1.107.0 touched a host, assume the stealer ran at the first Python startup after install, not at import, so "that job never imported litellm" is not a defense. Rotate everything in the module list: SSH keys, cloud credentials, CI/CD secrets, AI provider keys, and any keys held in a LiteLLM proxy database. Check for &lt;code&gt;/tmp/.pc_once_72129118c59f5636c0bb&lt;/code&gt; and &lt;code&gt;/tmp/remote_code_loader.lock&lt;/code&gt;, and for the three files in &lt;code&gt;site-packages&lt;/code&gt;. Treat a release whose artifacts do not match their git tag, and which lacks PyPI provenance attestations, as the detectable signal it was here.&lt;/p&gt;

&lt;p&gt;The backdoor's control channel is already dead: the &lt;code&gt;letters9813&lt;/code&gt; account and repository returned 404 about two hours after release, so hosts can no longer fetch a new &lt;code&gt;codepy&lt;/code&gt;. Any host that ran the daemon inside that two-hour window may have pulled and executed second-stage code that SafeDep could not recover.&lt;/p&gt;

</description>
      <category>supplychain</category>
      <category>pypi</category>
      <category>litellm</category>
    </item>
    <item>
      <title>Respond before you confirm</title>
      <dc:creator>RC</dc:creator>
      <pubDate>Wed, 21 Oct 2026 22:25:36 +0000</pubDate>
      <link>https://dev.to/randomchaos/respond-before-you-confirm-2c8</link>
      <guid>https://dev.to/randomchaos/respond-before-you-confirm-2c8</guid>
      <description>&lt;p&gt;A representative of ShinyHunters told 404 Media the group holds names, home addresses, phone numbers, and spouse information for FBI agents, and that the stolen set covers "all FBI employees and applicants." The words the group gave the reporter were blunt: "We hacked the FBI. We hold data on all FBI employees and applicants." They say they reached it through multiple FBI-related services.&lt;/p&gt;

&lt;p&gt;That claim is the event you have to act on. Everything past the list of field types is conditional in the reporting: the breach could be significant, it may carry national security and counterintelligence implications, the data could help a foreign service, and in other criminals' hands it could put agents and their families at risk. The scope is unverified. You are looking at one group's word about what it took and how much.&lt;/p&gt;

&lt;p&gt;For anyone holding data of this shape, the claim alone is enough to act on, because confirmation is the slow part. Proving or disproving "all employees and applicants" means reconstructing what a breach touched across several services, and that takes time the data does not give you. The group only needs its claim to be credible to start selling or leaking. You need it to be false to justify doing nothing, and you cannot assume that from the outside.&lt;/p&gt;

&lt;p&gt;This group's claim is worth treating as a working assumption for a reason the source names directly. Criminals from the same ecosystem as ShinyHunters have already used hacked data like phone records to track, intimidate, and harass the FBI agents investigating them. The path from stolen contact and address data to real pressure on named people is one this crowd has walked before.&lt;/p&gt;

&lt;p&gt;The fields they describe are the durable kind. A leaked password gets rotated and the loss stops there. A home address and the name of someone's spouse do not expire, and there is no rotation for them. If the set is real and it spreads, the exposure follows the named people for as long as they live at those addresses. That longevity is also what makes it useful to a foreign intelligence service trying to map how the agency is staffed and where its people are.&lt;/p&gt;

&lt;p&gt;So the response that counts here sits on the human side rather than the systems side. Work on the systems side addresses the breach, not the harm the breach enables, and that harm lands on individuals at known addresses with known family members. Protecting them means address confidentiality, notification of the people named in the data, and threat monitoring for the group most exposed. The reporting's note that this ecosystem has already used stolen records to track and harass FBI agents is the argument for starting that work on the claim rather than waiting for a confirmed count.&lt;/p&gt;

</description>
      <category>shinyhunters</category>
      <category>databreach</category>
      <category>incidentresponse</category>
    </item>
  </channel>
</rss>
