On November 5, Microsoft Threat Intelligence published research on threat actors using agentic AI tooling to hunt for secrets exposed on GitHub. With those secrets they got into Entra ID tenants, Azure Key Vaults and Azure AI services. The IP at the centre of that activity was 199.19.77.84.
When we checked VulnCheck Canaries, we found the same address had been hitting our infrastructure too, by another route. Instead of leaked GitHub secrets, it was exploiting Langflow to pull credentials straight off the box.
In our post, we looked at two attackers who both went after Langflow, one for credentials and one for cryptomining. This is a third, and it may be the most interesting of the three. Over 36 minutes it ran 11 payloads that read less like an exploit kit and more like an agent working the problem.
Below we walk through what we saw, how it lines up with Microsoft's research, and what defenders can do about it. Let's dive in.
What Did Microsoft Find?
Microsoft describes an agentic framework that sends large numbers of GitHub searches for secrets, from August 2026 on. The searches combine target names with keywords for cloud and AI services. From October 28, Microsoft saw successful service principal sign-ins from 199.19.77.84 using leaked application credentials. Some were multitenant vendor apps, which opened the way into downstream tenants.
After signing in, the agent enumerated Azure, read Key Vault secrets and storage keys, pulled SharePoint and OneDrive content, and validated stolen Azure AI resources. In one case it went from a GitHub search to Key Vault exfiltration in five minutes. Microsoft also points to adaptive troubleshooting: failed ARM calls retried 28–80 seconds later with a corrected API version.
Microsoft tied two more IPs to the campaign. It linked vulnerability exploitation to 65.87.223.26 and AI-workload reconnaissance to 157.22.126.128. In Microsoft's account, 199.19.77.84 is the credential-abuse address.
Todyl and Huntress reported the same IP signing into Entra ID with stolen app secrets. Todyl counts at least 27 affected organizations and places the address on AS203662, a Poland-based hosting provider. Huntress saw the actor obtain Azure tokens in four customer tenants. Neither report describes this IP exploiting a vulnerability, and that is where our data comes in.
What Did Our Canaries See?
VulnCheck canaries logged 25 events from 199.19.77.84 across three countries, from 13 distinct requests. Each PHP probe tripped two signatures at once, and 10 of the 11 Langflow stages were sent twice, usually less than a second apart. All times are UTC, newest first.
| Time (UTC) | Canary | CVE | Activity |
|---|---|---|---|
| Nov 7, 00:35–00:38 | GB | CVE-2025-3248 | Stages 4–11: cloud and Docker recon, log scraping, credential decryption |
| Nov 7, 00:30–00:32 | GB | CVE-2025-3248 | Stages 2–3: env dump, SQLite discovery under /app |
| Nov 7, 00:02 | GB | CVE-2025-3248 | Stage 1: env, .env files and langflow.db sweep |
| Nov 2, 08:44 | SE, BR | CVE-2026-109618, CVE-2026-109619 | PHP upload-progress session priming probes |
The Langflow activity on November 7 UTC is the evening of November 6 in US time zones. That is one day after Microsoft published, so the operator was still active with the same infrastructure.
Breaking Down the Langflow Attack
All 11 stages use one wrapper. CVE-2025-3248 lets an unauthenticated caller send Python to /api/v1/validate/code. Langflow compiles that code to validate it, and a decorator runs at function definition, so the payload runs immediately:
import os
@exec('\nimport os, json\ndef _gather():\n return {"pid": os.getpid(), "cwd": os.getcwd(), "host": os.uname().nodename,\n "env": {k: v for k, v in os.environ.items()}}\nraise Exception("|RAISE|" + json.dumps(_gather())[:80000])\n')
def _lf_probe():
pass
This is stage 2 exactly as sent. Later stages swap in more code, rename the helper to _g() and change the size cap, but the shape never changes.
The stolen data doesn't leave through a separate channel. Each stage puts its results in an exception marked |RAISE|, and the vulnerable endpoint returns exception text in its HTTP response, so the reply to each request carries the data. None of the payloads call back to attacker infrastructure, download anything or write a file. The only outbound traffic stays inside the host. One stage queries the cloud metadata service at 169.254.169.254 and talks to the Docker socket, and that is the traffic worth alerting on.
The stages build on each other:
- Sweep (00:02). Dump
os.environ. Read.envfiles under/app,/homeand/root. Glob forlangflow.dband dump tables named like config, variable, user, apikey, credential, provider or flow. - Map the host (00:30–00:35). List
/app/data, walk for SQLite files and read/proc/1/cmdline. Check for/var/run/docker.sockand, if present, requestGET /containers/json?all=1. Fetch DigitalOcean metadata and user-data from169.254.169.254. - Look for other intruders (00:36). Read
/proc/*/cmdlinefor miner processes (xm,cpuminer) and runcrontab -l. Read files left by earlier attackers, such as/app/data/.kxc/mine.log,/tmp/.kk9/.d.pyand/tmp/keepx.sh. Some of these, including/tmp/.l.sh, were dropped on the same canary two days earlier by a separate cryptomining crew that had hit the same canary. One code comment says it outright: "leftover scripts of other actors". - Scrape for keys (00:36–00:37). Grep
langflow.logand theflowtable forsk-,AIza,AKIA,AQ.Ab8,JQQJ99,Ocp-Apim,BEGIN PRIVATE KEY,openai.azure,cognitiveservicesandservices.ai.azure. Pullapi_keyandbase_urlfields from saved flows. Read themem0memory-layer config. - Decrypt the vault (00:36–00:38). Langflow encrypts stored variables with Fernet. The agent tried four approaches in turn: Langflow's own
decrypthelper,grep -rn "def decrypt"over the package, a candidate secret that appears only after its two environment dumps (LANGFLOW_SECRET_KEY=[redacted], our decoy's key) run through seven key derivations, and finally Langflow's ownensure_valid_key()fed that real secret. The last stage decrypts every row ofvariablejoined to its owner's username. Because it uses Langflow's own key derivation with the decoy's key, that is the method that works. Against a real instance, this is where the provider keys come out. Against our canary, all it could recover was decoy data. - Wrap up (00:38). Dump the
fileandvertex_buildtables and list upload directories.
Is There an AI Agent Behind the Keyboard?
We can't prove from network traffic alone that an AI agent ran this session. That said, it lines up with what Microsoft describes.
- Each stage depends on the last. Paths, table names and key-derivation guesses in later stages come from what earlier stages returned. A fixed kit would send the same payload to every target.
- Retry at machine speed. The decryption attempts took about 80 seconds from first try to the method that works, with each failure followed by a new variation. That matches the 28–80 second ARM retries in Microsoft's report.
- Narrating comments. Payloads carry comments such as
# try langflow decrypt on any encrypted-looking valuesand# leftover scripts of other actors: grep, typical of generated code. - Python HTTP clients. Stage 1 and the PHP probes follow python-requests' header order (
User-Agent, thenAccept-Encoding,Accept: */*andConnection). Stages 2–11 match urllib (Accept-Encoding: identityfirst,Connection: close). Microsoft lists Python HTTP clients among ARTEX's default tools. - Hunting for AI keys. Every key pattern and endpoint in the payloads points at an LLM provider or a cloud AI service. Microsoft saw the same focus.
Before Langflow: Poking at PHP
On November 2, the same IP sent one multipart POST / each to canaries in Sweden and Brazil. Both tripped our CVE-2026-109618 and CVE-2026-109619 detections.
The request picks its own session ID and sets an upload-progress key. This is the priming step for php2shell, the pair of PHP request-memory bugs behind CVE-2026-109618 and CVE-2026-109619 that can lead to remote code execution. The content here is harmless, so this was a check for exposure, not an exploit.
Not the Only One at the Door
199.19.77.84 wasn't the only intruder after AI credentials in our canaries that week. On November 2, about five hours before .84 probed our Brazil and Sweden canaries for the PHP bug, 179.43.191.82 (Private Layer, Switzerland) ran an interactive session against our Brazil Langflow canary through CVE-2025-3248.
Its playbook looks a lot like .84's:
- Langflow secrets. It read
/app/data/.cache/langflow/secret_keyand/proc/1/environ, and greppedlangflow.logforsk-,api_key,openai,anthropic,aiza,gsk_,hf_andvertex. - Agent memory. It listed and read the
.mem0and.composiostores, which hold memory and tool-integration config for AI agents. - Other intruders. It read leftover files such as
/app/data/.cache/.sync/.s.shanddl.out. - The container. It checked the Docker and containerd sockets and port-scanned the container network.
- Azure identity. It tried several times to get a managed-identity token for
management.azure.com, queried Azure's instance metadata endpoint, grepped the environment forIDENTITY|MSI|AZURE, and tested whether it could reach Azure's WireServer at168.63.129[.]16.
Eight hours later, the same IP hit HKUDS AutoAgent (CVE-2026-86124) with a script that harvests AWS IMDSv1/v2 role credentials, user-data, and OCI and GCP metadata. Across five days it touched four CVEs, all in AI tooling: CVE-2025-3248, CVE-2026-7873 and CVE-2026-51886 in Langflow, and CVE-2026-86124 in AutoAgent.
We don't attribute .82 to the same operator. Its code is different: a def foo() stub, a bare exception with no |RAISE| marker, and the default python-requests/2.34.2 user agent where .84 spoofed Chrome. Neither Microsoft nor Todyl names it. But the convergence on targeting is the point. Exposed AI tooling has become a front door to cloud identities, and several actors are working through it with the same checklist.
Indicators and Fingerprints
Microsoft points out that agentic frameworks swap IPs and user agents quickly. Code that an agent writes fresh for each session changes just as fast, so expect the strings below to change too. Hunt on the behaviour.
| Type | Indicator | Notes |
|---|---|---|
| IP | 199.19.77.84 | Seen in our canaries and in Microsoft's, Todyl's and Huntress's reporting |
| IP | 199.19.77.18 | Microsoft, Tor exit node, may include unrelated traffic |
| IP | 65.87.223.26 | Microsoft, vulnerability exploitation and App Service token attempts |
| IP | 157.22.126.128 | Microsoft, recon of Azure AI workloads |
Fingerprints:
| Type | Indicator | Confidence | Notes |
|---|---|---|---|
| Request body | |RAISE| exception prefix, def _lf_probe(): | Medium (retro-hunt) | Unique to this actor in our data, but likely generated per session and unlikely to persist |
| Behaviour | Most requests sent twice, usually less than a second apart; staged validate/code POSTs escalating from env dump to database decryption | Medium | Survives IP, user-agent and code changes better than strings |
Related activity (not attributed to this actor):
| Type | Indicator | Notes |
|---|---|---|
| IP | 179.43.191.82 | Langflow credential theft and Azure managed-identity token attempts, Oct 29 – Nov 2 |
The CVEs we observed this actor targeting are CVE-2025-3248 (Langflow), CVE-2026-109618 and CVE-2026-109619 (PHP). The related actor also targeted CVE-2026-7873 and CVE-2026-51886 (Langflow) and CVE-2026-86124 (HKUDS AutoAgent).
So What Should Defenders Do?
Microsoft's guidance covers the cloud side: rotate leaked secrets, lock down service principals and hunt sign-ins from these IPs. Our data adds the application side. If you run Langflow or similar AI tooling, assume the keys stored inside it are what attackers are after.
- Get Langflow off the internet, and patch it. CVE-2025-3248 has been on CISA KEV since May 2025, and attackers are still landing it in November 2026. Put Langflow behind authentication and a VPN or private network.
- Treat every key in Langflow as exposed if the instance was reachable. That includes variables, flow configs,
.envfiles and thesecret_key. Rotate the provider keys (OpenAI, Azure, Gemini, Anthropic, AWS), then rotate the Langflow secret key. Once an attacker has that key, Langflow's encryption no longer protects the rest. - Check for squatters. These actors went looking for other attackers' leftovers, so look for them too:
/app/data/.kxc,/app/data/.cache/.sync/,/tmp/.kk9,/tmp/.kkx,/tmp/.l.sh,/tmp/.cache/h.py,/tmp/keepx.sh, miner processes and unexpected cron jobs. - Watch the provider side. Look for AI API usage from unfamiliar IPs or unusual model calls on keys tied to Langflow. Stolen AI keys often get resold or used to run the attacker's own agents.
- Close the paths out of the container. Don't mount
docker.sockinto Langflow, and block the metadata endpoint (169.254.169.254) from app containers where you can. On Azure, scope managed identities tightly. An attacker with code execution in the container can request tokens for whatever the identity can reach. - Hunt on behaviour, not just IPs. Look for bursts of
POST /api/v1/validate/codewith large bodies, error responses carrying JSON blobs, and requests containing@exec(.
VulnCheck Canaries pulled this agent into a 36-minute session against a decoy, which is the kind of deception that helps understand how the attacker works. Every stage it ran gave us intel on its playbook, and none of it touched a real customer.
Two Doors, One Goal
Microsoft saw this actor coming in through leaked GitHub secrets. We saw it coming in through a Langflow exploit. Both routes end in the same place: credentials for AI services and the cloud resources behind them. In layman's terms, AI tooling has become both the target and the tool. Attackers use agents to steal the keys that power other people's agents.
That's the pattern we flagged in our 1H-2026 State of Exploitation report and our last Langflow post. AI platforms are being deployed fast, they're often exposed, and they hold the keys to everything around them. The difference now is speed. When an agent can go from first request to a working decryption method in about half an hour, patch windows measured in weeks don't hold up.
Thanks to the Microsoft Threat Intelligence team for publishing their research. Sharing indicators like these is what helps connect the dots.
Sources
- Microsoft Threat Intelligence, Threat actors use agentic AI tooling to find and abuse exposed secrets, November 5, 2026
- Todyl, Stolen App Credentials, Real Access: An Actor Is Signing Into Entra ID and Azure DevOps as Your Workloads, November 3, 2026
- Huntress, post on X, November 3, 2026
- VulnCheck, Same Target, Different Playbooks: Two Attackers, Two Different Paths to Pwning the AI Stack, August 28, 2026
- VulnCheck Canary Intelligence,
vulncheck-canariesindex, events October 29 – November 7, 2026
About VulnCheck
VulnCheck is helping organizations not just to solve the vulnerability prioritization challenge - we’re working to help equip any product manager, CSIRT/PSIRT or SecOps team and Threat Hunting team to get faster and more accurate with infinite efficiency using VulnCheck solutions.
We knew that we needed better data, faster across the board, in our industry. So that’s what we deliver to the market. We’re going to continue to deliver key insights on vulnerability management, exploitation and major trends we can extrapolate from our dataset to continuously support practitioners.
Are you interested in learning more? If so, VulnCheck's Exploit & Vulnerability Intelligence has broad threat actor coverage. Register and demo our data today.