On 29 October 2026 I examined a set of GitHub accounts distributing malware through repositories that impersonate zapret, a real open-source tool used in Russia to restore access to Discord, YouTube and Telegram. The accounts were identified from public malware-URL submissions and then checked individually against GitHub's own public API. This analysis reports what that check found.
The campaign is not new and I did not discover it. The Russian-language zapret community has documented these clones since June 2026, and related GitHub distribution campaigns were published by Island in July and by Apiiro in October. What follows is not a discovery of the operation. It is a measurement of how its accounts are constructed, and that measurement produced a signature I have not found described anywhere.
Every account I examined signs itself the same way. It registers with no followers. On that same day it creates one repository whose name is exactly eight random lowercase letters and nothing else. It then goes dormant for somewhere between nine and ninety-six days. Finally it publishes its entire set of lure repositories in a single batch on one later date. Twenty accounts drawn at random followed that sequence without a single exception.
Method and scope. The candidate account list came from public URLhaus submissions between 20 and 29 October 2026, filtered to repository names matching the campaign's lure patterns. Verification was done by reading GitHub's public API: account creation dates, follower counts, repository names and creation dates, and release asset download counts. One hundred accounts were checked for liveness and download totals; twenty of those were examined in full for repository structure. I did not download any payload and did not interact with the infrastructure in any way.
zapret is a genuine open-source project. In Russia it is used to restore access to services subject to throttling or blocking, principally Discord, YouTube and Telegram. The best-known packaging of it is maintained under the GitHub account Flowseal, and the ordinary way to obtain it is to download a ZIP archive from a GitHub releases page.
That ordinary way is the entire attack. A person searching for a way to unblock Discord expects to find a GitHub repository, expects to download an archive from it, and expects to run an unsigned executable with administrator rights, because that is what the genuine tool legitimately requires. The audience is pre-selected for precisely the behavior the malware needs.
Name: One canonical repository name, with forks that keep it
Account: A maintainer with followers, history and other work
Repositories: Source code, issues, commits over time
Description: Written once, by a person
Name: Dozens of permutations of the same words across unrelated accounts
Account: Zero followers on 98 of the 100 I checked
Repositories: Four to six, all published on one day, carrying release archives
Description: The same adjectives reordered from repository to repository
The repository names in this set are permutations of what a user would type into a search box. Reading them in bulk makes the generator visible.
| Technique | Examples Observed |
|---|---|
| Word-order permutation | discordzapret / zapretdiscord |
| Separator variation | discord-fix / discordfix / fix-discord / fixdiscord |
| Version suffixes | 1.9.9c · 1.9.9d · 1.10.1 · 1.10.2 · 1.11.1 |
| Qualifier suffixes | DiscordFix-2026 / -New / -Stable / -Update / -Windows |
| Random case mangling | dIsCoRdzapReT · tELeGRaM-ZaPrET |
| Maintainer's name | flowseal-zapret-discord-youtube |
| Transliterated Russian | obhod, from обход, meaning bypass |
The descriptions are generated the same way. Three repositories on three different accounts carried the phrases Стабильнее, быстрее, надежнее, Надежнее, быстрее, стабильнее and Быстрее, надежнее, стабильнее. The same three adjectives, reordered. A reader who does not read Russian sees three plausible descriptions; a reader who does sees one sentence shuffled three ways.
Why the random case mangling matters. Names like dIsCoRdzapReT and ZAPRET_gItHuB-DISCOrd_1.9.9C are not sloppiness. Randomized capitalization defeats exact-string matching on repository names, which is the most obvious check a platform would run. The generator is built against the detection it expects.
The naming is noisy by design and varies account to account. The account lifecycle does not vary at all. Every one of the twenty accounts I examined in full followed the same five steps.
The clearest evidence that this is one operation rather than many is that accounts registered on the same day are switched on together, with the same repositories, weeks later.
| Registered | Accounts | Activated | Repository Set |
|---|---|---|---|
| 30 Jul 2026 | Lacquergruraid, bandwidowbegin | 16 Aug 2026 | Identical, 5 repos |
| 6 Aug 2026 | wildstagekindle, SwiftSoundIdolize | 23 Aug 2026 | Identical, 5 repos |
| 9 Aug 2026 | SplendorEchoHatchet, StorageStudent | 2 Sep 2026 | Identical, 5 repos |
| 13 Aug 2026 | PatrolGiraffePipe, MoatSorcerer | 20 Sep 2026 | Identical, 3 repos |
Two accounts with unrelated names, registered the same day, dormant for the same number of days, waking on the same day with the same five repository names. Four such pairs appeared inside a sample of twenty, which is not what independent activity looks like.
Most of what is visible here is deliberately noisy. Names are permuted, capitalization is randomized, version numbers rotate. Those are the parts the operator varies, so they are the parts worth ignoring. The signal is in what does not vary.
| Signal | Indicator | Confidence |
|---|---|---|
| Eight-character marker repo | repo name matches ^[a-z]{8}$, created on account creation date | High |
| Single-date activation | all remaining repos share one creation date | High |
| No social graph | followers == 0 and following == 0 | Medium |
| Dormancy before first lure | activation date minus registration date, 9 to 96 days | Medium |
| Name-permutation clustering | many accounts, few distinct names for one token | Medium |
| Release archive without source | release asset present, repository has no code | Medium |
No single row in that table is sufficient on its own. Plenty of real accounts have no followers, and plenty of real projects publish an archive. The first two rows together are a different matter: a repository named with eight random lowercase letters created on registration day, followed by a batch of repositories all created on one later date, is a sequence I have not been able to produce from any legitimate account.
The practical value of the first signal is that it costs nothing to check and the operator cannot vary it without redesigning the generator. The name permutations can be regenerated in an afternoon. The lifecycle is the part that has to stay fixed.
For anyone looking for zapret or a Discord unblocker. Check the account, not the repository. A maintainer of a widely used tool has followers, a history, and other work. An account with none of those, holding four repositories created on one day, is not the project you were looking for, whatever the repository is called.
I want to be precise about the boundary, because the interesting finding here is narrow and it is easy to overstate it.
What I measured. One hundred accounts verified live or gone against GitHub's API on a single date. Eight hundred and thirty-four release assets and their recorded download counts. Twenty accounts examined in full, every one showing the same five-step lifecycle. Four cohort pairs within those twenty. Registration dates, follower counts and repository creation dates for all one hundred.
What I did not establish. The candidate list contained 5,066 accounts and 19,597 repositories matching the campaign's naming patterns, but I verified 120 of them individually and I am not claiming the remainder. A name filter is an inference, not a finding, and the genuine project's own name appears inside several of those patterns, so some proportion of any name-matched list will be legitimate. I have not attributed this operation to anyone. I have not analyzed a payload. The malware family named by URLhaus on 17,220 of these URLs is SalatStealer, which is that database's classification rather than my determination.
What changed while I was writing it. Three figures I initially believed did not survive checking. An account total of 19,763 collapsed to 5,066 once legitimate repositories were filtered out of it. A claim that three independent submitters had corroborated the account list collapsed to one submitter. A claim that this campaign delivered SmartLoader collapsed when the campaign-filtered data showed no SmartLoader at all. Each of those was caught by running one more query, and I mention them because a reader has no way to see the claims that were discarded, only the ones that remained.
What survives is small and specific. An operation distributing malware through GitHub builds its accounts on an assembly line, and the assembly line leaves a mark: eight random lowercase letters, created on day zero, never touched again. It is on every account I looked at. It is readable without authentication, without tooling, and without downloading anything. And it is still there on almost all of them.
Method: candidate accounts were drawn from public URLhaus submissions dated 20 to 29 October 2026, filtered to repository names matching this campaign's lure patterns, yielding 5,066 accounts across 19,597 repositories from a single submitter. One hundred accounts were selected at random from those carrying a zapret-named repository and checked against GitHub's public REST API on 29 October 2026 for existence, creation date, follower count, repository list and release asset download counts. Twenty of those hundred were examined in full for repository creation sequence. All figures reflect API responses on that date; download counters are cumulative since each release was published and include automated retrieval by researchers, sandboxes and scanners. No payload was downloaded, no archive was opened, and no interaction with the operation's infrastructure took place at any point. Prior public reporting on related GitHub distribution campaigns: Island, July 2026, 7,600 repositories; Apiiro, October 2026, 17,610 repositories; both describe SmartLoader and StealC rather than the payload classified here. The Russian-language zapret community wiki has documented clone repositories since June 2026 and is the earliest public record of this lure set that I could find. This analysis represents independent research produced for educational purposes.
I'm a security researcher in Connecticut. Analysis is the part I love: tracing threat actor behavior, pulling apart supply chain attacks, and following evidence even when it lands on "unknown." When a question needs a tool that doesn't exist, I build it; most of the tools on this site started that way. Before security I spent 15 years designing enterprise software, which is why my tools assume a human will actually have to use them. I contribute detection rules to Sublime Security's open-source production ruleset. Security+ in progress. Everything here is independent work, shared as a contribution to the security community.