Use with caution. Address findings before production.
Scanned 5/3/2026, 6:47:01 PM·Cached result·Fast Scan·45 rules·How we decide ↗
AIVSS Score
Medium
Severity Breakdown
0
critical
6
high
684
medium
18
low
MCP Server Information
Findings
This package presents significant security concerns with a C grade and safety score of 32/100, driven primarily by 432 vulnerable dependencies and 168 instances of verbose error handling that could leak sensitive information. The 6 high-severity findings combined with 684 medium-severity issues—including server configuration weaknesses, container image vulnerabilities, and potential resource exhaustion risks—suggest it requires substantial hardening before production use. You should carefully evaluate whether the functionality justifies the security debt and consider implementing additional monitoring and isolation controls if you proceed with installation.
Dependencies
protobufjs (2)
protobuf (7)
pytest (1)
python-dotenv (37)
py (5)
Scan Details
Want deeper analysis?
Fast scan found 26 findings using rule-based analysis. Upgrade for LLM consensus across 5 judges, AI-generated remediation, and cross-file taint analysis.
Building your own MCP server?
Same rules, same LLM judges, same grade. Private scans stay isolated to your account and never appear in the public registry. Required for code your team hasn’t shipped yet.
26 of 26 findings
26 findings
MCP tool with a destructive-sounding name is registered without the `destructiveHint: true` annotation. Clients rely on this hint to gate user confirmation, so the model may invoke the tool silently. Add `{ annotations: { destructiveHint: true } }` (TS) or `destructive_hint=True` on the tool decorator (Python).
Evidence
| 1 | import os |
| 2 | import argparse |
| 3 | import logging |
| 4 | import json |
| 5 | import volcenginesdkcore |
| 6 | import volcenginesdkdts |
| 7 | import volcenginesdkdts20180101 |
| 8 | from typing import Optional, Final, Any, List |
| 9 | from pydantic import Field |
| 10 | from mcp_server_dts.config import load_config |
| 11 | from mcp.server.fastmcp import FastMCP |
| 12 | from mcp_server_dts import model |
| 13 | |
| 14 | openapi_cli = None |
| 15 | openapi_20180101_cli = None |
| 16 | |
| 17 | # Configure logging |
| 18 | logging.basicConfig( |
| 19 | level=logging.INFO, |
| 20 | format="%(asctime)s - %(name)s - %(levelname)s - %(mess |
Remediation
Missing annotation: add `{ annotations: { destructiveHint: true } }` as the 4th argument to `server.tool(...)` (TS) or pass `destructive_hint=True` to the `@mcp.tool(...)` decorator (Python). readOnly-lying: remove the `readOnlyHint: true` / `read_only_hint=True` assertion, or refactor the handler so it no longer calls the destructive sink. Do not suppress with a waiver — clients rely on these hints for user-facing confirmation.
MCP tool with a destructive-sounding name is registered without the `destructiveHint: true` annotation. Clients rely on this hint to gate user confirmation, so the model may invoke the tool silently. Add `{ annotations: { destructiveHint: true } }` (TS) or `destructive_hint=True` on the tool decorator (Python).
Evidence
| 1 | import argparse |
| 2 | import base64 |
| 3 | import json |
| 4 | import logging |
| 5 | import os |
| 6 | from typing import Optional |
| 7 | |
| 8 | import volcenginesdkcore |
| 9 | from dotenv import load_dotenv |
| 10 | from mcp.server.fastmcp import Context, FastMCP |
| 11 | from mcp.server.fastmcp.resources import HttpResource |
| 12 | from mcp.server.session import ServerSession |
| 13 | from starlette.requests import Request |
| 14 | |
| 15 | import mcp_server_vmp.config as config |
| 16 | import mcp_server_vmp.vmpapi as vmpapi |
| 17 | |
| 18 | # Configure logging |
| 19 | logging.basicConfig( |
| 20 | level=logging.INFO, format="%(asctime |
Remediation
Missing annotation: add `{ annotations: { destructiveHint: true } }` as the 4th argument to `server.tool(...)` (TS) or pass `destructive_hint=True` to the `@mcp.tool(...)` decorator (Python). readOnly-lying: remove the `readOnlyHint: true` / `read_only_hint=True` assertion, or refactor the handler so it no longer calls the destructive sink. Do not suppress with a waiver — clients rely on these hints for user-facing confirmation.
MCP tool with a destructive-sounding name is registered without the `destructiveHint: true` annotation. Clients rely on this hint to gate user confirmation, so the model may invoke the tool silently. Add `{ annotations: { destructiveHint: true } }` (TS) or `destructive_hint=True` on the tool decorator (Python).
Evidence
| 1 | # Copyright (c) Amazon.com, Inc. or its affiliates. |
| 2 | # Copyright (c) 2025 ByteDance Ltd. and/or its affiliates. |
| 3 | # SPDX-License-Identifier: Apache-2.0 |
| 4 | # |
| 5 | # This file has been modified by ByteDance Ltd. and/or its affiliates on 2025-10-30. |
| 6 | # |
| 7 | # Original file was released under the Apache License, Version 2.0. |
| 8 | # The full license text is available at: |
| 9 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | # |
| 11 | # This modified file is released under the same license. |
| 12 | |
| 13 | """VolcengineLabs Cloud Control API MCP Serv |
Remediation
Missing annotation: add `{ annotations: { destructiveHint: true } }` as the 4th argument to `server.tool(...)` (TS) or pass `destructive_hint=True` to the `@mcp.tool(...)` decorator (Python). readOnly-lying: remove the `readOnlyHint: true` / `read_only_hint=True` assertion, or refactor the handler so it no longer calls the destructive sink. Do not suppress with a waiver — clients rely on these hints for user-facing confirmation.
MCP tool with a destructive-sounding name is registered without the `destructiveHint: true` annotation. Clients rely on this hint to gate user confirmation, so the model may invoke the tool silently. Add `{ annotations: { destructiveHint: true } }` (TS) or `destructive_hint=True` on the tool decorator (Python).
Evidence
| 1 | from mcp.server.fastmcp import FastMCP |
| 2 | from .api.api import ImagexAPI |
| 3 | import uuid |
| 4 | import json |
| 5 | |
| 6 | |
| 7 | def Error(message: str): |
| 8 | return "API Error: " + message |
| 9 | |
| 10 | |
| 11 | def HandlerVolcResponse(response: dict): |
| 12 | if ( |
| 13 | response |
| 14 | and hasattr(response, "ResponseMetadata") |
| 15 | and response.ResponseMetadata |
| 16 | and hasattr(response.ResponseMetadata, "Error") |
| 17 | and response.ResponseMetadata.Error |
| 18 | ): |
| 19 | return Error(response.ResponseMetadata.Error.Message) |
| 20 | return str(res |
Remediation
Missing annotation: add `{ annotations: { destructiveHint: true } }` as the 4th argument to `server.tool(...)` (TS) or pass `destructive_hint=True` to the `@mcp.tool(...)` decorator (Python). readOnly-lying: remove the `readOnlyHint: true` / `read_only_hint=True` assertion, or refactor the handler so it no longer calls the destructive sink. Do not suppress with a waiver — clients rely on these hints for user-facing confirmation.
Install-time script pipes a remote download directly into a shell. Any `npm install` or `docker build` on this package will execute attacker-controlled code without review. Fetch a pinned artifact, verify a checksum, and invoke it explicitly — or drop the hook entirely.
Evidence
| 12 | TRANSPORT_TYPE=streamable-http |
| 13 | |
| 14 | COPY . . |
| 15 | |
| 16 | RUN curl -LsSf https://astral.sh/uv/install.sh | sh \ |
| 17 | && uv sync |
| 18 | |
| 19 | EXPOSE 8000 |
Remediation
Prefer libraries that do not require install-time code execution: - Drop `postinstall`/`preinstall`/`prepare` scripts if the work can happen at runtime or build-time instead. - Ship pre-built native binaries rather than compiling via a custom `cmdclass` or `build_ext` override. - For Dockerfiles: replace `RUN curl … | sh` with a pinned download + checksum verification + explicit `RUN` of a named script. - If the hook is unavoidable, document exactly what it does so downstream reviewers
TLS certificate verification is disabled on an outbound HTTP client. Any MITM in the network path can intercept and modify requests / responses — credentials, tokens, and tool output flow over a channel with no integrity guarantee. Python requests / httpx: drop `verify=False`. If the peer is using a private CA, set `verify="/path/to/ca-bundle.pem"` or configure the system trust store. Node TS axios / fetch: drop `rejectUnauthorized: false` from the agent / `httpsAgent` options. Same private-CA
Evidence
| 49 | ], |
| 50 | } |
| 51 | |
| 52 | response = requests.post(url, headers=headers, json=data, verify=False) |
| 53 | logger.info(f"response: {response}") |
| 54 | |
| 55 | response.raise_for_status() |
| 56 | |
| 57 | response_json = response.json() if response.content else None |
| 58 | logger.info(f"response_json: {response_json}") |
| 59 | results_dict = response_json.get('results')[0].get('content').get('results').get('organic') |
| 60 | logger.info(f"results_dict: {results_dict}") |
Remediation
Drop the verify-disable flag. If the peer presents a private CA: - Python: pass `verify="/path/to/ca.pem"` or trust the system store - Node: `new https.Agent({ ca: fs.readFileSync("ca.pem") })` - Go: load the CA via `x509.NewCertPool().AppendCertsFromPEM(...)` and set `tls.Config.RootCAs` Self-signed certificates: import the cert into the OS trust chain rather than disabling verification per-call.
`.env` file contains a credential-like variable name (API_KEY / TOKEN / SECRET / PASSWORD / PRIVATE_KEY / BEARER) assigned to what looks like a real value. `.env` files ship inside `git archive`, `docker build` contexts, and install tarballs — any secret here leaks downstream (MCP Top-10 R9). Replace the value with a placeholder, rename the file to `.env.example`, and load the real value from a secret manager at runtime. If the credential was already committed, revoke it now (it is still in git
Evidence
| 1 | # VolcEngine config example |
| 2 | VOLCENGINE_ACCESS_KEY=VOLCENGINE_ACCESS_KEY |
| 3 | VOLCENGINE_SECRET_KEY=VOLCENGINE_SECRET_KEY |
| 4 | VOLCENGINE_REGION=cn-beijing |
| 5 | VOLCENGINE_ENDPOINT=vpc.cn-beijing.volcengineapi.com |
Remediation
Remove the credential from the `.env` file and replace with a template placeholder: OPENAI_API_KEY=<your-openai-key> OPENAI_API_KEY=${OPENAI_API_KEY} Rename the file to `.env.example` so humans know it is a template. Store the real value in a secret manager and inject it at runtime. If the credential has already been committed, revoke it immediately (git history still contains it).
requests==2.32.3 has 2 known CVEs [MEDIUM]: GHSA-9hjg-9r4m-mvj7, GHSA-gc5v-m9x4-r6x2. Upgrade to a patched version.
Remediation
Upgrade the pinned dependency to a patched version. Check the CVE's advisory URL for the recommended safe release, or use `npm audit fix` / `pip-audit --fix`. If no patched release is available yet, pin to a known-good prior version, vendor the fix, or remove the dependency.
requests==2.32.3 has 2 known CVEs [MEDIUM]: GHSA-9hjg-9r4m-mvj7, GHSA-gc5v-m9x4-r6x2. Upgrade to a patched version.
Remediation
Upgrade the pinned dependency to a patched version. Check the CVE's advisory URL for the recommended safe release, or use `npm audit fix` / `pip-audit --fix`. If no patched release is available yet, pin to a known-good prior version, vendor the fix, or remove the dependency.
mcp==1.22.0 has 1 known CVE [HIGH]: GHSA-9h52-p55h-vw2f. Upgrade to a patched version.
Remediation
Upgrade the pinned dependency to a patched version. Check the CVE's advisory URL for the recommended safe release, or use `npm audit fix` / `pip-audit --fix`. If no patched release is available yet, pin to a known-good prior version, vendor the fix, or remove the dependency.
aiohttp==3.11.18 has 19 known CVEs [HIGH]: GHSA-2vrm-gr82-f7m5, GHSA-3wq7-rqq7-wx6j, GHSA-54jq-c3m8-4m76 (+16 more). Upgrade to a patched version.
Remediation
Upgrade the pinned dependency to a patched version. Check the CVE's advisory URL for the recommended safe release, or use `npm audit fix` / `pip-audit --fix`. If no patched release is available yet, pin to a known-good prior version, vendor the fix, or remove the dependency.
python-dotenv==1.1.0 has 1 known CVE [MEDIUM]: GHSA-mf9w-mj56-hr94. Upgrade to a patched version.
Remediation
Upgrade the pinned dependency to a patched version. Check the CVE's advisory URL for the recommended safe release, or use `npm audit fix` / `pip-audit --fix`. If no patched release is available yet, pin to a known-good prior version, vendor the fix, or remove the dependency.
urllib3==2.4.0 has 5 known CVEs [HIGH]: GHSA-2xpw-w6gg-jr37, GHSA-38jv-5279-wg99, GHSA-48p4-8xcf-vxj5 (+2 more). Upgrade to a patched version.
Remediation
Upgrade the pinned dependency to a patched version. Check the CVE's advisory URL for the recommended safe release, or use `npm audit fix` / `pip-audit --fix`. If no patched release is available yet, pin to a known-good prior version, vendor the fix, or remove the dependency.
python-multipart==0.0.20 has 2 known CVEs [HIGH]: GHSA-mj87-hwqh-73pj, GHSA-wp53-j4wj-2cfg. Upgrade to a patched version.
Remediation
Upgrade the pinned dependency to a patched version. Check the CVE's advisory URL for the recommended safe release, or use `npm audit fix` / `pip-audit --fix`. If no patched release is available yet, pin to a known-good prior version, vendor the fix, or remove the dependency.
python-dotenv==1.2.1 has 1 known CVE [MEDIUM]: GHSA-mf9w-mj56-hr94. Upgrade to a patched version.
Remediation
Upgrade the pinned dependency to a patched version. Check the CVE's advisory URL for the recommended safe release, or use `npm audit fix` / `pip-audit --fix`. If no patched release is available yet, pin to a known-good prior version, vendor the fix, or remove the dependency.
pygments==2.19.1 has 1 known CVE [LOW]: GHSA-5239-wwwm-4pmq. Upgrade to a patched version.
Remediation
Upgrade the pinned dependency to a patched version. Check the CVE's advisory URL for the recommended safe release, or use `npm audit fix` / `pip-audit --fix`. If no patched release is available yet, pin to a known-good prior version, vendor the fix, or remove the dependency.
mcp==1.12.2 has 1 known CVE [HIGH]: GHSA-9h52-p55h-vw2f. Upgrade to a patched version.
Remediation
Upgrade the pinned dependency to a patched version. Check the CVE's advisory URL for the recommended safe release, or use `npm audit fix` / `pip-audit --fix`. If no patched release is available yet, pin to a known-good prior version, vendor the fix, or remove the dependency.
python-dotenv==1.1.0 has 1 known CVE [MEDIUM]: GHSA-mf9w-mj56-hr94. Upgrade to a patched version.
Remediation
Upgrade the pinned dependency to a patched version. Check the CVE's advisory URL for the recommended safe release, or use `npm audit fix` / `pip-audit --fix`. If no patched release is available yet, pin to a known-good prior version, vendor the fix, or remove the dependency.
aiohttp==3.11.18 has 19 known CVEs [HIGH]: GHSA-2vrm-gr82-f7m5, GHSA-3wq7-rqq7-wx6j, GHSA-54jq-c3m8-4m76 (+16 more). Upgrade to a patched version.
Remediation
Upgrade the pinned dependency to a patched version. Check the CVE's advisory URL for the recommended safe release, or use `npm audit fix` / `pip-audit --fix`. If no patched release is available yet, pin to a known-good prior version, vendor the fix, or remove the dependency.
python-multipart==0.0.20 has 2 known CVEs [HIGH]: GHSA-mj87-hwqh-73pj, GHSA-wp53-j4wj-2cfg. Upgrade to a patched version.
Remediation
Upgrade the pinned dependency to a patched version. Check the CVE's advisory URL for the recommended safe release, or use `npm audit fix` / `pip-audit --fix`. If no patched release is available yet, pin to a known-good prior version, vendor the fix, or remove the dependency.
pygments==2.19.1 has 1 known CVE [LOW]: GHSA-5239-wwwm-4pmq. Upgrade to a patched version.
Remediation
Upgrade the pinned dependency to a patched version. Check the CVE's advisory URL for the recommended safe release, or use `npm audit fix` / `pip-audit --fix`. If no patched release is available yet, pin to a known-good prior version, vendor the fix, or remove the dependency.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 1006 | keys = list(cloud_resource.keys()) |
| 1007 | if keys: |
| 1008 | first_key = keys[0] |
| 1009 | target_function_id = cloud_resource.get(first_key, {}).get("function_id") |
| 1010 | except json.JSONDecodeError: |
| 1011 | pass |
| 1012 | |
| 1013 | # Fallback: try to get from Config |
| 1014 | if not target_function_id: |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 1128 | try: |
| 1129 | app_detail = client.get_application(target_application_id) |
| 1130 | cloud_resource = app_detail.get("Result", {}).get("CloudResource", "") |
| 1131 | access_url = extract_access_url_from_cloud_resource(cloud_resource) |
| 1132 | except: |
| 1133 | pass |
| 1134 | |
| 1135 | log(" → Deployment completed!") |
| 1136 | else: |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 1286 | data = cloud_resource[keys[0]] |
| 1287 | url_obj = data.get('url', {}) |
| 1288 | # Prefer system_url, fallback to inner_url |
| 1289 | access_url = url_obj.get('system_url') or url_obj.get('inner_url') |
| 1290 | except: |
| 1291 | pass |
| 1292 | |
| 1293 | # Build base response |
| 1294 | app_detail = { |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 30 | } |
| 31 | } |
| 32 | } |
| 33 | } catch {} |
| 34 | return defaultOptions; |
| 35 | } |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 116 | if isinstance(kwargs['CreateTime'], int): |
| 117 | try: |
| 118 | from datetime import datetime |
| 119 | kwargs['CreateTime'] = datetime.fromtimestamp(kwargs['CreateTime']).strftime("%Y-%m-%d %H:%M:%S") |
| 120 | except: |
| 121 | pass |
| 122 | if not isinstance(kwargs['CreateTime'], str): |
| 123 | kwargs['CreateTime'] = str(kwargs['CreateTime']) |
| 124 | if 'UpdateTime' in kwargs: |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
describe_transmission_tasks
list_workspaces
get_resource_schema_information
guide