Supply Chain Security

2 findingsMCP08MCP10ASI04CoSAI-T6CoSAI-T8CoSAI-T11MAESTRO-L4EU-AI-Act-Art-9AML.T0017#

Malicious & Typosquat Packages

2 findings
D3

Typosquatting Risk in Dependencies

HighMCP10-supply-chain

Server depends on 'expresss' (triple s) with Levenshtein distance 1 from 'express'

Finding 1 of 2HighConfidence 88%
  1. 1Open the manifest and confirm the dependency `distro@1.9.0` is present. The scanner's similarity pipeline matched this name against the curated target `discord` via the levenshtein-near classifier. If this dependency is an intentional internal fork or re-export, add it to `legitimate-forks.ts` so the finding will no longer fire.npm:distro@1.9.0Expect: Dependency npm:distro@1.9.0 is declared; it is NOT in the legitimate-fork allowlist at scan time.
  2. 2Recompute the Damerau-Levenshtein distance and Jaro-Winkler similarity between `distro` and `discord` using the same primitives as the scanner. Concretely, the rule expects Damerau-Levenshtein ≤ 3 and Jaro-Winkler ≥ 0.80 (except for advisory-registry matches which skip the floor). Observed values: distance 3, Jaro-Winkler 0.848.npm:distro@1.9.0Expect: Damerau-Levenshtein distance between "distro" and "discord" is 3. Jaro-Winkler is 0.848. The numbers agree with what the rule recorded.
  3. 3Open the package manifest at this RFC 6901 pointer and read the line. Confirm the package name recorded in the manifest is literally `distro` (not a spelling the build tool fuzzed to) and that no post-resolution rewrite turns this entry into the legitimate `discord`.package.json/dependencies/distroExpect: The manifest entry at package.json/dependencies/distro resolves to distro@1.9.0 — the exact name the scanner flagged.
  4. 4Open the npm page for `distro` and compare against the legitimate `discord`. Check: publisher identity, publish date, weekly download count, repository link, postinstall script presence. A typosquat typically presents as: recently published, low download count, no repository link, optionally carrying a postinstall hook that executes code at install time.npm:distro@1.9.0Expect: Either the candidate is a legitimate publisher-authored alternative (in which case add to `legitimate-forks.ts`) or its metadata confirms the typosquat hypothesis (recent, unknown publisher, low downloads, suspicious scripts).
sourceexternal-content
npm:distro@1.9.0
Dependency npm:distro@1.9.0 is within Damerau-Levenshtein distance 3 of discord (threshold 3).

Dependency names are external content resolved from public package registries. A near-miss to a popular canonical name is a supply-chain anomaly under ISO 27001 A.5.21 — the package manager installs whichever spelling is declared, with no built-in guard against lexically similar substitutions.

propagationdirect-pass
package.json/dependencies/distro
The manifest entry at /dependencies/distro directs the package manager to resolve and install distro@1.9.0. Resolution is purely string-matched against the registry — a typosquatted name installs whatever code the squatter published.
sinkcommand-execution
npm:distro@1.9.0
Malicious package `distro` executes attacker code in the build environment or at import time. Attack classifier: levenshtein-near. Target shadowed: `discord`.
mitigationinput-validationabsent
package.json/dependencies/distro

Lockfiles pin versions but do not pin the spelling of the dependency name. The static analyser cannot confirm whether a typosquat-aware package firewall (Socket.dev, Snyk Advisor) is in the CI chain; the auditor must verify.

impactremote-code-execution
server-host

A developer installs `distro` by typo, copy-paste, or autocomplete. The package's postinstall hook runs during installation with the developer's or CI runner's credentials, or the payload executes on first import when the MCP server starts. An MCP server compromised this way delegates full tool authority to attacker code on every downstream agent interaction.

trivial
Confidence88%ISO-27001-A.5.21ISO/IEC 27001:2022 Annex A Control 5.21 — ICT Supply Chain Security
4 confidence factors
  • +0.1input-validation absentNo input-validation found — Lockfiles pin versions but do not pin the spelling of the dependency name. The static analyser cannot confirm whether a typosquat-aware package firewall (Socket.dev, Snyk Advisor) is in the CI chain; the auditor must verify.
  • +0.1target_distance_under_thresholdDamerau-Levenshtein distance 3 between `distro` and `discord` is within the target's declared ceiling of 3. Combined with the Jaro-Winkler agreement check, this is the distance-only classifier — the most common class.
  • +0.02algorithm_agreement_moderateJaro-Winkler similarity 0.848 clears the agreement floor (0.80) but is below the high-agreement band — the finding stands but reviewer confirmation is advised.
  • -0.04legitimate_fork_allowlist_consultedThe candidate was not in legitimate-forks.ts at scan time. The rule records this explicitly so the finding can be dismissed by adding to the allowlist, with audit trail, if the reviewer confirms the dependency is a sanctioned variant.
Finding 2 of 2HighConfidence 90%
  1. 1Open the manifest and confirm the dependency `pyaml@25.5.0` is present. The scanner's similarity pipeline matched this name against the curated target `pyyaml` via the levenshtein-near classifier. If this dependency is an intentional internal fork or re-export, add it to `legitimate-forks.ts` so the finding will no longer fire.pypi:pyaml@25.5.0Expect: Dependency pypi:pyaml@25.5.0 is declared; it is NOT in the legitimate-fork allowlist at scan time.
  2. 2Recompute the Damerau-Levenshtein distance and Jaro-Winkler similarity between `pyaml` and `pyyaml` using the same primitives as the scanner. Concretely, the rule expects Damerau-Levenshtein ≤ 2 and Jaro-Winkler ≥ 0.80 (except for advisory-registry matches which skip the floor). Observed values: distance 1, Jaro-Winkler 0.956.pypi:pyaml@25.5.0Expect: Damerau-Levenshtein distance between "pyaml" and "pyyaml" is 1. Jaro-Winkler is 0.956. The numbers agree with what the rule recorded.
  3. 3Open the package manifest at this RFC 6901 pointer and read the line. Confirm the package name recorded in the manifest is literally `pyaml` (not a spelling the build tool fuzzed to) and that no post-resolution rewrite turns this entry into the legitimate `pyyaml`.pyproject.toml/project/dependencies/pyamlExpect: The manifest entry at pyproject.toml/project/dependencies/pyaml resolves to pyaml@25.5.0 — the exact name the scanner flagged.
  4. 4Open the PyPI page for `pyaml` and compare against the legitimate `pyyaml`. Check: publisher identity, publish date, weekly download count, repository link, postinstall script presence. A typosquat typically presents as: recently published, low download count, no repository link, optionally carrying a postinstall hook that executes code at install time.pypi:pyaml@25.5.0Expect: Either the candidate is a legitimate publisher-authored alternative (in which case add to `legitimate-forks.ts`) or its metadata confirms the typosquat hypothesis (recent, unknown publisher, low downloads, suspicious scripts).
sourceexternal-content
pypi:pyaml@25.5.0
Dependency pypi:pyaml@25.5.0 is within Damerau-Levenshtein distance 1 of pyyaml (threshold 2).

Dependency names are external content resolved from public package registries. A near-miss to a popular canonical name is a supply-chain anomaly under ISO 27001 A.5.21 — the package manager installs whichever spelling is declared, with no built-in guard against lexically similar substitutions.

propagationdirect-pass
pyproject.toml/project/dependencies/pyaml
The manifest entry at /project/dependencies/pyaml directs the package manager to resolve and install pyaml@25.5.0. Resolution is purely string-matched against the registry — a typosquatted name installs whatever code the squatter published.
sinkcommand-execution
pypi:pyaml@25.5.0
Malicious package `pyaml` executes attacker code in the build environment or at import time. Attack classifier: levenshtein-near. Target shadowed: `pyyaml`.
mitigationinput-validationabsent
pyproject.toml/project/dependencies/pyaml

Lockfiles pin versions but do not pin the spelling of the dependency name. The static analyser cannot confirm whether a typosquat-aware package firewall (Socket.dev, Snyk Advisor) is in the CI chain; the auditor must verify.

impactremote-code-execution
server-host

A developer installs `pyaml` by typo, copy-paste, or autocomplete. The package's postinstall hook runs during installation with the developer's or CI runner's credentials, or the payload executes on first import when the MCP server starts. An MCP server compromised this way delegates full tool authority to attacker code on every downstream agent interaction.

trivial
Confidence90%ISO-27001-A.5.21ISO/IEC 27001:2022 Annex A Control 5.21 — ICT Supply Chain Security
5 confidence factors
  • +0.1input-validation absentNo input-validation found — Lockfiles pin versions but do not pin the spelling of the dependency name. The static analyser cannot confirm whether a typosquat-aware package firewall (Socket.dev, Snyk Advisor) is in the CI chain; the auditor must verify.
  • +0.1target_distance_under_thresholdDamerau-Levenshtein distance 1 between `pyaml` and `pyyaml` is within the target's declared ceiling of 2. Combined with the Jaro-Winkler agreement check, this is the distance-only classifier — the most common class.
  • +0.06algorithm_agreement_highJaro-Winkler similarity 0.956 ≥ 0.90 — two complementary algorithms (Damerau-Levenshtein + Jaro-Winkler) agree on the similarity claim. Agreement across algorithms is the filter against single-algorithm noise.
  • -0.04legitimate_fork_allowlist_consultedThe candidate was not in legitimate-forks.ts at scan time. The rule records this explicitly so the finding can be dismissed by adding to the allowlist, with audit trail, if the reviewer confirms the dependency is a sanctioned variant.
  • -0.02charter_confidence_capD3 charter caps confidence at 0.9 — similarity is fuzzy and a candidate within Damerau-Levenshtein distance of a popular target can still be a legitimate namespace fork or internal alias the allowlist has not yet captured. The 0.10 gap signals "strong static evidence, reviewer should corroborate against the public registry before removal".
Methodology5 tests · 4 frameworks
Technique
similarity
Tests (5)
  1. legitimate-fork-allowlist
  2. visual-confusable-replay
  3. scope-squat-detection
  4. numeric-version-suffix-strip
  5. algorithm-agreement-gate
Lethal edge cases (7)
  • Legitimate namespace fork — `lodash-es` is a real package within Damerau-Levenshtein distance 3 of `lodash`. A detector that fires purely on edit distance misclassifies it as a typosquat. The rule suppresses candidates listed in `legitimate-forks.ts` and down-weights candidates whose only extra content is a structural suffix like `-es`, `-fork`, `-pro`.
  • Visual-confusable graphemes in ASCII — `rnistral` differs from `mistral` by substituting `rn` for `m`. Pure Damerau-Levenshtein scores distance 2 but doesn't flag this as "near" `mistral` with high confidence. The rule re-evaluates every <=2-distance candidate through `visuallyConfusableVariants` to catch the RN/M, CL/D, VV/W cohort.
  • Scope-squat under a different scope — `@mcp/sdk` shadows the official `@modelcontextprotocol/sdk` via scope replacement rather than substring edits. Character-level Levenshtein would consider these far apart. The rule runs a scope-squat check on any dependency whose UNSCOPED tail matches the tail of a `scoped_official` target but whose scope differs (including no-scope).
  • Version-suffixed package — `react-18`, `webpack-5`, `python-3.12`. These are legitimate publisher-versioned aliases and must not be flagged. The rule treats numeric suffixes separated by `-` or `.` as non-material for the similarity comparison — the suffix is stripped before Damerau-Levenshtein evaluation.
  • Deprecated-official official rename — `request` is deprecated in favour of `got`, yet `request` remains a published package and many legacy servers still depend on it. The rule must NOT flag `request` as a typosquat of `got` (distance-wise these are far apart anyway, but the rule nonetheless documents this class to acknowledge the failure mode).
  • Author-internal name coinciding with a public near-miss — an org's private package `@acme/requestss` is three edits from public `requests`. The rule cannot distinguish private from public registries statically; it emits the finding with a `no_confirmed_malicious_record` factor (negative adjustment) so the reviewer sees that the finding is distance-only and can apply organisational context to dismiss.
  • Short-name collisions — `axios` has length 5. A Damerau-Levenshtein distance of 2 against `axios` produces many legitimate 3-5 character unrelated names (e.g. a greenfield utility called `axles`). The rule uses the target's declared `max_distance` (2 for short names, 3 for longer) and additionally requires a Jaro-Winkler similarity ≥ 0.80 before firing — agreement between two complementary algorithms is the filter against single-algorithm noise.
Confidence cap
unbounded
Frameworks (4)
  • EU AI ActArt.9Risk Management System
  • OWASP MCPMCP08Dependency Vulnerabilities
  • OWASP MCPMCP10Supply Chain Compromise
  • OWASP ASIASI04Agentic Supply Chain
Backing
  • Precision:
  • Recall:
  • Red-team fixtures: 4
  • CVE replays: none
  • Last validated:
Test 102 more rules — give us more context2 input gaps
Live connection3 rules

To unlock these tests: register a live MCP endpoint.

  • E1No Authentication RequiredCode VulnerabilitiesServer-Hardening Failures
  • E2Insecure TransportAuthentication & IdentitySession & Transport Security
  • E3Response Time AnomalyAudit & LoggingAbsent or Unstructured Logging
Source code99 rules

To unlock these tests: publish your source on GitHub.

  • C1Command InjectionCode VulnerabilitiesCommand & Shell Execution
  • C10Prototype PollutionCode VulnerabilitiesData Store Injection
  • C11ReDoS — Catastrophic Regex BacktrackingCode VulnerabilitiesServer-Hardening Failures
  • C12Unsafe DeserializationCode VulnerabilitiesDynamic Code Evaluation & Deserialization
  • C13Server-Side Template Injection (SSTI)Code VulnerabilitiesDynamic Code Evaluation & Deserialization
  • C14JWT Algorithm Confusion / None Algorithm AttackCode VulnerabilitiesInsecure Credential & Crypto
  • C15Timing Attack on Secret or Token ComparisonCode VulnerabilitiesInsecure Credential & Crypto
  • C16Dynamic Code Evaluation with User InputCode VulnerabilitiesCommand & Shell Execution
  • C2Path TraversalCode VulnerabilitiesFilesystem & Network Traversal
  • C3Server-Side Request Forgery (SSRF)Code VulnerabilitiesFilesystem & Network Traversal
  • C4SQL InjectionCode VulnerabilitiesData Store Injection
  • C5Hardcoded Secrets in Source CodeCode VulnerabilitiesInsecure Credential & Crypto
  • C6Error Message Information LeakageCode VulnerabilitiesServer-Hardening Failures
  • C7Wildcard CORS ConfigurationCode VulnerabilitiesServer-Hardening Failures
  • C8No Authentication on Network-Exposed ServerCode VulnerabilitiesServer-Hardening Failures
  • C9Excessive Filesystem ScopeCode VulnerabilitiesCommand & Shell Execution
  • G7DNS-Based Data Exfiltration ChannelData ExfiltrationExplicit Network Exfiltration
  • H1MCP OAuth 2.0 Insecure ImplementationAuthentication & IdentityOAuth Misimplementation
  • I12Capability Escalation Post-InitializationHuman OversightPost-Init Capability Escalation
  • I15Transport Session SecurityAuthentication & IdentitySession & Transport Security
  • J1Cross-Agent Configuration PoisoningSupply Chain SecurityConfig Injection & Bridge Supply Chain
  • J2Git Argument InjectionCode VulnerabilitiesCommand & Shell Execution
  • J4Health Endpoint Information DisclosureModel ManipulationInformation Disclosure Via Debug Surface
  • J5Tool Output Poisoning PatternsPrompt InjectionIndirect Gateway Injection
  • J7OpenAPI Specification Field InjectionCode VulnerabilitiesOpenAPI / Spec Field Injection
  • K1Absent Structured LoggingAudit & LoggingAbsent or Unstructured Logging
  • K10Package Registry SubstitutionTool PoisoningUpdate-Channel Spoofing
  • K11Missing Server Integrity VerificationSupply Chain SecurityKnown Vulnerable Dependencies
  • K12Executable Content in Tool ResponseTool PoisoningAnnotation Deception
  • K13Unsanitized Tool OutputTool PoisoningAnnotation Deception
  • K14Agent Credential Propagation via Shared StateAuthentication & IdentityCross-Boundary Credential Sharing
  • K16Unbounded Recursion / Missing Depth LimitsProtocol & TransportJSON-RPC Batching & Flooding
  • K17Missing Timeout or Circuit BreakerDenial of ServiceRecursion & Loop Bombs
  • K18Cross-Trust-Boundary Data Flow in Tool ResponseData ExfiltrationSource-to-Sink Flow
  • K19Missing Runtime Sandbox EnforcementDenial of ServiceTimeout & Circuit-Breaker Gaps
  • K2Audit Trail DestructionAudit & LoggingLog Destruction
  • K20Insufficient Audit Context in LoggingAudit & LoggingInsufficient Audit Context
  • K3Audit Log TamperingAudit & LoggingLog Destruction
  • K5Auto-Approve / Bypass Confirmation PatternHuman OversightAuto-Approve & Bypass
  • K6Overly Broad OAuth ScopesAuthentication & IdentityOAuth Misimplementation
  • K7Long-Lived Tokens Without RotationAuthentication & IdentityOAuth Misimplementation
  • K8Cross-Boundary Credential SharingData ExfiltrationTrust-Boundary Data Flow
  • K9Dangerous Post-Install HooksSupply Chain SecurityInstall-Time Execution
  • L1GitHub Actions Tag PoisoningSupply Chain SecurityCI/CD Poisoning
  • L10Registry Metadata SpoofingTool PoisoningUpdate-Channel Spoofing
  • L11Environment Variable Injection via MCP ConfigSupply Chain SecurityConfig Injection & Bridge Supply Chain
  • L12Build Artifact TamperingCode VulnerabilitiesOpenAPI / Spec Field Injection
  • L13Build Credential File TheftSupply Chain SecurityCI/CD Poisoning
  • L14Hidden Entry Point MismatchSupply Chain SecurityManifest & Entry-Point Confusion
  • L15Update Notification SpoofingTool PoisoningBehavior Drift
  • L2Malicious Build Plugin InjectionCode VulnerabilitiesOpenAPI / Spec Field Injection
  • L3Dockerfile Base Image Supply Chain RiskSupply Chain SecurityRegistry & Distribution Substitution
  • L4MCP Config File Code InjectionSupply Chain SecurityManifest & Entry-Point Confusion
  • L5Package Manifest Confusion IndicatorsSupply Chain SecurityManifest & Entry-Point Confusion
  • L6Config Directory Symlink AttackSupply Chain SecurityRegistry & Distribution Substitution
  • L7Transitive MCP Server DelegationSupply Chain SecurityManifest & Entry-Point Confusion
  • L8Version Rollback / Downgrade AttackSupply Chain SecurityRegistry & Distribution Substitution
  • L9CI/CD Secret Exfiltration PatternsSupply Chain SecurityCI/CD Poisoning
  • M2TokenBreak Boundary ManipulationModel ManipulationTokenizer Boundary Attacks
  • M6Progressive Context Poisoning EnablersHuman OversightTool-Position & Progressive Poisoning
  • M7Tool Response Structure BombDenial of ServiceResponse Payload Amplification
  • M8Inference Cost AmplificationDenial of ServiceInference Cost Amplification
  • M9Model-Specific System Prompt ExtractionModel ManipulationReasoning Extraction
  • N1JSON-RPC Batch Request AbuseProtocol & TransportJSON-RPC Batching & Flooding
  • N10Incomplete Handshake Denial of ServiceProtocol & TransportJSON-RPC Batching & Flooding
  • N11Protocol Version Downgrade AttackProtocol & TransportProtocol Version & Method Confusion
  • N12Resource Subscription Content MutationPrompt InjectionIndirect Gateway Injection
  • N13HTTP Chunked Transfer SmugglingProtocol & TransportStreaming & Session Hijacking
  • N14Trust-On-First-Use Bypass (TOFU)Authentication & IdentitySession & Transport Security
  • N15JSON-RPC Method Name ConfusionProtocol & TransportProtocol Version & Method Confusion
  • N2JSON-RPC Notification FloodingProtocol & TransportJSON-RPC Batching & Flooding
  • N3JSON-RPC Request ID CollisionProtocol & TransportJSON-RPC Batching & Flooding
  • N4JSON-RPC Error Object InjectionPrompt InjectionProtocol-Surface Injection
  • N5Capability Downgrade DeceptionProtocol & TransportProtocol Version & Method Confusion
  • N6SSE Reconnection HijackingProtocol & TransportStreaming & Session Hijacking
  • N7Progress Token Prediction and InjectionProtocol & TransportStreaming & Session Hijacking
  • N8Cancellation Race ConditionProtocol & TransportJSON-RPC Batching & Flooding
  • N9MCP Logging Protocol InjectionPrompt InjectionContext & Trust Manipulation
  • O10Privacy-Violating TelemetryData ExfiltrationCovert Channels
  • O4Clipboard and UI Exfiltration InjectionData ExfiltrationTrust-Boundary Data Flow
  • O5Environment Variable HarvestingData ExfiltrationCovert Channels
  • O6Server Fingerprinting via Error ResponsesData ExfiltrationCovert Channels
  • O8Timing-Based Covert ChannelData ExfiltrationCovert Channels
  • O9Ambient Credential ExploitationData ExfiltrationCovert Channels
  • P1Docker Socket Mount in ContainerContainer & RuntimeContainer Escape Vectors
  • P10Host Network Mode and Missing Egress ControlsContainer & RuntimeHost Mount & Network
  • P2Dangerous Container CapabilitiesContainer & RuntimeContainer Escape Vectors
  • P3Cloud Metadata Service AccessContainer & RuntimeCloud Metadata Access
  • P4TLS Certificate Validation BypassContainer & RuntimeTLS & Crypto Misconfig
  • P5Secrets Exposed in Container Build LayersSupply Chain SecurityRegistry & Distribution Substitution
  • P6LD_PRELOAD and Shared Library HijackingContainer & RuntimeContainer Escape Vectors
  • P7Sensitive Host Filesystem MountContainer & RuntimeHost Mount & Network
  • P8Insecure Cryptographic Mode or Static IV/NonceContainer & RuntimeTLS & Crypto Misconfig
  • P9Missing Container Resource LimitsDenial of ServiceContainer Resource Exhaustion
  • Q13MCP Bridge Package Supply Chain AttackSupply Chain SecurityConfig Injection & Bridge Supply Chain
  • Q15A2A/MCP Protocol Boundary ConfusionHuman OversightTrust-Delegation Confusion
  • Q3Localhost MCP Service HijackingProtocol & TransportLocalhost & Concurrency Hijack
  • Q4IDE MCP Configuration InjectionSupply Chain SecurityConfig Injection & Bridge Supply Chain
  • Q7Desktop Extension Privilege ChainContainer & RuntimePrivileged Roots & Extensions

Tested cleanly

  • Prompt Injection24 rules tested cleanly
  • Tool Poisoning17 rules tested cleanly
  • Code Vulnerabilities23 rules tested cleanly
  • Data Exfiltration15 rules tested cleanly
  • Authentication & Identity9 rules tested cleanly
  • Human Oversight6 rules tested cleanly
  • Audit & Logging5 rules tested cleanly
  • Multi-Agent Security1 rule tested cleanly
  • Protocol & Transport15 rules tested cleanly
  • Denial of Service7 rules tested cleanly
  • Container & Runtime10 rules tested cleanly
  • Model Manipulation8 rules tested cleanly
agentic-auth security findings — MCP Sentinel