P.K. SHARMA

Cyber security intelligence, AI governance, practitioner analysis

Corelight says a pinned MCP server ran 15 dependency sets in five weeks; 23 of its 69 packages changed

Corelight says an MCP server set to one release ran 15 different dependency sets in five weeks, with 23 of its 69 packages changing and the configuration untouched. It is one lab workstation and the post reports no compromise.

By · LinkedIn · · 19 min read

23 of 69 packages changed under a release that looked pinned (derived: a third)

Corelight's blog post of 10 November 2026 says one MCP server on an administrator's workstation, "configured to run one specific release, built from one specific commit", "ran with 15 different sets of dependencies" over five weeks, and that "23 of its 69 packages changed versions underneath a release that looked pinned". That is 33.3 percent of the packages (derived: 23 divided by 69). Five weeks is 35 days (derived), so the 15 sets are one every 2.33 days (derived: 35 divided by 15); counted by builds instead, the post's 19 builds in the same five weeks are one every 1.84 days (derived: 35 divided by 19), which the post words as "one every couple of days". The post's one sentence of method: "pinning a package's version doesn't necessarily pin the packages it depends on".

What that does not establish. It does not establish a compromise: the post says "Nothing on that workstation was compromised". It does not say that any of the 15 sets held a malicious or vulnerable package, which 23 packages changed, or that the same drift happens on anyone else's machine. It is one lab, one workstation and, for the five weeks, one community server. The second headline figure, that 23 of 35 reviewed servers have a recommended install that would resolve from a public registry, counts install instructions in two unnamed vendor catalogs and the lab. It does not count running deployments.

Whose numbers. Every count above is Corelight's, from the post's page data published at 23:19 UTC on 10 November 2026 and modified at 23:38 UTC the same night. This site credits Corelight and names no individual. Corelight sells network detection and response products and wrote the post: the lab, the review and the remedies are its own, and the catalog vendors and the Python Package Index are not parties at fault. The saved copy of the post used here was fetched between 07:05 and 07:30 UTC on 13 November 2026.

What Corelight found, in its own order

The workstation's AI coding assistants started their MCP servers with a one step launcher, uvx, from a single configuration line. One was a community MCP server for the network gateway. The author "pinned its seven direct dependencies exactly, and it published a hash-pinned lock file". But the launcher "was installed from the package's declared dependencies, not from the lock file", so "the roughly 60 packages underneath were resolved fresh from PyPI", within whatever version ranges the dependency tree allowed. Seven pinned out of 69 leaves 62 (derived: 69 minus 7); the post says roughly 60, and elsewhere about 70 packages in the tree.

The launcher did not download everything on every launch. It kept a cached environment. The assistant started the server 162 times in one week (about 23 a day, derived: 162 divided by 7), and most of those only checked the Git tag and reused the cache. The cache held 19 builds of the same release and commit over five weeks, and those 19 builds made 15 distinct environments. Twenty three of the 69 packages changed versions, "including the cryptography library, the JSON Web Token library (four versions), and the MCP software development kit itself". The post does not name the other packages or print any version number.

Two more observations carry weight. During the test, an ordinary launch "built a new environment that included two dependencies released since the previous day's build", so the change is something Corelight watched, not only inferred from the cache. And the pattern was not one server: every MCP server launched the same way on the workstation showed it, whether pinned to a release tag, an exact PyPI version or an exact Git commit. "One of the servers that was pinned to a commit had 19 builds and 17 distinct environments", and its MCP framework was "running two major versions ahead of the version in the project's own lock file".

Drawn from Corelight's post of 10 November 2026. Corelight's figures are as printed; the percentages, the 62 and the day counts are derived by this site.

The post is explicit that this is about how the servers were launched, not about the servers: "None of this is a flaw in MCP", and the issue "isn't only specific to MCP": "Any software installed or launched this way behaves in the same fashion". It matters more for MCP servers because they act for a user, so they are often set up with that user's credentials.

The review ledger: 35 servers, 23 with a registry install, and the lab counts

The post's second headline sentence is a count of install instructions: Of the 35 MCP servers reviewed, from two vendor catalogs and its own lab, "23 had a recommended install that would have resolved dependencies fresh from a public registry", either with every launch or with each install or image build. That is 65.7 percent (derived: 23 divided by 35), leaving 12 (derived: 35 minus 23, or 34.3 percent) that the post does not describe. Two things shape how to read it. The words are "would have resolved", a statement about what the recommended install does, not about a deployment seen doing it. And the 23 mix two behaviours, every launch and each install or image build, without saying how many of each. The post names neither catalog, no server, and does not say how many of the 35 came from the lab.

Drawn from Corelight's post of 10 November 2026. The 12, the 65.7 and 34.3 percent are derived by this site. Each lab count is Corelight's, with what it does and does not claim.

The lab counts are separate observations with different windows, which is why this site does not divide one by another. The 162 launches are one week; the 19 builds are five weeks, so a launches per build ratio would compare a week with 35 days. The more than 1,600 connections to 11 management systems are one week across the workstation's MCP servers, so an average per system would mean nothing and is not computed.

Corelight's lab counts as printed, and what each does and does not claim. Source: Corelight, post of 10 November 2026; the last column is this site's reading.

Count (Corelight)What the post ties it toWhat it does not claim
162 launches in one weekOne community MCP server started by the assistant; most only checked the tag.How many launches rebuilt the environment.
19 builds, 15 distinct environments, five weeksThe launcher's cache for the same release and commit.Which of the 15 held a bad package.
23 of 69 packages changedThe cryptography library, the JSON Web Token library (four versions), the MCP SDK among them.The other packages, or any version number.
More than 1,600 connections in a week to 11 management systemsThe workstation's MCP servers, including the firewall, the SIEM and sensor management.That any connection was misused, or the split by system.
203 GitHub and 136 PyPI connections in a weekThe launcher, Git and two assistants, on the administrator's workstation.Anything about the other three hosts, which the post marks Expected.
457 starts of five frozen servers over two weeksInstalled package lists identical to install day.Whether five servers are typical.

Why Corelight says it matters, and what it cites

The post's argument is that a managed update has a controlled build, review, and a version number you can see, while an unfrozen environment has none of these. In its comparison table, an MCP server through a one step launcher changes "when a rebuild happens", and as to how you would know, the answer is "You wouldn't", because "The MCP server's own version number doesn't change". Every dependency also loads into the server's process, so code in any of them runs with the server's credentials, files and network reach.

To show that dependencies do get hijacked, the post cites xz Utils (2024), Ultralytics (2024), Nx (2025) and Shai-Hulud (2025 to 2026), with links to the original reports. This site did not re-check xz, Ultralytics or Nx. It did read three of the pages the post cites for Shai-Hulud, on 13 November 2026, to check the one statement that touches MCP packages:

The Shai-Hulud sentences in Corelight's post against the pages it cites, each read by this site on 13 November 2026. Dates are from each page's own data.

Corelight writesWhat the cited page saysDifference
"reaching at least 187 packages in its first days"Krebs on Security, 16 September 2025: "At least 187 code packages" on the npm repository infected.None. Krebs describes npm packages.
A variant reached PyPI in June 2026, "including MCP-themed packages"SecurityWeek, 9 June 2026: the second Hades wave of 8 June hit "bioinformatics, graph machine learning, and MCP-themed packages", at least 29 packages, citing StepSecurity.None. SecurityWeek is the page that says MCP-themed.
In one wave, "six malicious releases were published in under a minute and quarantined within 30 minutes"Endor Labs, 8 June 2026: six malicious versions of Python bioinformatics packages in under 60 seconds, all quarantined within 30 minutes.The six are bioinformatics packages, not MCP packages. The two sentences are about the same wave but not the same packages.

So the cited pages support the claim that a worm reached PyPI in June 2026 and that some of its packages were MCP themed. None of them involves the workstation, the community server, or any package that changed in Corelight's lab, and the post does not say it does. Its own conclusion is a probability argument: "a malicious release may be available for only minutes or hours", so "A launcher that rebuilds every couple of days, started automatically, has more chances to land in one". The post also cites a 2025 command injection flaw in an MCP proxy rated CVSS 9.6 by its source, which this site did not check.

The post separates the Python case from a second one it found in vendors' setup instructions: a small open source proxy started with npm's runner and a latest tag, so "the client asks the npm registry for the newest version each time it starts". It says the proxy "released six versions in one recent month, four of them within 14 hours", and that in another vendor's example "the setup also turned off TLS certificate checking for the whole proxy process". That is a reading of setup instructions and a release cadence, not a measured drift on the lab machine. Whether npx drifts as uvx did on that workstation is not stated.

A pin on the top is a label, not a control

Three labels in the story stand where a control should. Pinned describes the line in the configuration, and the post's point is that it described one package of 69. Lock file describes a file the author published, and a lock file nobody installs from controls nothing: the post says the author "had done the hard part" and that "What was missing was an install path that used the lock file". Release tag is a label that can move: the first item in the post's fix is "Pin to a commit, not a tag. Tags can be moved."

The same pattern sits behind the post's observation that a quiet network does not prove a fix: "Quiet network logs alone don't prove a fix, though." Corelight says the check that mattered most was what was installed, with the network and endpoint records as support. A sentence in a README or a pin in a configuration is a claim about what runs; the installed package list is the evidence.

What Corelight states, and what it does not

What Corelight's post of 10 November 2026 states and does not state, as read from the saved copy on 13 November 2026.

QuestionStated in the postNot stated
CompromiseNothing on that workstation was compromised.Any compromised package, in any of the 15 sets or the 35 servers.
Scope of the driftOne community server for five weeks; every server launched the same way on that workstation showed the pattern.How common this is outside the lab. The post reports no count from other environments.
The 15 sets19 builds made 15 distinct environments; 23 of 69 packages changed.Which packages, the versions, or whether any set held a known vulnerable version.
The 35 serversFrom two vendor catalogs and the lab; 23 had a recommended install that would have resolved fresh.The catalogs, the servers, the split between catalogs and lab, or deployments.
Other launchersnpx with a latest tag appears in several vendors' setup instructions it reviewed.Measured drift for npx on the lab machine.
CauseThe launcher installed from declared dependencies, not the lock file. None of this is a flaw in MCP.Whether the launcher's behaviour is a design choice or a defect.
The fixFive frozen servers started 457 times over two weeks with identical package lists.A flag or command for any installer; the post prints none.

One more limit sits inside the post's own fix. Freezing pins older code: "40 of its packages were older than what the launcher would have pulled that day". The post's answer is ownership, "a named owner needs to re-lock on a schedule, review what changed, and check the pinned versions for known vulnerabilities", and without it "the environment just ages".

Where the figures differ, inside the post and against its sources

The post disagrees with itself in small ways that matter to anyone repeating its numbers. The community server has 69 packages, seven pinned and roughly 60 underneath, which is 62 by subtraction; the comparison table says "about 70 packages". The cache held 19 builds over five weeks, while the endpoint records counted "17 to 21 per MCP server over 30 days" by counting cache folders in process events. Thirty days is 4.3 weeks, not five (derived: 30 divided by 7), so the two windows differ and the figures are consistent rather than identical. And the 19 builds and 15 distinct environments belong to the first server, while 19 builds and 17 distinct environments belong to another. This site keeps each figure with its server.

Against its sources, the one difference is in the Shai-Hulud sentence set out in the table above: the MCP themed packages and the six quarantined releases come from different pages and the six were bioinformatics packages. The post does not say otherwise, but a reader who joins the two sentences would get it wrong. The post also words 15 sets as "different sets of dependencies" in its opening and "distinct environments" later; this site treats them as the same quantity.

How this differs from the archived MCP servers story

This site's earlier briefing on a Glow Labs report, Glow Labs says AI coding agents install archived MCP servers from model memory, and no patch is coming, is a different problem. There the risk is which package an agent chooses: it recalls an archived, deprecated MCP server from training and installs it. Here the package is the one the administrator chose and pinned, and the risk is below the pin, in what the launcher resolves each time it rebuilds. One is a wrong name at install time, the other is a right name whose underneath keeps moving. What the two share is that nothing in either case records, checks or pins the code the server actually runs, so a team that fixes one still has the other.

Corelight's remedies, and which are general

Corelight sells network detection and response, and its post is partly a demonstration of it: the hunt it describes uses Corelight DNS and SSL logs, Zeek metadata and an agent connected to Corelight data through MCP, with endpoint records to confirm. The post also names a Corelight product in its table of hosts, Fleet Manager, as the expected fetcher on a jump host. The fix itself, freezing the environment, does not use any Corelight product, and the post describes it in generic terms. The split below is this site's reading.

Corelight's remedies sorted by whether they depend on its products. The sorting is this site's, from the post of 10 November 2026.

Remedy in the postNeeds a Corelight product?Where it comes from
Pin to a commit; install from the hash-pinned lock file with hash checking enforced; install the server without dependency resolution; launch it directly; turn off update checks.No.The fix, as printed.
Name an owner who re-locks on a schedule, reviews what changed and checks pinned versions for known vulnerabilities.No.After the freeze, as printed.
Give each MCP server its own account or API client with the least access, read-only where supported, with expiring tokens.No.After the freeze, as printed.
Find hosts that fetch code at runtime with DNS and TLS logs, then confirm the process with endpoint records.Uses network logs; any DNS and TLS logs can serve, and the post's own were Corelight's.The hunt, as printed.
Check the installed package versions after a restart; use JA4 for clients that randomise the TLS handshake.No for the check; JA4 depends on the sensor.The check and the JA4 note, as printed.

What to do, in order

Each item says whose it is. Corelight items are the post's own advice. This site items are this site's suggestion and are not in the post. The post prints no installer flag, so no flag is given here: use your installer's documentation for the options that enforce hashes and skip dependency resolution.

Take this with you

Order of work

  • Corelight: for each credential holding MCP server, pin to a commit not a tag, install from the project's hash-pinned lock file into a dedicated environment with hash checking enforced, install the server without dependency resolution, launch it directly and turn off startup update checks. The post says it froze five servers this way.
  • This site: where a server publishes no lock file, treat it as unfrozen and decide whether it should hold credentials at all. The post says that is worth knowing before you hand credentials over.
  • This site: vendor or mirror the packages your MCP servers need, so a rebuild cannot reach a public registry. The post does not suggest this; it follows from its point that the registry is where the change enters.
  • Corelight, with this site's addition: name an owner who re-locks on a schedule and reviews what changed. This site adds that the owner should keep the resolved package list from each rebuild and diff it against the last.
  • Corelight: give each MCP server its own account or API client with the least access its tools need, read-only where supported, with tokens that expire. The post's workstation reached 11 management systems.
  • Corelight: check AI client configurations for one step runners and a latest tag, including any local proxy for a hosted MCP server, and pin or freeze them.
  • This site: log MCP server start-ups with the resolved versions, so that after a bad release is announced you can answer which set was running that day.
  • Corelight: check the fix by what is installed, not by quiet network logs. Installed versions should stay the same across restarts and the server should still work.

Technical details

Corelight's post prints three launch lines, each with placeholders in angle brackets, a list of domains to hunt for, a table of connection counts and a setup prompt for maintainers' users. It prints no package names, no versions, no hashes, no lock file contents, no installer flags and no indicators of compromise. There is nothing of those kinds to copy, so none is invented here. The first block is the form Corelight describes for the community server, a Git tag as the source. A defender searches client configuration files for lines of this shape, because a tag can move and the lock file is not consulted.

Text
uvx --from git+https://github.com/<owner>/<server>@<release-tag> <server>
A launch line as printed in Corelight's post, read from the lead's saved copy on 13 November 2026. The placeholders are the post's.

The next two are the other forms the post prints. An exact PyPI version through uvx looked as fixed as the tag form, and the post says every server launched the same way on the workstation showed the same drift. The local proxy line, with a latest tag, is what the post says appears in several vendors' setup instructions it reviewed, and it asks the npm registry for the newest release at every start. A defender searches client configurations for both shapes.

Text
uvx --from <package>==<version> <package>
A second launch line as printed in Corelight's post, read on 13 November 2026.
Text
npx <proxy>@latest <url>
The proxy launch line with a latest tag, as printed in Corelight's post, read on 13 November 2026.

The hunt prompt in the post searches seven days of DNS and TLS records for hosts that fetch code from these domains. They are public code and package hosts, not indicators, and are printed here as the post prints them. A defender uses the list to find hosts other than developer workstations that contact them, then asks the endpoint tool which process did.

Text
github.com
codeload.github.com
raw.githubusercontent.com
objects.githubusercontent.com
pypi.org
files.pythonhosted.org
registry.npmjs.org
The seven code and package domains in the hunt prompt, one per line, from Corelight's post, read on 13 November 2026.

The table below is the post's endpoint count for each host that contacted code domains in one week, with the verdicts as Corelight words them. Browser and code editor traffic on the workstation (607 GitHub connections) was excluded by Corelight as normal. A defender compares their own hosts with it: volume was not the signal, the host was.

Text
Host                          GitHub  PyPI  Verdict (Corelight)
Development server             1,700     0  Expected
Jump host                         16     0  Expected
Container host                     4     0  Expected
Administrator's workstation      203   136  Investigate
Corelight's table of endpoint connection counts in one week, reformatted into columns by this site from the post's table, read on 13 November 2026.

The post's setup prompt for people who install MCP servers by asking an assistant is printed below as Corelight prints it. It is a request to the assistant, not a command. A defender or a maintainer reads it to see the frozen pattern in one paragraph, and checks what the assistant proposes before approving it.

Text
Install the [server name] MCP server version [X] as a frozen build. Download the hash-pinned requirements file published with that release, create a dedicated environment in [path], install the dependencies with hash checking enforced, then install the server itself without resolving dependencies. Configure this assistant to launch the installed program directly, not through a one-step launcher, and turn off any startup update checks. Before changing my configuration, show me the installed versions and the exact config change, and tell me how to repeat this when I upgrade.
The setup prompt in Corelight's post, read on 13 November 2026. Square brackets are the post's placeholders.

The last block is the page data this site used to date the post. It is the page's own, not Corelight's text.

Text
page title: The Supply-Chain Risk Hiding in Your MCP Servers | Corelight
page date line: Nov 10, 2026
datePublished: 2026-11-10T23:19:03Z
dateModified: 2026-11-10T23:38:59Z
canonical: https://corelight.com/blog/mcp-server-supply-chain-risk
Page data from Corelight's blog page, read on 13 November 2026.

The question the post leaves open

A bad release can be live for minutes, and the post's server rebuilt every couple of days across 15 environments, with 23 of 69 packages moving. If one of those releases had been a bad one, which of the 15 sets would have been running when it was announced, and where would anyone have looked it up?

Key facts

Sources

  1. PrimaryCorelight blog post, The Supply-Chain Risk Hiding in Your MCP Servers (page data 23:19 UTC on 10 November 2026): the whole post, the primary for every count and for the fix. Saved by the lead, read in full by this builderCorelightaccessed 2026-11-13
  2. PrimaryEndor Labs write-up of 8 June 2026, cited by Corelight; used for the six malicious PyPI releases in under 60 seconds and the quarantine within 30 minutesEndor Labsaccessed 2026-11-13
  3. Reported byReport of 9 June 2026 on the Shai-Hulud variants, cited by Corelight; used to check that the June 2026 PyPI wave included MCP themed packagesSecurityWeekaccessed 2026-11-13
  4. Reported byReport of 16 September 2025, cited by Corelight; used for at least 187 infected npm packagesKrebs on Securityaccessed 2026-11-13

Share this briefing

Know someone who owns this problem? Send it to them.

Related briefings

The briefing, in your inbox

Practitioner analysis of cyber and AI security news. No vendor noise.

How often

Every new briefing in one email, at 7am, or at 7am, 12:30pm and 6pm. Nothing is sent when nothing is new. Unsubscribe any time.