TL; DR
The packages delete themselves. Over fifteen days in August, one npm operator published nine packages under nine names from seven accounts and withdrew eight of them personally. The window each was left standing fell from thirteen hours to seventeen minutes. The technique is not theirs alone: seven further packages from unrelated operators, carrying entirely different payloads, were withdrawn by their own publishers at a median of 37.8 minutes. The artifact is gone before most defensive processes run, and the install has already happened.
Everything the registry exposes rotates; the payload does not. All nine shipped a byte-identical bin/ directory, the same SHA-256 digests across three package names and two accounts, fifteen days apart. Content identity is the only tracking signal this operator did not break, and the single package they never withdrew is the reason any of it could be examined at all.
The people installing it are not victims, and are badly exposed anyway. This tool is not aimed at developers: it defeats remote exam proctoring through hidden screen capture, on-screen text extraction and answers returned to an overlay, so whoever runs npm install is the intended beneficiary rather than the target. They also run an unsigned binary that decrypts their browser cookie store, from an account that deletes itself within the hour. They cannot receive a fix, cannot audit later what they ran, and cannot report harm without disclosing why they installed it.
Ecosistema: npm, same pattern observed on PyPI. Período: June–August 2026.
La medida
Dwell time is the interval between a package appearing and disappearing, computed from the registry’s own metadata. These are measurements, not estimates.
| PREMIUM | Published (UTC) | Left standing |
|---|---|---|
moidev | 2026-08-16 16:31 | 5h 58m |
moidevx | 2026-08-17 03:24 | 13h 23m |
moidevz | 2026-08-26 03:38 | 12h 56m |
moideva | 2026-08-26 18:58 | 1h 33m |
amicat | 2026-08-28 20:48 | 17m |
bmcat | 2026-08-28 21:17 | 47m |
eyevox | 2026-08-28 21:44 | 21m |
moidevh | 2026-08-31 03:22 | 47m |
Read in publication order, the window contracts by more than a factor of forty — from 13h 23m at the widest to 17 minutes at the narrowest. The first four packages average eight and a half hours; the last four average thirty-three minutes. On 28 August, three packages were published and withdrawn inside a single 77-minute span.
The contraction is not gradual drift. It is concentrated between 26 and 28 August, and what changed was the operator’s estimate of how long a package can safely stand.
Every withdrawal here is publisher-initiated. The registry document for each shows an empty maintainer list beside a time.unpublished record — the signature of an unpublish rather than a takedown. A ninth package, eyiouss, was never withdrawn at all; it is the reason any of this could be examined.
A second withdrawal regime exists and should not be confused with this one. Where only the payload version is pulled and the package survives, the median is roughly 73 hours across 31 packages. Those replacements arrive in scripted batches and leave an empty husk — a package.json declarando un principal that ships no file — whose only function is to keep the name held. That regime is housekeeping on a schedule. This one is a tuned exposure window.
What Survives the Deletion
Nine of these packages are one operator: moidev, moidevx, moidevz, moideva, moidevh, amigo, bmcat, ojo y eyiouss. The names share no convention — anyone tracking the moidev stem would have missed more than half of them — and they were published from seven separate accounts, nearly all registered on disposable-email domains.
What they share is a manifest entry with no reason to exist:
"bin": { "": "bin/kalamasha-tool.js" } } We retained copies of five before removal. Across all five, the entire compartimiento/ directory is byte-identical:
| Archivo | SHA-256 |
|---|---|
bin/kalamasha-tool.js | 0c293be90c10c8a7618d25f4c4811fa63612b7bc5199b86e10bb31eb36c716dd |
bin/uia_extract.exe | e2fda5aa8397799669f29258f69e803cf05d322c1d93269eef6754ca024c3865 |
bin/chrome_cookies.ps1 | 21b61ec810331850d72423c40c5448e6cd310c4cfad6aed54f92cd7e7cac5f3a |
bin/stealth_capture.ps1 | c9baf5897c03b941c54f736df5af9243ad28794a9e69746d41d4f4a34065589c |
bin/uia_extract.py | c20b38c63efd9221930095c54b42cdd5adffa1972c44c4578226cbe1e4dbac3e |
bin/uia_get_text.ps1 | 4a3f3ada0bdf13aa8e89edb8af817c7816296147dae5be25f169ff960d28a87c |
Two further signals agree. Three of the packages were published at 03:24, 03:38 and 03:22 UTC on 17 August, 26 August and 31 August — a sixteen-minute band across fifteen days and three separate accounts. And two of those accounts were registered on the same disposable email domain, tying them together independently of the code.
Las cuentas
These are the npm publisher accounts that shipped the payload, with the package each uploaded and how long it was left standing:
| Publisher account | PREMIUM | Email domain | Left standing |
|---|---|---|---|
letol39119 | moidev:1.0.0 | hutdot.com (disposable) | 5h 58m |
so1d1a7i27 | moidevx:1.0.0 | ogzmail.com (disposable) | 13h 23m |
lololololol435678 | eyiouss:3.0.21, 3.0.22, 4.0.1 | ogzmail.com (disposable) | still published |
tagadob568 | moidevz:1.0.0 | ebflyai.com (disposable) | 12h 56m |
tayihim489 | moideva:1.0.0 | prodbits.com (disposable) | 1h 33m |
sahihai123 | amicat:1.0.0, bmcat:2.0.9, eyevox:1.0.0 | consumer webmail | 17m / 47m / 21m |
heytoshan | moidevh:1.0.0 | consumer webmail | 47m |
so1d1a7i27 y lololololol435678 compartir la ogzmail.com registration domain — the link that ties the account still hosting a live copy to the account that published under the moidev stem two weeks earlier. sahihai123 published and withdrew three separate package names inside a single 77-minute window on 28 August. heytoshan registered, published moidevh, and withdrew it 47 minutes later; it remains that account’s only publication.
Every one of these accounts is email-unverified, carries no verified source-control link, and has published no unrelated project. Six of the seven no longer host anything.
One package was never withdrawn. eyiouss:4.0.1 has been published since 16 August and was still resolvable at the time of writing. Eight artifacts were unrecoverable; the campaign was reconstructed entirely from the one that stayed. An operator who deletes reflexively will still, eventually, leave one standing.
Qué hace la herramienta
eyiouss:4.0.1 describes itself on npm as a “High-performance DOM utility and diagnostic bridge for modern web applications”. It is a screen-capture and answer-retrieval tool built to run underneath remote exam proctoring, and the source says so in its own words.
The launcher copies the Electron runtime under a false filename before running it, and names what it is avoiding:
// 🛡️ STEALTH BINARY NAME: Must NOT collide with real Testpad! const STEALTH_NAME = 'SearchApp.exe';
The same file’s header calls it an Anti-Proctor Ghost Watchdog and implements a respawn loop that backs off further the faster it is killed. Elsewhere the process raises its own priority to fight proctoring CPU throttling, pushes the exam application out of the foreground when it takes focus, and terminates a Safe Exam Browser child process with taskkill /F /T.
Capture runs through a bundled PowerShell script invoked with the execution policy disabled and the window suppressed, with on-screen text harvested in parallel through Windows UI Automation. The queued images and text are submitted to a language-model session in an embedded browser and the answer rendered in an always-on-top overlay. That connection is deferred deliberately, and the code gives the reason: to avoid permanent NETSTAT exposure.
The package also ships chrome_cookies.ps1, headed CHROME COOKIE EXTRACTOR, which decrypts Chrome and Edge cookies via DPAPI and reads the cookie database from hasta four browser profiles. Stated precisely: we did not find that script invoked by name from any shipped JavaScript file. What is present and reachable is the consuming half, which injects stored session cookies into the embedded browser.
The Position of the People Who Install It
Nobody installs this by accident. It has no function outside a monitored exam, and its output is an answer overlay on the user’s own screen. The deceptive package description is not aimed at the installer at all — it is cover directed at the registry and at anyone auditing the machine afterwards. The installer knows what they are getting; the description exists so the grabar of the install does not reflect it.
The parties harmed are third parties who never touched npm: the institution running the exam, the other candidates, and everyone downstream who relies on the credential meaning something.
But the installer is not therefore safe, and this is the part worth spelling out, because the disappearing-package model itself is what creates the exposure.
They are running an unsigned binary from nobody. uia_extract.exe ships compiled, with no source and no build provenance, from an account that no longer exists. The same file, by hash, has been republished by letol39119, so1d1a7i27, lololololol435678, tagadob568, tayihim489, sahihai123 y heytoshan across fifteen days. There is no maintainer to ask, no repository to read, and no history to check — every identity that shipped it deleted itself.
They have granted it exactly the capabilities malware needs. A hidden process, running under a false name, that decrypts the browser cookie store, reads the screen continuously, terminates security software and respawns when killed. Today the cookie decryption is scoped to one vendor’s domains and serves the user’s own session. That scope is a one-line change, and nothing about the delivery model would surface it if it changed — a new name, a new account, a new upload.
They cannot receive a fix. The package is unpublished within the hour. There is no update path, no advisory, and no way to learn later that the version they installed differed from the one their friend installed. Whatever is on the machine stays there.
They cannot audit what they ran. Their lockfile now references a package that no longer resolves. If they later wanted to establish what was on their machine — after an incident, or a dispute — the registry has no record to give them.
And they cannot report harm. A user compromised by this tool cannot file an abuse report without disclosing why they installed it. That is not incidental. Registry abuse reports are a main channel by which short-lived packages are caught, and this operator’s user base is structurally incapable of using it. The only remaining adversary is automated scanning — which a seventeen-minute window is calibrated against.
The victim structure and the dwell time are the same fact seen twice. It also explains the anomaly in the timeline: if withdrawal were driven by fear of complaints, the long-lived popular package would go first. It did not, because the complaints never come.
The Same Pattern, a Different Operator
The proctoring operator is not alone in this, and the clearest parallel runs on an unrelated payload.
Between 24 and 27 August, four npm packages appeared under names borrowed from two-factor authentication tooling — auth-otp, Secretokey-2fa, Secretokey2fa y 2fa-Secretokey — carrying sixteen versions between them. Each was published from its own freshly registered account (beayilol, jeanpaul686g, zzzalipay, dluuuuu), all email-unverified, none with a verified source-control link, none publishing anything else. Every one was withdrawn by its own publisher.
The payload has nothing to do with exam software. It reads browser credential stores and Discord tokens, and walks an Xbox Live authentication ladder against the Minecraft launcher to capture a refresh token. Here the installer is the victim in the ordinary sense — which is what makes the comparison useful, because the delivery behaviour is identical regardless.
The four cycles ran in publication order at 274.9, 37.8, 37.6 and 35.7 minutes: one long first attempt, then convergence on a figure that holds. Three further packages belong to other operators again and show the same withdrawal behaviour.
| PREMIUM | Operador | Left standing |
|---|---|---|
octopus-action | recon beacon | 2.5 min |
mt-ts-serverless-starter | recon beacon | 9.6 min |
2fa-Secretokey | 2FA cover names | 35.7 min |
Secretokey2fa | 2FA cover names | 37.6 min |
Secretokey-2fa | 2FA cover names | 37.8 min |
auth-otp | 2FA cover names | 274.9 min |
hex-encode-utils | otros | 724.2 min |
Seven packages, median 37.8 minutes, none of them related to exam software.
Three unrelated payloads, three unrelated sets of accounts, one shared technique.
Why the Window Is Closing
Something changed in the registry’s environment during 2026, and the obvious candidate is that scanning got faster.
Until recently, malicious packages were found principally after the fact: by a user noticing something, by a downstream report, or by a periodic sweep. Detection latency was measured in days. That is no longer the only regime. Near-real-time analysis of newly published packages — Xygeni’s own Malware Early Warning among a growing set of such systems across the industry — closes the gap between publication and inspection to something much shorter.
An operator facing that has two options. Make the payload harder to recognise, or shorten the time it is available to be looked at. The second is cheaper, requires no engineering, and the registry provides the mechanism for free: within npm’s 72-hour unpublish window a publisher may remove a package unilaterally, and the name can be reused afterwards. Withdrawal costs the operator nothing.
The timing fits. Both operators above converge on a figure and hold it rather than drifting, which is what a tuned parameter looks like rather than a matter of convenience. And the parameter they converged on — tens of minutes — sits precisely where it would need to sit to beat an automated inspection pass while still leaving the package installable long enough to reach its audience.
This remains a hypothesis. Timing data cannot separate a response to scanning from a response to registry enforcement, or from ordinary operational maturation as these operators learn from one another. What can be said without inference is narrower and still useful: the exposure window is now short enough that any control depending on inspecting a package after publication is racing a clock the operator sets. Controls that do not depend on inspection — quarantine by age, disabled install scripts — are unaffected by that race, which is the practical reason to prefer them.
Qué hacer al respecto
Quarantine by age. Nothing in the dwell-time table survived thirteen hours. A policy that no dependency version is installable until it has existed for 72 hours would have excluded every one of them without detecting anything.
Disable install scripts by default. –ignorar-scripts removes the delivery mechanism the credential-stealing packages in this corpus depend on. It does not help against a tool the user runs deliberately, which is precisely the distinction worth understanding.
Treat disappearance as a security event. Alert when an installed dependency stops resolving. Your lockfile, not the registry, is where the evidence still lives.
Track content, not names. The six digests above match regardless of package name, publisher account or version string — every field this operator demonstrated they will change. A registry-side rule that a newly registered account withdrawing its only package within an hour is a reportable pattern would have fired on every package here, on metadata alone.
And if you are considering installing something in this category: the properties that make it hard for a registry to catch are the same properties that leave you with no recourse. There is no publisher to hold responsible, no update path, and no record of what you ran.
indicadores
| Tipo | Valor |
|---|---|
| Archivo | bin/kalamasha-tool.js — non-standard bin entry point |
| SHA-256 | 0c293be90c10c8a7618d25f4c4811fa63612b7bc5199b86e10bb31eb36c716dd |
| SHA-256 | e2fda5aa8397799669f29258f69e803cf05d322c1d93269eef6754ca024c3865 |
| Proceso | SearchApp.exe written beside a legitimate Electron runtime |
| Comportamiento | powershell -ExecutionPolicy Bypass -File con windowsHide: true |
| Comportamiento | taskkill /F /T targeting a Safe Exam Browser process |
| metadatos | Empty maintainer list beside a time.unpublished grabar |
| Cuentas | letol39119, so1d1a7i27, lololololol435678, tagadob568, tayihim489, sahihai123, heytoshan |
| Registración de | ogzmail.com, hutdot.com, ebflyai.com, prodbits.com — disposable-mail domains |
Referencias
- npm unpublish policy — the 72-hour window within which a publisher may remove a package without intervention.




