Back to skill

Security audit

AgentMesh

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent encrypted agent-messaging library, but it overstates important security guarantees and its network/key-storage guidance needs careful review before installation.

Review this before installing in any sensitive environment. Prefer a pinned commit or release, use LocalHub or bind the network hub to localhost/private networks, add firewalling and authenticated transport before exposing it, and treat persistent key files as long-lived secrets outside source control with restrictive permissions. Do not rely on the current implementation for production-grade forward secrecy or hostile-network security without further hardening.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (7)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/agentmesh/hub.py:176
Finding
Unauthenticated Agent Registration Enables Identity Replacement and Message Interception<![CDATA[ ## Vulnerability Details **File Location**: `src/agentmesh/hub.py:176-190` **Vulnerability Type**: Unauthenticated registration and public-key replacement **Risk Level**: Critical ### Vulnerable Code ```python if cmd == "REGISTER": agent_id = msg["bundle"]["agent_id"] with self._lock: self._bundles[agent_id] = msg["bundle"] self._agent_socks[agent_id] = conn conn.sendall(b'{"status": "OK"}\n') elif cmd == "GET_BUNDLE": b = self._bundles.get(msg["agent_id"]) conn.sendall((json.dumps({"bundle": b}) + "\n").encode()) elif cmd == "DELIVER": target = msg["envelope"]["to"] with self._lock: s = self._agent_socks.get(target) if s: s.sendall((json.dumps({"cmd": "INCOMING", "envelope": msg["envelope"]}) + "\n").encode()) ``` ### Technical Analysis The hub accepts any `REGISTER` request and directly associates the supplied `agent_id`, public-key bundle, and connection. It does not require authentication, proof of possession of a previously trusted key, administrator approval, or confirmation from an existing registration. Registering an existing identifier silently overwrites both `_bundles[agent_id]` and `_agent_socks[agent_id]`. Other agents obtain public keys from this same unauthenticated directory. Consequently, Ed25519 message signatures do not prevent this attack: recipients verify signatures against the attacker-controlled identity key returned by the compromised directory. ### Attack Path 1. The attacker establishes a TCP connection to the hub. 2. The attacker generates their own Ed25519 and X25519 key pairs. 3. The attacker sends a `REGISTER` command containing the victim's `agent_id` and the attacker's public keys. 4. The server replaces the victim's public bundle and routing socket. 5. A sender calls `GET_BUNDLE` for the victim and receives the attacker's keys. 6. The sender derives a session key using the attacker's X25519 key and encrypts a message intended for the victim. 7. The ...[truncated 765 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Authenticate every registration using a trusted credential or certificate. - Require proof of possession by having the registering agent sign a server-provided challenge. - Reject duplicate agent identifiers unless an authenticated key-rotation protocol is completed. - Pin public-key fingerprints after first verification and alert users to unexpected changes. - Use an authenticated key-transparency mechanism or out-of-band fingerprint verification. - Bind each connection to one authenticated identity and authorize delivery operations against that identity. - Add tests for duplicate registration, unauthorized key replacement, key rotation, and stale-session behavior. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/agentmesh/hub.py:90
Finding
Hub Protocol Uses Unauthenticated Plaintext TCP and Exposes Control Operations<![CDATA[ ## Vulnerability Details **File Location**: `src/agentmesh/hub.py:90-91, 123-126, 159-162` **Vulnerability Type**: Missing transport encryption and peer authentication **Risk Level**: High ### Vulnerable Code ```python def _connect(self): self._sock = socket.create_connection((self.host, self.port), timeout=5) self._sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) ``` ```python def _request(self, msg: dict) -> dict: with self._lock: if not self._sock: self._connect() self._sock.sendall((json.dumps(msg) + "\n").encode()) return self._pending_resps.get(timeout=10) ``` ```python def start(self, block: bool = True): self._srv_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._srv_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._srv_sock.bind((self.host, self.port)) self._srv_sock.listen(128) ``` The server also defaults to all network interfaces: ```python def __init__(self, host: str = "0.0.0.0", port: int = 7700): ``` ### Technical Analysis The network client and server communicate through newline-delimited JSON over raw TCP. There is no TLS, server certificate validation, client authentication, command authentication, or integrity protection for hub control messages. Application payloads are encrypted separately, but public-key discovery, registration, agent identifiers, routing metadata, timestamps, and commands remain observable and modifiable. Because key discovery is itself unauthenticated, an active network attacker can combine protocol interception with public-key substitution. Binding to `0.0.0.0` by default increases exposure by making the service reachable through every configured interface unless external firewall rules prevent access. ### Attack Path 1. An attacker obtains network access to TCP port 7700 or positions themselves between an agent and the hub. 2. The attacker observes plaintext registration, directory queries, agent ...[truncated 837 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Protect all network traffic with TLS and mandatory certificate validation. - Prefer mutual TLS or an equivalent authenticated transport for agent connections. - Default the server to `127.0.0.1`; require an explicit option to expose it externally. - Authenticate and authorize each protocol command. - Cryptographically bind directory responses and registrations to trusted identities. - Add connection-level session identifiers and prevent one connection from claiming arbitrary agent IDs. - Document firewall, certificate, and deployment requirements. - Do not claim production-grade network security until authenticated transport and key discovery are implemented and tested. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/agentmesh/hub.py:99
Finding
Unbounded TCP Frames and Per-Connection Threads Permit Remote Resource Exhaustion<![CDATA[ ## Vulnerability Details **File Location**: `src/agentmesh/hub.py:99-105, 165-175` **Vulnerability Type**: Unbounded input buffering and connection concurrency **Risk Level**: High ### Vulnerable Code ```python def _recv_loop(self): buf = b"" try: while self._running: data = self._sock.recv(65536) if not data: break buf += data while b"\n" in buf: line, buf = buf.split(b"\n", 1) msg = json.loads(line) ``` ```python def _accept_loop(self): while True: conn, addr = self._srv_sock.accept() threading.Thread(target=self._handle_client, args=(conn,), daemon=True).start() def _handle_client(self, conn): agent_id = None buf = b"" try: while True: data = conn.recv(65536) if not data: break buf += data while b"\n" in buf: line, buf = buf.split(b"\n", 1) msg = json.loads(line) ``` ### Technical Analysis Both protocol endpoints accumulate bytes until a newline appears. There is no maximum frame length, maximum buffered data limit, JSON nesting limit, read deadline, or idle timeout. A peer can therefore send an indefinitely long non-terminated frame and force the process to retain an expanding `bytes` buffer. The server also creates a new thread for every accepted connection without authentication, per-address quotas, or a bounded worker pool. Slow or idle clients can retain threads and sockets indefinitely. ### Attack Path 1. The attacker opens one or more TCP connections to the exposed hub. 2. On each connection, the attacker continuously sends data without a newline or sends an extremely large JSON frame. 3. `_handle_client` repeatedly appends the received data to `buf`. 4. Since no complete frame is detected, the buffer is never released or rejected. 5. The attacker opens additional connections, causing the server to create additional threa ...[truncated 397 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Define and enforce a strict maximum protocol-frame size before appending more data. - Close connections immediately when buffered data exceeds the configured limit. - Configure socket read, write, handshake, and idle timeouts. - Replace unbounded per-connection thread creation with a bounded worker pool or event-driven server. - Add global and per-source connection quotas and rate limits. - Limit JSON depth, key count, string sizes, and envelope dimensions. - Catch parsing errors per frame and close abusive connections safely. - Add stress tests covering slow clients, missing delimiters, oversized frames, and connection floods. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/agentmesh/crypto.py:173
Finding
Replay Cache Is Updated Before Authentication and Grows Without Bound<![CDATA[ ## Vulnerability Details **File Location**: `src/agentmesh/crypto.py:173-183` **Vulnerability Type**: Replay-state poisoning and memory exhaustion **Risk Level**: High ### Vulnerable Code ```python # Replay detection nonce_key = (nonce, counter) if nonce_key in self._seen_nonces: raise CryptoError("Replay attack detected – nonce reuse") self._seen_nonces.add(nonce_key) counter_bytes = counter.to_bytes(8, "big") full_aad = nonce + counter_bytes + aad aesgcm = AESGCM(self._recv_key) try: return aesgcm.decrypt(nonce, ciphertext, full_aad) except InvalidTag as exc: raise CryptoError("Authentication tag mismatch – message tampered") from exc ``` The replay collection is initialized as an unbounded set: ```python self._seen_nonces: set = set() ``` ### Technical Analysis A nonce/counter pair is inserted into `_seen_nonces` before AES-GCM verifies that the envelope is authentic. Invalid messages therefore permanently alter replay state. The set has no upper bound, expiration policy, or counter window. An attacker can submit arbitrary malformed envelopes with fresh nonce/counter pairs to grow the set. If an attacker observes a legitimate envelope, they can also send a modified copy with the same nonce and counter before the authentic envelope arrives. The modified copy fails authentication but reserves the nonce, causing the later valid envelope to be rejected as a replay. ### Attack Path 1. The attacker establishes or claims a sender identity known to the target. 2. The attacker repeatedly sends envelopes containing unique nonce/counter pairs and invalid ciphertext or authentication tags. 3. The target inserts each pair into `_seen_nonces`. 4. AES-GCM authentication fails, but the inserted replay entries remain. 5. Repetition causes persistent session-memory growth. 6. Alternatively, an on-path attacker copies a legitimate envelope, modifies its ciphertext, and delivers the modified version first. 7. The target records its nonce/counter ...[truncated 385 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Add a nonce or counter to replay state only after successful AEAD authentication. - Track a monotonically increasing receive counter with a bounded sliding replay window. - Reject counters outside an acceptable range before expensive processing. - Bound all replay-related data structures and expire obsolete entries. - Rate-limit authentication failures by connection and claimed sender. - Ensure replay state is synchronized if concurrent receive threads remain in use. - Add tests proving that invalid ciphertext cannot consume replay entries or suppress a later valid envelope. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/agentmesh/agent.py:190
Finding
Persistent Private Keys Are Written in Plaintext Without Secure File Permissions<![CDATA[ ## Vulnerability Details **File Location**: `src/agentmesh/agent.py:190-198` **Vulnerability Type**: Insecure storage of cryptographic private keys **Risk Level**: High ### Vulnerable Code ```python def _load_or_create_keypair(path: Path) -> AgentKeyPair: if path.exists(): with path.open() as fh: data = json.load(fh) return AgentKeyPair.from_dict(data) kp = AgentKeyPair() path.parent.mkdir(parents=True, exist_ok=True) with path.open("w") as fh: json.dump(kp.to_dict(), fh, indent=2) return kp ``` The serialized data contains raw private keys encoded only with Base64: ```python return { "identity_private": _b64( self.identity_private.private_bytes( serialization.Encoding.Raw, serialization.PrivateFormat.Raw, serialization.NoEncryption(), ) ), "exchange_private": _b64( self.exchange_private.private_bytes( serialization.Encoding.Raw, serialization.PrivateFormat.Raw, serialization.NoEncryption(), ) ), } ``` ### Technical Analysis `serialization.NoEncryption()` exports raw private-key bytes, and Base64 provides no confidentiality. The key file is created with the process's default umask rather than an explicitly restrictive mode. The code does not validate the existing file's owner or permissions, reject symbolic links, or perform atomic exclusive creation. As a result, keys may be readable by other local users or processes. A pre-created path or symlink can also redirect key output to an unintended filesystem location when the process has permission to write there. ### Attack Path 1. An application enables persistent identities through `keypair_path`. 2. The process creates the JSON file under a permissive umask, or an attacker prepares a symlink at the chosen path. 3. The raw Ed25519 and X25519 private keys are written in Base64 form. 4. Another local principal, compromised ...[truncated 558 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Create key files atomically and exclusively with mode `0600`. - Create key directories with mode `0700`. - Validate that existing files are regular files owned by the expected account and are not group/world-readable. - Reject symbolic links and other non-regular filesystem objects. - Support an operating-system keyring, hardware-backed keystore, or encrypted private-key format. - Use temporary-file-plus-atomic-rename semantics to prevent partial writes. - Clearly document backup and rotation requirements. - Add generated key directories to ignore-file guidance to prevent accidental source-control commits. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/agentmesh/crypto.py:44
Finding
Static X25519 Exchange Keys Contradict the Advertised Forward-Secrecy Guarantee<![CDATA[ ## Vulnerability Details **File Location**: `src/agentmesh/crypto.py:44-51, 229-260` **Vulnerability Type**: Missing ephemeral key exchange and session ratcheting **Risk Level**: High ### Vulnerable Code ```python def __init__( self, identity_private: Optional[Ed25519PrivateKey] = None, exchange_private: Optional[X25519PrivateKey] = None, ): self.identity_private = identity_private or Ed25519PrivateKey.generate() self.exchange_private = exchange_private or X25519PrivateKey.generate() self.identity_public: Ed25519PublicKey = self.identity_private.public_key() self.exchange_public: X25519PublicKey = self.exchange_private.public_key() ``` ```python # Deserialise remote keys their_exchange_raw = _db64(their_public_bundle["exchange_key"]) their_exchange_pub = X25519PublicKey.from_public_bytes(their_exchange_raw) # ECDH raw_shared = my_keypair.exchange_private.exchange(their_exchange_pub) # Mix in both identity keys for domain separation my_identity_raw = my_keypair.identity_public.public_bytes( serialization.Encoding.Raw, serialization.PublicFormat.Raw ) their_identity_raw = _db64(their_public_bundle["identity_key"]) keys_sorted = sorted([my_identity_raw, their_identity_raw]) salt = hashlib.sha256(keys_sorted[0] + keys_sorted[1]).digest() hkdf = HKDF( algorithm=hashes.SHA256(), length=32, salt=salt, info=b"AgentMesh-v1-session", ) shared_key = hkdf.derive(raw_shared) ``` ### Technical Analysis The X25519 exchange key is part of the persistent `AgentKeyPair` and is reused for every session involving that identity. The session key is deterministically derived from static ECDH output and public identity keys. No ephemeral X25519 key, authenticated ephemeral handshake, session rotation, symmetric ratchet, Diffie-Hellman ratchet, or old-key erasure is implemented. This does not provide forward secrecy. If either party's static exchange private key is later disclosed, an attacker with the other party's pu ...[truncated 923 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Implement an authenticated ephemeral X25519 handshake for every new session. - Bind ephemeral keys to long-term Ed25519 identities with signatures. - Use a reviewed protocol design rather than a custom “X3DH-lite” construction. - Add a symmetric and/or Diffie-Hellman ratchet with secure deletion of obsolete key material. - Rotate sessions and keys according to explicit lifetime and message-count limits. - Add cryptographic test vectors and independent protocol review. - Remove all forward-secrecy and ephemeral-session claims until the property is actually implemented and verified. ]]>

T08 · Insecure Dependencies

Warning
Location
README.md:30
Finding
Recommended Installation Pulls and Executes a Mutable Git Repository<![CDATA[ ## Vulnerability Details **File Location**: `README.md:30-33` **Vulnerability Type**: Unpinned VCS dependency installation **Risk Level**: Medium ### Vulnerable Code ```markdown ## 📦 Installation ```bash pip install git+https://github.com/cerbug45/AgentMesh.git ``` ``` The same recommendation appears in `SKILL.md:33-36`: ```markdown ### Option 1 – Install from GitHub (recommended) ```bash pip install git+https://github.com/cerbug45/AgentMesh.git ``` ``` ### Technical Analysis The recommended command installs from the repository's current default branch without pinning an immutable commit, signed tag, package version, or artifact hash. The effective code executed by pip can therefore change after this audit without any modification to the reviewed Skill files. Pip installation may execute build-backend code and installs the fetched package with the invoking user's permissions. Repository takeover, maintainer-account compromise, or a malicious future commit would convert the documented installation path into a code-execution supply-chain channel. ### Attack Path 1. The repository or a maintainer account is compromised, or the default branch is changed maliciously. 2. Malicious package or build code is committed to the branch referenced implicitly by the installation command. 3. A user follows the documented `pip install git+https://...` instruction. 4. Pip fetches the current mutable branch rather than the version reviewed in this audit. 5. Build or package code executes with the permissions of the user running pip. 6. The malicious version may access that user's files, credentials, environment, or network resources. ### Impact Assessment Successful exploitation provides arbitrary code execution with the permissions of the user or environment performing installation. If installation is performed in a privileged system environment or CI runner, the scope may include system files, deployment credentials, source repositories, and build secrets ...[truncated 5 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Publish versioned release artifacts to a trusted package index. - Recommend installation using an immutable version. - If VCS installation is necessary, pin the full commit hash rather than a branch or mutable tag. - Provide hashes for release artifacts and use hash-verified lock files in deployments. - Sign release tags and artifacts and document signature verification. - Pin build-system dependencies where reproducibility is required. - Avoid labeling a mutable VCS installation as the recommended production installation method. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (13)

YARA rule 'agent_skill_remote_bootstrap_execution': Remote script or code download followed by execution/bootstrap installation [agent_skills]

High
Category
YARA Match
Content
d25519 signature on every message, impersonation impossible
- 🔄 **Forward secrecy** — X25519 ephemeral session keys
- 🛡️ **Replay protection** — nonce + counter deduplication
- 🌐 **Local or network** — LocalHub (in-process) or NetworkHub (TCP, multi-machine)
- 📦 **One dependency** — only `cryptography` required
- 🚀 **3-line quickstart**

---

## 📦 Installation

```bash
pip install git+https://github.com/cerbug45/AgentMesh.git
```

Or clone:

```bash
git clone https://github.com/cerbug45/AgentMesh.git
cd AgentMesh
pip install .
```

---

## 🚀 Quick Start

```python
from agentmesh import Agent, LocalHub

hub   = LocalHub()
alice = Agent("alice", hub=hub)
bob   = Agent("bob",   hub=hub)

@bob.on_message
def handle(msg):
    print(f"[{msg.recipient}] ← {msg.sender}: {msg.text}")

alice.send("bob", text="Hello! This is end-to-end encrypted 🔐")
```

```
[bob] ← alice: Hello! This is end-to-end encrypted 🔐
```

---

## 🌐 Network Mode

**Start the hu
Confidence
85% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

YARA rule 'agent_skill_remote_bootstrap_execution': Remote script or code download followed by execution/bootstrap installation [agent_skills]

High
Category
YARA Match
Content
d25519 signature on every message, impersonation impossible
- 🔄 **Forward secrecy** — X25519 ephemeral session keys
- 🛡️ **Replay protection** — nonce + counter deduplication
- 🌐 **Local or network** — LocalHub (in-process) or NetworkHub (TCP, multi-machine)
- 📦 **One dependency** — only `cryptography` required
- 🚀 **3-line quickstart**

---

## 📦 Installation

```bash
pip install git+https://github.com/cerbug45/AgentMesh.git
```

Or clone:

```bash
git clone https://github.com/cerbug45/AgentMesh.git
cd AgentMesh
pip install .
```

---

## 🚀 Quick Start

```python
from agentmesh import Agent, LocalHub

hub   = LocalHub()
alice = Agent("alice", hub=hub)
bob   = Agent("bob",   hub=hub)

@bob.on_message
def handle(msg):
    print(f"[{msg.recipient}] ← {msg.sender}: {msg.text}")

alice.send("bob", text="Hello! This is end-to-end encrypted 🔐")
```

```
[bob] ← alice: Hello! This is end-to-end encrypted 🔐
```

---

## 🌐 Network Mode

**Start the hu
Confidence
85% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Missing User Warnings

Medium
Confidence
86% confidence
Finding
The README advertises automatic key generation and optional persistence but does not warn that private cryptographic keys may be written to local storage, where they could be exposed through weak filesystem permissions, backups, logs, or multi-tenant hosts. In a security-focused messaging tool, omission of storage-safety guidance can lead operators to assume persistence is harmless, increasing the chance of key compromise and identity theft.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The network usage section instructs users to bind the hub server to 0.0.0.0 and connect over raw TCP, but it does not clearly warn that exposing the broker makes routing metadata and a remotely reachable service available to the network. Even if payloads are encrypted, unauthenticated or broadly exposed network services increase attack surface for enumeration, denial of service, and metadata collection.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The code persists the agent keypair, including private key material, to disk in plaintext JSON without any protection, access control checks, encryption, or warning to the caller. If the filesystem is accessible to another local user, malware, backups, or logs, an attacker could steal the private key and fully impersonate the agent, decrypt future traffic tied to that identity, and undermine trust in the mesh.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
The docstring makes a security-relevant claim that the hub never sees message contents and only routes opaque encrypted envelopes, but the implementation parses JSON messages and directly inspects plaintext fields such as cmd, bundle, envelope, envelope['to'], and bundle['agent_id']. This is dangerous because developers or users may rely on the documented privacy/trust boundary and deploy the hub in environments where the broker is assumed unable to read or tamper with metadata or payload structure, leading to misplaced trust and insecure architecture decisions.

Missing User Warnings

Low
Confidence
84% confidence
Finding
The skill documents persistent key storage and briefly notes to store the file securely, but it does not adequately warn that the file contains private key material that may be copied by backups, source control mistakes, shared volumes, or local compromise. This can lead to identity theft of the agent and loss of confidentiality/authentication guarantees for that identity.

Unverifiable Dependency: setuptools has 10 known advisory(ies) (CVE-2013-1633 (Setuptools vulnerable to Man-in-the-middle attacks); CVE-2025-47273 (setuptools has a path traversal vulnerability in PackageIndex.download that lead); CVE-2024-6345 (setuptools vulnerable to Command Injection via package URL) +7 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Unverifiable Dependency: wheel has 4 known advisory(ies) (CVE-2026-24049 (Wheel Affected by Arbitrary File Permission Modification via Path Traversal in w); CVE-2022-40898 (pypa/wheel vulnerable to Regular Expression denial of service (ReDoS)); CVE-2022-40898 (An issue discovered in Python Packaging Authority (PyPA) Wheel 0.37.1 and earlie) +1 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Unverifiable Dependency: cryptography has 16 known advisory(ies) (GHSA-39hc-v87j-747x (Vulnerable OpenSSL included in cryptography wheels); CVE-2023-50782 (Python Cryptography package vulnerable to Bleichenbacher timing oracle attack); GHSA-537c-gmf6-5ccf (Vulnerable OpenSSL included in cryptography wheels) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Unverifiable Dependency: pytest has 2 known advisory(ies) (CVE-2025-71176 (pytest has vulnerable tmpdir handling); CVE-2025-71176 (pytest has vulnerable tmpdir handling)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# AgentMesh – Runtime dependencies
cryptography>=42.0

# Development / testing (install with: pip install -r requirements-dev.txt)
Confidence
97% confidence
Finding
The dependency is specified as `cryptography>=42.0`, which allows any future release and does not produce reproducible installs. This increases supply-chain risk because vulnerable or breaking upstream versions could be pulled in without review, and the exact deployed version cannot be audited reliably.

Unverifiable Dependency: cryptography has 16 known advisory(ies) (GHSA-39hc-v87j-747x (Vulnerable OpenSSL included in cryptography wheels); CVE-2023-50782 (Python Cryptography package vulnerable to Bleichenbacher timing oracle attack); GHSA-537c-gmf6-5ccf (Vulnerable OpenSSL included in cryptography wheels) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
92% confidence
Finding
Because `cryptography` is not pinned, it is impossible to verify from this manifest whether the installed version avoids known advisories affecting some releases. In a security-sensitive library like `cryptography`, version ambiguity is especially risky because the package directly implements core cryptographic functionality and may bundle vulnerable components in some versions.

Static analysis

No suspicious patterns detected.