❌

Visualização normal

Antes de ontemMicrosoft Security Blog

Inside the LiteLLM 1.107.0 supply chain compromise: Credential theft through Python startup hooks

On October 21, 2026, a compromised LiteLLM 1.107.0 release was published to the Python Package Index (PyPI) and distributed through official container images. The malicious package added files that Python could execute during normal interpreter initialization. An application did not need to import LiteLLM for the payload to run: starting Python in an affected environment could be enough.

Microsoft analyzed two execution paths in the affected wheels: a credential collector launched through a path extension, and a Unix-oriented loader persisted through site-specific configuration. The collector targeted authentication material across developer tools, AI applications, cloud environments, browsers, and infrastructure. A separate database module attempted to read selected credential and model-configuration records from the LiteLLM proxy.

Endpoint observations on Windows and macOS matched the recovered collector’s discovery, encryption, and outbound-connection behavior. In one Windows example, a routine Python invocation to install an unrelated dependency activated the collector. This distinction matters for response: investigators should not start Python or pip inside a suspect environment to determine whether the malicious package is present.

This blog explains the startup mechanisms, the credentials the payload could reach, and the evidence defenders can use to investigate exposure. It also provides Microsoft Defender detection information, advanced hunting queries, and recovery guidance. Removing the package or a release tag is not sufficient recovery. Organizations must address the affected Python environment, any surviving processes, and credentials accessible to the compromised identity.

Attack overview

LiteLLM is commonly deployed as a gateway between applications and model providers. In that position it may have access to model-provider API keys, database connection strings, workload identities, routing configuration, and tenant policy data. The same package is also used on developer workstations, build agents, test systems, and containers, which widened the set of environments that could be exposed by the compromised release.

According to LiteLLM maintainers, stolen developer GitHub credentials were used to alter the release workflow and redirect it to the lookalike repository Berri-AI/litellm rather than the legitimate BerriAI/litellm repository. A credential associated with another developer account was then used to satisfy a production approval step. Microsoft has not independently determined how the attacker first accessed the upstream environment or obtained those credentials.

The compromised package used Python startup mechanisms to execute malicious code automatically, meaning exposure was not limited to systems actively using a LiteLLM gateway. Developer workstations, continuous integration and continuous delivery/deployment (CI/CD) agents, test environments, containers, and other systems that started Python with the affected package installed could also execute the payload. The malicious code supported credential collection and, on Unix-based systems, retrieval and execution of additional Python code.

Diagram showing compromised LiteLLM 1.107.0 installing Python startup files that automatically launch a credential collector. Stolen developer, cloud, browser, SSH, environment, and LiteLLM database data is encrypted and sent to an attacker-controlled endpoint. An optional Unix path can retrieve and execute additional Python code; this activity was not confirmed.
Figure 1: Compromised LiteLLM 1.107.0 execution flow.

1. Compromised package distribution

The compromised LiteLLM 1.107.0 release delivered malicious Python startup files to environments where the package was installed.

2. Automatic payload execution

Python startup processing launched the credential collector without requiring the application to actively use LiteLLM gateway functionality.

3. Credential and sensitive-data collection

The collector targeted developer credentials, cloud credentials, browser data, SSH material, environment variables, and LiteLLM database data accessible to the affected process.

4. Encryption and exfiltration

Collected data was encrypted and transmitted to an attacker-controlled endpoint.

5. Conditional retrieval and execution of additional code

On Unix-based systems, the payload supported retrieving and executing additional Python code, although this activity was not confirmed.

Technical details

Compromised package distribution and automatic payload execution

The compromised wheel packaged cook.pth, cook.py, and sitecustomize.py under litellm-1.107.0.data/purelib/. During installation, these files were relocated into the Python environment’s library directory, outside the normal litellm application directory. This placement enabled execution through Python’s normal site initialization, which processes executable import statements in .pth files and later attempts to import the sitecustomize module.

The first execution path began with the single executable line in cook.pth: “import cook”. This loaded cook.py, whose wrapper Base64-decoded and zlib-decompressed an embedded Python program before executing the recovered source. The program identified itself as PRIVCOLLECT and performed credential collection in a daemon thread.

Python code checks the PRIVCOLLECT_ACTIVE flag, then launches the credential collector in a daemon thread or synchronously.
Figure 2. The executable .pth line imports cook, and the recovered collector starts a daemon thread after checking its inherited environment flag.

Before starting the thread, the collector checked the inherited PRIVCOLLECT_ACTIVE environment variable. A nonempty value caused it to return; otherwise, it set the flag, limiting duplicate collection in descendant processes. After an upload returned HTTP 200, it attempted to write /tmp/.pc_once_72129118c59f5636c0bb. These duplicate-suppression gates were not containment controls: startup alone did not prove collection or upload completed, because a short-lived process could exit before the thread finished, while write failures or temporary-storage changes could leave the marker absent.

Python code decodes and executes an embedded Base64- and zlib-encoded payload. The recovered Linux collector configuration specifies an upload endpoint and RSA key, and enables asynchronous collection of system, browser, SSH, shell-history, and cloud-credential data.
Figure 3. Encode Cook.py file and decoded PRIVCOLLECT credential Stealer configuration.

A second startup mechanism used sitecustomize.py, providing a separate Unix-oriented execution path with an embedded collector and functionality to retrieve and execute additional Python code from a remote host. Remote retrieval and execution through this path were not confirmed.

Together, these mechanisms extended potential exposure beyond active LiteLLM deployments: simply starting Python in an affected environment could activate the malicious code, even when LiteLLM itself was never imported. Because the startup files resided outside the litellm application directory, removing only the application files could leave the malicious startup components behind.

Credential and sensitive-data collection

The recovered collector was designed to gather sensitive authentication material across developer tools, AI applications, cloud environments, browsers, and infrastructure. It runs multiple collection modules sequentially with independent error handling, allowing collection to continue even when individual targets are unavailable or inaccessible.

TargetRecovered collection behavior
Developer and AI toolsReads selected authentication and configuration files for AI assistants, integrated development environments (IDEs) , GitHub Copilot, VS Code, and MCP integrations. Collects fixed paths and top-level JSON files in selected tool directories under a collection budget.
Source control and package ecosystemsSearches Git credentials, package-manager configuration, selected dotenv files, and private-key extensions. Shallow directory walks and file-size limits constrain these searches.
Cloud and workload credentialsReads AWS, Azure CLI, and Google Cloud configuration or credential caches; Kubernetes service-account files; Docker configuration; and mounted secrets. It also attempts AWS and GCP metadata credential retrieval.
Browsers and user historiesAccesses Chromium-family and Firefox credential-related data and browsing history, plus shell, database-client, and interactive-tool histories. Password decryption is platform- and format-dependent.
Process environmentsCollects its own environment and, on Linux, other process environments readable through procfs. This can expose secrets beyond variables explicitly configured for the LiteLLM process.
Private keys and infrastructureTargets readable Secure Shell (SSH) material and selected GNU Privacy Guard (GPG), Transport Layor Security (TLS), CI/CD, Vault, and infrastructure-tool configuration. A target appearing in the code does not establish successful access.
LiteLLM proxy dataWhen its prerequisites are satisfied, starts a Python child using Prisma to read selected fields from two proxy database tables, with a 500-row limit for each query

Encryption and exfiltration

After collection, the payload serializes module results and host metadata as JSON. Each run generates a 32-byte AES key and a 16-byte initialization vector. AES-256-CBC encrypts the collection document; an embedded 4,096-bit RSA public key wraps the AES key using OAEP. The OpenSSL path tries SHA-256 and then SHA-1 for OAEP, and the resulting metadata records the selected digest.

Python code encrypts collected data with AES, wraps the key with RSA, packages the results in a gzip archive, and uploads it.
Figure 4. The collector generates a fresh AES key and IV, wraps the key with RSA, and packages the encrypted collection in a gzip tar archive before attempting upload. Selected code excerpts are wrapped for readability.

The collector places three members in a gzip-compressed tar archive: data.bin, containing the initialization vector (IV) and encrypted collection; key.bin, containing the wrapped AES key; and hdr.json, containing plaintext envelope metadata. It then attempts an HTTP POST to hxxp://www[.]litellm[.]dev/healthcheck, using application/octet-stream, a fixed browser-like User-Agent, and a body checksum in an X-SHA256 header. The upload routine retries and treats only HTTP 200 as success.

The OpenSSL backend creates temporary directories beginning with .pc_e_, stages input and output files and removes them after use.

Conditional retrieval and execution of additional code

In addition to the credential collector, the compromised package contained a separate Unix-oriented loader in sitecustomize.py, designed to retrieve and execute additional Python code. When Python starts, the loader takes an exclusive lock on /tmp/remote_code_loader.lock so that only one instance runs per host and detaches into the background. Each cycle reads a GitHub-hosted domain.txt file, which acts as a mutable pointer to an attacker-controlled server.

Figure 5. The remote-loader path checks the pointer and DNS before retrieving code, then compiles and executes the response without a content-signature check.

If a valid server address is returned and successfully resolved, the loader is designed to request /codepy from that server, compile the returned content, and execute it as Python code within the affected environment. This gives the attacker a mechanism to change the second-stage payload without publishing another compromised LiteLLM package. This loader is separate from the credential collector delivered directly in the compromised package.

At the time the cited researchers examined domain.txt, it was empty and no second-stage retrieval or execution was confirmed. Because the file could be changed, the loader remained a re-armable remote-code execution mechanism.

Mitigation and protection guidance

Microsoft recommends the following actions for organizations that installed, mirrored, or built images with LiteLLM 1.107.0:

  • Find and contain every affected copy. Identify LiteLLM 1.107.0 across installed environments, uv and pip caches, internal package mirrors, lock files, build outputs, and container images. Scope mutable container tags and the relevant exposure windows once validated and compare artifacts with the customer-ready hashes in the indicators of compromise section. For background, see secure software supply chain practices and Docker image digests. Digests are preferable to mutable tags because they identify immutable image content.
  • Prevent Python execution and investigate from outside the environment. Isolate affected developer workstations, build agents, test systems, containers, and AI gateway hosts. Where operationally safe, stop running Python processes and prevent automation from restarting them. Do not run python, pip, or other commands that invoke the affected interpreter during evidence collection; inspect the environment with trusted tools from a known-clean system. Python normally processes site configuration, including executable import lines in .pth files, during initialization.
  • Rebuild from verified artifacts. Confirm that cook.pth, cook.py, and sitecustomize.py were removed from the environment library path. Rebuilding is more reliable than assuming that deleting the litellm directory cleaned the top-level startup files.
  • Rotate reachable credentials from a known-clean machine. Include model-provider keys, cloud and workload credentials, CI/CD secrets, source-control and registry tokens, SSH and GPG keys, AI coding-tool tokens, and browser sessions available to the affected identity. On proxy hosts, include stored provider credentials and DATABASE_URL. Revoke affected identity sessions rather than assuming password or key rotation immediately invalidates every active token or application session. See revoke user access in Microsoft Entra ID.
  • Correlate before declaring compromise. Combine file hashes, Python process ancestry, .pc_e_ cryptographic staging, network destination, workload identity, and subsequent cloud or identity use. Do not use package presence or a generic filename as the sole verdict.
  • Restrict outbound access. Developer workstations, build agents, test systems, containers, and AI gateway hosts should not have unrestricted outbound HTTP access unless required. Route outbound traffic through managed egress controls, deny unnecessary destinations, and allowlist required services. See control outbound internet access from Azure.
  • Enable Microsoft Defender for Endpoint protections. Onboard supported developer workstations, build agents, and AI gateway servers to Microsoft Defender for Endpoint, and enable Microsoft Defender Antivirus real-time and cloud-delivered protection where supported. See configure always-on protection and configure cloud protection.

Microsoft Defender XDR detections

As of October 22, 2026, the following Microsoft Defender Antivirus signatures and Microsoft Defender for Endpoint alerts were available for activity associated with the compromised LiteLLM 1.107.0 release. Detection names and availability may change as protection is updated.

Tactic Observed activity Microsoft Defender coverage
Initial Access / ExecutionMalicious components associated with the compromised package are detected and blocked; related suspicious script and network activity is identified across endpoints and cloud workloads.Microsoft Defender Antivirus
– Trojan:PyPI/Stealer.SA
– Trojan:PyPI/LiteLlmSupplyChain.A
– Trojan:PyPI/LiteLlmSupplyChain.B
– Backdoor:PyPI/LiteLlmSupplyChain.C

Microsoft Defender for Endpoint
– Suspicious script launched
– Suspicious network connection observed
Command and Control / Credential AccessCredential-like data is staged by Python and followed by network activity to a public destination, including malicious-domain lookups and OpenSSL activity associated with the compromise.Microsoft Defender for Endpoint
– Possible theft of passwords and other sensitive web browser information
– Suspicious OpenSSL command launch

Microsoft Defender for Cloud
Microsoft Defender for Cloud triggers below detections for related activity in Azure App Service and Kubernetes workloads:

– OpenSSL activity associated with possible LiteLLM compromise detected
– DNS lookup of a known malicious domain
Vulnerability ManagementDevices vulnerable to this security issue are surfaced for remediation.Microsoft Defender Vulnerability Management
– Endpoints exposure tab in the Microsoft Defender portal: TVM-2026-0003

Threat intelligence reports

Microsoft customers can use the following reports in Microsoft products to get the most up-to-date information about the threat actor, malicious activity, and techniques discussed in this blog. This report provides intelligence, protection information, and recommended actions to prevent, mitigate, or respond to associated threats found in customer environments.

Microsoft Defender XDR Threat analytics

Inside the LiteLLM 1.107.0 supply chain compromise: Credential theft through Python startup hooks

Advanced hunting

These queries support investigation of the stages discussed above. Select the appropriate lookback in Defender XDR and correlate results with environment, process and identity evidence. They are investigation leads, not standalone verdicts.

Connections to the collector domain

Normalize URL/hostname observations before matching the campaign domain. The query rejects suffix lookalikes such as www[.]litellm[.]dev[.]example; a match still needs process and workload context.

DeviceNetworkEvents
| extend UrlForParsing = iff(RemoteUrl contains "://",
    RemoteUrl, strcat("http://", RemoteUrl))
| extend RemoteHost = trim_end(@"\.",
    tolower(tostring(parse_url(UrlForParsing).Host)))
| where RemoteHost in ("www.litellm.dev", "litellm.dev")
| project Timestamp, DeviceId, DeviceName, ActionType,
    RemoteUrl, RemoteIP, RemotePort, InitiatingProcessFileName,
    InitiatingProcessId, InitiatingProcessCreationTime, ReportId

Known startup-file hashes

The four hashes cover LF and CRLF variants. A missing SHA-256 field limits this hunt; a generic filename is not an equivalent match.

DeviceFileEvents
| where SHA256 in~ (
    "9dd0a3926f96a37eb86cf1ee2310d9be93139cc4ebef3ef9e2efe9531390be25",
    "03ac2a8b752605d1d7710979c17ff18b03dd978203ba23ba97fd8ce3d6f897ea",
    "34bef04fe88ac9d0aae0475630b1738681d15b94f233ac8aa46eacf5968305fa",
    "b6122440d0d9cb1eb1ade9933f49214da8c31288de7710c076c2680dfa528465",
    "7f191632e7320705d154b85204f1ae546b543acbd7e8861229b76f5042b92bdb",
    "84dc8c82c0a4a4a62552ef826b49fcc86d1a5c4a5d0f2c06665723f93d129d7d")
| project Timestamp, DeviceId, DeviceName, ActionType,
    FileName, FolderPath, SHA256, InitiatingProcessFileName,
    InitiatingProcessId, InitiatingProcessCreationTime, ReportId

Inline database-collection program

Look for the sensitive table/field pair together with the query API, serialization and complete output-suppression pattern. Legitimate exports may overlap. The recovered parent’s /proc prerequisite limits its applicability; raw arguments are omitted because they can contain a database secret.

DeviceProcessEvents
| where FileName startswith "python" or FileName startswith "platform-python"
| where strlen(ProcessCommandLine) <= 4096
| where ProcessCommandLine contains_cs "-c "
| where (ProcessCommandLine contains_cs "LiteLLM_CredentialsTable"
        and ProcessCommandLine contains_cs "credential_values")
    or (ProcessCommandLine contains_cs "LiteLLM_ProxyModelTable"
        and ProcessCommandLine contains_cs "litellm_params")
| where ProcessCommandLine contains_cs "query_raw"
| where ProcessCommandLine contains_cs "json.dumps("
    or ProcessCommandLine contains_cs "json.dump("
| where ProcessCommandLine contains_cs "os.devnull"
    and ProcessCommandLine contains_cs "os.dup2"
| project Timestamp, DeviceId, DeviceName, FileName,
    ProcessId, ProcessCreationTime, InitiatingProcessFileName,
    InitiatingProcessId, InitiatingProcessCreationTime, ReportId

Collector-like encryption staging

The staging prefix plus encryption operation identifies a behavioral lead, not an upload or a uniquely malicious OpenSSL invocation. Alternate backends are outside this query, and key-bearing arguments are not projected.

DeviceProcessEvents
| where FileName in~ ("openssl", "openssl.exe")
| where ProcessCommandLine contains_cs ".pc_e_"
| where (ProcessCommandLine contains_cs " enc "
        and ProcessCommandLine contains_cs "-aes-256-cbc")
    or ProcessCommandLine contains_cs " pkeyutl "
    or ProcessCommandLine contains_cs " rsautl "
| extend CryptoOperation = iff(
    ProcessCommandLine contains_cs " enc ", "AES packaging", "RSA wrapping")
| project Timestamp, DeviceId, DeviceName, FileName, CryptoOperation,
    ProcessId, ProcessCreationTime, InitiatingProcessFileName,
    InitiatingProcessId, InitiatingProcessCreationTime, ReportId

Vulnerability/Posture Check | Is the device potentially exposed to the affected Litellm?

Use this query to identify devices potentially exposed to TVM-2026-0003. A match indicates potential exposure, not confirmed exploitation or compromise.

DeviceTvmSoftwareVulnerabilities
| where CveId == "TVM-2026-0003"

CloudProcessEvents query to detect encryption before exfiltration

Identifies OpenSSL public-key encryption using /tmp/.pc_ staging paths, consistent with key wrapping before potential exfiltration.

CloudProcessEvents
| where ProcessName == 'openssl' and ProcessCurrentWorkingDirectory has_any ('/runner/','/app','/tmp/')
    and ProcessCommandLine has_all ('pkeyutl','-encrypt','-pubin') and ProcessCommandLine contains '/tmp/.pc_'

MITRE ATT&CK techniques observed

Microsoft mapped the following techniques based on observed activity and analysis of the recovered malicious components; individual entries note where behavior was not confirmed. For standard industry documentation, refer to the MITRE ATT&CK framework.

Initial Access

Persistence

Execution

Defense Evasion

Credential Access

Discovery

Collection

Command and Control

Indicators of compromise

URLs are defanged. Use precise roles and context rather than blocking shared infrastructure indiscriminately.

IndicatorTypeRole
www[.]litellm[.]devDomainExfiltration Domain
hxxp://www[.]litellm[.]dev/healthcheckURLExfiltration URL
hxxps://raw[.]githubusercontent[.]com/letters9813/pythonclient-test/main/domain.txtURLC2 dead-drop URL
9dd0a3926f96a37eb86cf1ee2310d9be93139cc4ebef3ef9e2efe9531390be25SHA-256cook.py, variant
03ac2a8b752605d1d7710979c17ff18b03dd978203ba23ba97fd8ce3d6f897eaSHA-256cook.py, Windows wheel variant
34bef04fe88ac9d0aae0475630b1738681d15b94f233ac8aa46eacf5968305faSHA-256sitecustomize.py, variant
b6122440d0d9cb1eb1ade9933f49214da8c31288de7710c076c2680dfa528465SHA-256sitecustomize.py, Windows wheel variant
7f191632e7320705d154b85204f1ae546b543acbd7e8861229b76f5042b92bdbSHA-256cook.pth
84dc8c82c0a4a4a62552ef826b49fcc86d1a5c4a5d0f2c06665723f93d129d7dSHA-256cook.pth, variant
/tmp/remote_code_loader.lockfileLock file created by the background loader.
/tmp/.pc_once_72129118c59f5636c0bbfileMarker written after stolen data was sent.
7598727f209d717041db37f7dca271d3a7d328a279890e0e1d55375729aeb86dSHA-256litellm-1.107.0-cp310-abi3-macosx_10_12_x86_64.whl
0aaf7ba346d41ef2f40390436738b001180d5a1c03aa093f121078a9969d9a1aSHA-256litellm-1.107.0-cp310-abi3-macosx_11_0_arm64.whl
668169d35b87bf51324080390b1b1c5ab12bd335cfe5f1a99e3689abd5e02ae6SHA-256litellm-1.107.0-cp310-abi3-manylinux_2_28_aarch64.whl
462d0c9f67ca522d9e0e4acd245e90b36ce0d5353604a66bb7c43a1ec4a6fcf7SHA-256litellm-1.107.0-cp310-abi3-manylinux_2_28_x86_64.whl
c2e32d0ce2548aa662c18bf5001911a79fe5b30cf8357132275add02fdcde054SHA-256litellm-1.107.0-cp310-abi3-musllinux_1_2_aarch64.whl
1bbce8caa94f01c0aaa0b7ddae51553a8a32e1ce53d96d44fe583272aff7ad00SHA-256litellm-1.107.0-cp310-abi3-musllinux_1_2_x86_64.whl
12d4ccc5c6f8d35cf4f2cf233b7f3e418e863e657d81ff5f5fc9e210005b9484SHA-256litellm-1.107.0-cp310-abi3-win_amd64.whl

References

Learn More

For the latest security research from the Microsoft Threat Intelligence community, check out the Microsoft Threat Intelligence Blog.

To get notified about new publications and to join discussions on social media, follow us on LinkedIn, X (formerly Twitter), and Bluesky.

To hear stories and insights from the Microsoft Threat Intelligence community about the ever-evolving threat landscape, listen to the Microsoft Threat Intelligence podcast.

Review our documentation to learn more about our real-time protection capabilities and see how to enable them within your organization.  

The post Inside the LiteLLM 1.107.0 supply chain compromise: Credential theft through Python startup hooks appeared first on Microsoft Security Blog.

From open lures to cloaked gates: How a macOS ClickFix campaign learned to hide

Microsoft Threat Intelligence observed a macOS ClickFix campaign distributing infostealers, including MacSync and Atomic Stealer (AMOS), through a large cluster of look-alike domains. The campaign evolved from broadly serving ClickFix lures to using a server-side browser-fingerprinting gate that shows the lure primarily to visitors whose environment appears consistent with a genuine macOS browser. This cloaking limits visibility for crawlers, sandboxes, and some automated analysis workflows. The blog details the domain pattern, fingerprinting checks, infection chain, detection coverage, and hunting pivots that defenders can use to identify related activity.

Activity overview

Microsoft Threat Intelligence has been tracking a macOS ClickFix operation that distributes information-stealing malware through a large family of algorithmically named domains. Over several weeks of monitoring, Microsoft observed a notable shift in tradecraft: the same infrastructure moved from openly serving the malicious command in the served page’s HTML source to concealing the lure behind a server-side fingerprinting gate that reveals the payload only to visitors the server assesses as a genuine macOS target. The chain ultimately delivers information stealers such as MacSync or Atomic Stealer (AMOS).

This activity is consistent with the broader shift in macOS ClickFix tradecraft that Microsoft Threat Intelligence previously documented, in which threat actors instruct users to run Terminal commands that retrieve remotely hosted content rather than the traditional approach of delivering a disk image for manual installation. The cluster described here is notable for two reasons: its domains are mass-produced by a recognizable name generator, and it adopted server-side cloaking on existing infrastructure, giving defenders a clear before-and-after view of the same operation.

In this blog, we describe the campaign’s domain-generation pattern, the two delivery phases we observed, the fingerprinting gate that now fronts the infrastructure, and the end-to-end infection chain. We also provide hunting guidance, mitigation recommendations, and defanged indicators of compromise.

How ClickFix works 

ClickFix is a social-engineering technique where attackers persuade users to copy and run a command in Terminal instead of downloading a traditional macOS application. The lure usually appears as a fake verification step, software update, download error, or CAPTCHA, with the command disguised as something required to complete the action. Because execution starts from a user-run Terminal command rather than a downloaded app bundle, the flow can avoid parts of the normal macOS application trust path, including quarantine handling, code-signing evaluation, and notarization checks typically applied to downloaded applications.

In this campaign, ClickFix remains the delivery mechanism, but the important change is that the lure is no longer shown to every visitor. The page first profiles the visitor through a browser-fingerprinting gate and primarily requests consistent with a genuine macOS browser environment receive the fake “Download for macOS” page and copied Terminal command.

Figure 1a – The counterfeit “Download for macOS” page served to a qualifying visitor by a cloaked gate (apricotfilepoint[.]com). The page displays a forged “Verified Publisher” badge and offers a one-click Copy of an obfuscated curl one-liner.

Delivery is conditional. During analysis, the same URLs returned different content to different requests. In some case the macOS ClickFix lure, and in others an apparently benign decoy page.

In our testing, a request presenting a Windows browser received a decoy page such as a fake browser-extension or VPN landing page (Figure 1b) or a page impersonating an unrelated business such as a logistics and freight-forwarding company rather than the ClickFix lure. Because this decision is made server-side on a per-request basis, a given scan or visit may receive benign or decoy content and still be interacting with malicious infrastructure, so an apparently benign or look-alike response does not mean the domain is safe. We examine how the gate evaluates each request later in this post.

Figure 1b – A decoy page (a fake “Urban VPN Proxy” browser extension landing page) returned to non qualifying requests on the same domain (apricotfilepoint[.]com).

Campaign overview

The key change in this campaign is not the ClickFix lure itself, but the new layer placed in front of it. Microsoft Threat Intelligence confirmed more than 250 ClickFix front-end domains during the tracking window, and many followed a repeated naming pattern using the token “file” with dictionary-style words, such as filecopperbasket, filevelvettractor, fileoceanhammer, and filemarblegarden.

Some related domains place “file” token in the middle or at the end, such as applefilevault, bananafastfile, and orangesmartfile, while others omit it completely, such as cloudsendhub and syncdatavault. Defenders should treat the naming pattern as a hunting pivot, not a complete signature. The stronger signal is the combination of dictionary-style domains, shared infrastructure behaviour, and the fingerprinting gate that controls who sees the ClickFix lure. This naming pattern is useful for clustering and hunting, but it is not the main story. The more important behaviour is that these domains now serve a browser-fingerprinting gate before showing any malicious content.

ClickFix moved from open pages to fingerprinting gates

In its earlier phase, the campaign’s domains served the lure directly. Retrieving one returned a “complete your download in Terminal” page with the malicious command present in the HTML. A scanner that does not execute JavaScript could recover the entire attack from the page source, including: the macOS paste-to-Terminal instructions, clipboard-write logic, obfuscated shell command, and encoded staging URL. Because the command was embedded in the served page, the domains were readily identifiable from passive data and static content matching.

The same infrastructure that previously exposed its ClickFix lure directly to visitors has evolved to employ a server-side fingerprinting gate. Rather than immediately presenting the malicious content, affected domains now return a minimal page containing only a lightweight JavaScript profiling routine(~2.5 KB size). To both casual visitors and automated scanners, the site may appear blank, inactive, or apparently benign.  In reality, the page serves as an evaluation layer that determines whether a visitor should be shown the ClickFix lure.

Across Microsoft Threat Intelligence’s investigation of this domain cluster, the outcomes were consistent. Simple crawlers received an empty, parked-looking page. JS-capable crawlers and sandbox environments that failed fingerprinting checks were served apparently benign decoy page, and requests presenting a genuine macOS browser fingerprint were shown the ClickFix lure.

Figure 2 – Earlier open-lure delivery compared with the current fingerprinting-gated delivery flow.

The fingerprinting gate

The gate profiles each visitor using a combination of browser, hardware, and runtime attributes, which are submitted to the server for evaluation. The following sections break down the categories of signals collected.

Browser profiling and environment collection

The first stage builds a browser fingerprint by collecting browser and page details from six objects exposed to the page: navigator, screen, window, document, location, and console. From navigator, it captures values such as platform, for example, “MacIntel”, user agent, language, vendor, and plugins, which establish the visitor’s claimed device and browser identity.

Display values from screen and window, including screen size, color depth, window dimensions, and pixel ratio, provide consistency signals for whether that identity is consistent with a real, non‑virtualized Mac environment. Page context from document and location, including title, referrer, character set, URL, and host, helps tie the fingerprint to the delivery context. The console object is also enumerated as part of the runtime surface and later helps identify developer tools or automated log-capturing environments. These values are merged into a single fingerprint object tagged with mode: “php” and later submitted back to the server for evaluation.

Figure 3a – The gate collects browser, system, and environment characteristics from multiple browser objects to build a visitor fingerprint.

Hardware validation

The gate then performs additional validation to determine whether the visitor resembles a genuine macOS user. One notable check uses WebGL, a browser graphics API normally used to render 2D and 3D content, to retrieve graphics-processing details from the visitor’s device. In this campaign, those WebGL-derived GPU signals help distinguish real Apple hardware from virtualized, emulated, software-rendered, or sandboxed environments before the server decides whether to return the ClickFix lure.

Figure 3b – WebGL-derived GPU signals can help distinguish likely Apple hardware from virtualized, emulated, software-rendered, or sandboxed environments.

Environment and behavioral checks

Additional probes evaluate characteristics such as timezone configuration, touch-input support, and whether the page is running inside an embedded frame. These signals help identify uncommon execution contexts that may indicate automated analysis or monitoring infrastructure.

The script records three signals:

  • timezoneOffset reads the system’s local timezone offset. Unusual or inconsistent values can contribute to identifying hosted infrastructure, sandbox environments, or otherwise atypical execution context.
  • frame checks whether the page is running inside an iframe. While common in legitimate scenarios, embedded execution contexts can also be associated with crawlers, analysis tools, and other automated environments, making this a useful qualification signal.
  • touchEvent checks for touch-input support. On desktop macOS systems, touch support is generally uncommon; unexpected touch capabilities can contribute to identifying an emulated, spoofed, or otherwise atypical environment.

Together, these checks help the gate distinguish a normal macOS desktop browser session from framed, headless, mobile, sandboxed, or automated environments before the server decides what content to return.

Figure 3c – Additional checks evaluate environmental attributes that can help differentiate legitimate users from automated systems.

Anti-analysis techniques

The gate also incorporates checks designed to detect browser instrumentation, automation frameworks, and modified browser behavior. Rather than simply determining whether a visitor is a bot, these probes appear intended to identify environments commonly used by researchers, crawlers, and security-analysis platforms. The implementation details described here are intended to help defenders recognize and detect gate behavior in malicious traffic-distribution infrastructure.

Figure 3d – The gate performs checks intended to identify browser instrumentation and automated analysis environments.

Two checks stand out. The first is a toString() counter. The script creates a temporary function whose toString() method increases a counter, then writes that function to the console. In a normal browser, this counter usually remains unchanged. However, if the developer console is open, or if a headless or log-capturing tool serializes console output, the function may be converted to a string, causing the counter to increase.

The second is a prototype-tamper probe built around a normal browser capability check. The gate calls canPlayType(“video/mp4”), which normally checks whether the browser supports MP4 playback. Here, that check is repurposed as a tripwire. A genuine browser handles the codec check natively and silently, but some automated or stealth browsers fake codec support in JavaScript. If that JavaScript path calls the hooked Array.prototype.includes, the gate sets the proto:true signal and flags the environment as potentially instrumented or automated.

Fingerprint submission

Once profiling is complete, the collected attributes are packaged and silently submitted back to the same server for evaluation. This process occurs without any user interaction or visible page content.

Figure 3e – Collected fingerprint data is submitted to the server, which determines whether the visitor qualifies to receive the ClickFix lure.

The following is the sample fingerprint the client sends to the server (values are representative and defanged):

Server-side victim selection

With the fingerprinting logic in place, the malicious content is no longer present in the initial page shown to the visitor. Instead, the server withholds the ClickFix lure until it receives and evaluates the submitted fingerprint, then returns one of two responses:

  • A bot, crawler, sandbox, virtual machine, unexpected geography, or unexpected browser receives a blank page, a benign decoy, or no content.
  • A genuine Mac and browser in an expected context receive the ClickFix lure: the counterfeit “Verified Publisher / Download for macOS” page and its poisoned one-liner. The targeting is primarily environment-based: genuine macOS users in an expected browser and request context receive the ClickFix lure.

This is a Traffic Distribution System (TDS) gate. We call it a TDS because the payload is delivered by server-side, on demand, only to visitors the operator selects security crawlers, researchers, and sandboxes are served no malicious content. This gating can make automated detection and analysis more difficult because those tools may see only an apparently benign response even though the infrastructure can deliver the ClickFix lure to selected macOS visitors.

Figure 4 – Server-side fingerprint evaluation and possible responses for selected and non-selected visitors.

Inside the infection chain: from gated lure to AMOS

The individual techniques used by the gate are not inherently malicious or novel. Browser fingerprinting, hardware validation checks, and Traffic Distribution System (TDS)-style visitor filtering are common in anti-abuse systems and have previously appeared in exploit-kit and malvertising ecosystems. What distinguishes this activity is how these techniques are integrated into a ClickFix campaign. Rather than immediately presenting a malicious command, the actor performs server-side victim qualification before revealing the lure, reducing visibility to researchers and automated security systems while maintaining access to intended macOS targets.

Using a qualified macOS target, we analyzed the complete infection chain. The activity began on a file<word><word>[.]com domain hosting the fingerprinting gate, which returned the counterfeit Download for macOS page (Figure 1a). A non-qualifying request received little or no visible content. The page uses GitHub-themed branding to mimic a legitimate software download experience; the branding is spoofed and does not indicate any compromise of GitHub.

When the victim runs the Terminal command, the campaign retrieves and executes a remote script from a /curl/<id> URL. The chain then progresses through multiple script stages before ultimately downloading and launching Atomic Stealer (AMOS), an information stealer that harvests credentials, browser and cryptocurrency wallet data, authentication stores, and other sensitive files before exfiltrating them. We detailed AMOS delivery across multiple macOS ClickFix lures in earlier research.

Because delivery is restricted to qualified visitors, the fingerprinting gate is often a more reliable hunting target than the downstream malware. Systems that inspect page content without executing client-side JavaScript can observe the gate logic directly, while environments that fail qualification are redirected to apparently benign or no content. Because these characteristics also appear in legitimate anti-bot implementations, evaluate combinations rather than single indicators. Useful signals include self-submitting fingerprinting forms, hidden fingerprint data fields, artifacts such as the mode:”php” parameter, and domains following the observed file naming convention; correlating several of these improves confidence and reduces false positives.

Mitigation and protection guidance

Organizations can apply the following recommendations to reduce exposure to this and similar macOS ClickFix campaigns:

  • Educate users. Reinforce that no legitimate download, CAPTCHA, or verification step requires pasting a command into Terminal.
  • Monitor Terminal usage. Alert on Terminal or shell sessions that spawn curl, base64, gunzip, or osascript, particularly when initiated shortly after web browsing.
  • Detect native-tool abuse. Flag unusual sequences of macOS utilities such as curl piped to zsh, base64 -d, and xattr -c immediately preceding chmod +x.
  • Inspect outbound downloads. Monitor curl activity that retrieves encoded or compressed payloads from newly registered or low-reputation domains, including /curl/<hex-id> request paths.
  • Protect credential stores. Detect unauthorized access to keychain items, browser credential databases, SSH keys, and cryptocurrency wallet data.
  • Monitor data staging. Alert on the creation of archives of sensitive artifacts followed by HTTP POST exfiltration.
  • Block on infrastructure, not just front-end domains. Where validated, prioritize blocking known shared back end and staging hosts (for example, malware-c2 and the /curl/<id> staging hosts) over individual disposable front-end domains.
  • Hunt the generation pattern. Where feasible, alert the file<word><word> domain pattern rather than maintaining a list of individual domains.

On macOS 26.4 and later, Apple introduced a mitigation that displays a warning when a user attempts to paste a potentially malicious command into Terminal, directly addressing the ClickFix delivery mechanism.

When a user attempts to paste a potentially malicious command into Terminal, they will now see the following prompt:

Possible malware, Paste blocked

Your Mac has not been harmed. Scammers often encourage pasting text into Terminal to try and harm your Mac or compromise your privacy. These instructions are commonly offered via websites, chat agents, apps, files, or a phone call.

Microsoft Defender XDR detections

Tactic Observed activity Microsoft Defender coverage 
 Initial Access Malicious webpage Microsoft Defender for SmartScreen
SmartScreen Detection Blocks webpage (Figure 5)
 Execution   User copies, pastes, and runs encoded instructions. The instructions are decoded, executable files are created from remote attacker infrastructure, and the malware implant is executed.Microsoft Defender for Endpoint
– Behavior:MacOS/SuspAmosExecution
– Malicious file execution  
– Behavior:MacOS/SuspOsascriptExec
– Malicious osascript execution
– Behavior:MacOS/SuspDownloadFileExec
– Behavior:MacOS/SuspInfoExfil
– Behavior:MacOS/SuspiciousActiviyGen.AE
– Suspicious file download and execution
Credential access Keychain extraction Behavior:MacOS/SuspKeyChainCopy.AB
Collection & Exfiltration  Browser data, crypto wallets, keys etc.  – Behavior:MacOS/SuspInfostealExec
– Behavior:MacOS/SuspCredCopy
– Behavior:MacOS/SuspPassSteal

Microsoft Defender SmartScreen displays a warning message to Microsoft Edge users when they visit a ClickFix landing page:

Figure 5. Microsoft Defender SmartScreen flagging a ClickFix webpage.

Microsoft Security Copilot  

Security Copilot customers can use the standalone experience to create their own prompts or run the following prebuilt promptbooks to automate incident response or investigation tasks related to this threat: 

  • Incident investigation
  • Microsoft User analysis  
  • Threat actor profile  
  • Threat Intelligence 360 report based on MDTI article  
  • Vulnerability impact assessment

Note that some promptbooks require access to plugins for Microsoft products such as Microsoft Defender XDR or Microsoft Sentinel.

Advanced hunting

The following query is an illustrative starting point. Validate table/column names and adjust the time range and indicators for your environment before running.

Known-IOC network sweep (mirrors a standard IOC hunt; populate from the IOC table and refresh as domains rotate)

let lookback = 30d;
let SuspiciousDomains = 
dynamic(["lemonfilewave.com","limefilescope.com","mangocloudfile.com"]);
DeviceNetworkEvents   
| where Timestamp >ago(lookback) 
| where RemoteUrl has_any (SuspiciousDomains)

Indicators of compromise (IOC)

Indicator Type Description 
applefilevault[.]comDomainClickFix Webpage
apricotfilepoint[.]comDomainClickFix Webpage 
bananafastfile[.]comDomainClickFix Webpage
cloudfilebridge[.]comDomainClickFix Webpage
filecedarwallet[.]online.DomainClickFix Webpage
filecopperbasket[.]sbsDomainClickFix Webpage
filecrimsonsignal[.]onlineDomainClickFix Webpage
filemarblegarden[.]sbsDomainClickFix Webpage
fileoceanhammer[.]sbsDomainClickFix Webpage
filerubyfolder[.]sbsDomainClickFix Webpage
filevelvettractor[.]sbsDomainClickFix Webpage
lemonfilewave[.]comDomainClickFix Webpage
limefilescope[.]comDomainClickFix Webpage
mangocloudfile[.]comDomainClickFix Webpage
orangesmartfile[.]comDomainClickFix Webpage
syncdatavault[.]comDomainClickFix Webpage
cloudsendhub[.]comDomainClickFix Webpage

References

Learn more

For the latest security research from the Microsoft Threat Intelligence community, check out the Microsoft Threat Intelligence Blog.

To get notified about new publications and to join discussions on social media, follow us on LinkedIn, X (formerly Twitter), and Bluesky.

To hear stories and insights from the Microsoft Threat Intelligence community about the ever-evolving threat landscape, listen to the Microsoft Threat Intelligence podcast.

Review our documentation to learn more about our real-time protection capabilities and see how to enable them within your organization.   

The post From open lures to cloaked gates: How a macOS ClickFix campaign learned to hide appeared first on Microsoft Security Blog.

❌
❌