Use with caution. Address findings before production.
Scanned 5/1/2026, 11:11:26 AM·Cached result·Fast Scan·45 rules·How we decide ↗
AIVSS Score
Medium
Severity Breakdown
0
critical
1
high
59
medium
22
low
MCP Server Information
Findings
This package has a low safety score of 44/100 and a security grade of C, indicating significant risks. It contains 60 security findings—mostly medium-severity issues like server misconfigurations (31), ANSI escape injection risks (12), and resource exhaustion vulnerabilities (11), plus one high-severity finding and hardcoded secrets (2). While no critical vulnerabilities were detected, the volume of medium-risk issues suggests poor security practices that could expose your system to exploitation or instability.
No known CVEs found for this package or its dependencies.
Scan Details
Want deeper analysis?
Fast scan found 82 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.
Showing 1–30 of 82 findings
82 findings
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
| 50 | } |
| 51 | } else if insecureMode { |
| 52 | transport.TLSClientConfig = &tls.Config{ |
| 53 | InsecureSkipVerify: true, // #nosec G402 |
| 54 | MinVersion: tls.VersionTLS12, |
| 55 | } |
| 56 | } else { |
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.
Hardcoded secret detected in source. MCP servers often proxy between the model and a third-party API, so any committed credential grants that access to anyone who can read the repo. Move to an environment variable or secret manager and rotate the leaked value.
Evidence
| 339 | ```bash |
| 340 | kubectl create secret generic aws-credentials \ |
| 341 | --from-literal=access-key-id='AKIAIOSFODNN7EXAMPLE' \ |
| 342 | --from-literal=secret-access-key='wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY' |
| 343 | ``` |
Remediation
Rotate the leaked credential immediately, then replace the hardcoded value with os.environ / process.env lookup. For deployment, inject the value through your secret manager (AWS Secrets Manager, Doppler, Vault).
Hardcoded secret detected in source. MCP servers often proxy between the model and a third-party API, so any committed credential grants that access to anyone who can read the repo. Move to an environment variable or secret manager and rotate the leaked value.
Evidence
| 289 | ```bash |
| 290 | kubectl create secret generic s3-credentials \ |
| 291 | --from-literal=access-key-id='AKIAIOSFODNN7EXAMPLE' \ |
| 292 | --from-literal=secret-access-key='wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY' |
| 293 | ``` |
Remediation
Rotate the leaked credential immediately, then replace the hardcoded value with os.environ / process.env lookup. For deployment, inject the value through your secret manager (AWS Secrets Manager, Doppler, Vault).
Service binds to 0.0.0.0 — all network interfaces. For MCP servers that only need to talk to a single parent process, bind to 127.0.0.1 (or a Unix domain socket) instead.
Evidence
| 2 | weaviate: |
| 3 | image: cr.weaviate.io/semitechnologies/weaviate:1.32.4 |
| 4 | command: |
| 5 | - --host |
| 6 | - 0.0.0.0 |
| 7 | - --port |
| 8 | - '8080' |
| 9 | - --scheme |
Remediation
Bind to 127.0.0.1 for local-only access. If cross-host access is truly required, put the service behind an authenticated reverse proxy rather than exposing it on 0.0.0.0.
Service binds to 0.0.0.0 — all network interfaces. For MCP servers that only need to talk to a single parent process, bind to 127.0.0.1 (or a Unix domain socket) instead.
Evidence
| 22 | weaviate: |
| 23 | image: cr.weaviate.io/semitechnologies/weaviate:1.32.4 |
| 24 | command: |
| 25 | - --host |
| 26 | - 0.0.0.0 |
| 27 | - --port |
| 28 | - '8080' |
| 29 | - --scheme |
Remediation
Bind to 127.0.0.1 for local-only access. If cross-host access is truly required, put the service behind an authenticated reverse proxy rather than exposing it on 0.0.0.0.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 781 | temp_file_path = f.name |
| 782 | |
| 783 | # Step 2: Upload batch input file |
| 784 | print("Step 2: Uploading batch input file...") |
| 785 | uploaded_file = client.files.upload( |
| 786 | file=temp_file_path, |
| 787 | config=UploadFileConfig(display_name='batch_e2e_gemini') |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 804 | jsonl_content = create_batch_jsonl(num_requests=3) |
| 805 | |
| 806 | # Step 2: Upload input file to S3 |
| 807 | print("Step 2: Uploading input file to S3...") |
| 808 | timestamp = int(time.time()) |
| 809 | s3_key = f"bifrost-batch-input/batch_{timestamp}.jsonl" |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 482 | {"custom_id": "req-2", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "anthropic.claude-3-sonnet-20240229-v1:0", "messages": [{"role": "user", "content": "What is the capital of France?"}], "max_tokens": 100}}''' |
| 483 | |
| 484 | # Step 2: Upload file |
| 485 | print("Step 1: Uploading batch input file...") |
| 486 | uploaded_file = client.files.create( |
| 487 | file=("batch_e2e.jsonl", jsonl_content.encode(), "application/jsonl"), |
| 488 | purpose="batch", |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 903 | bedrock_client.meta.events.register("before-send", add_provider_header) |
| 904 | |
| 905 | # Step 1: Create OpenAI JSONL content |
| 906 | print("Step 1: Creating OpenAI batch input file...") |
| 907 | |
| 908 | def create_openai_jsonl(num_requests: int) -> str: |
| 909 | lines = [] |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 755 | ) |
| 756 | |
| 757 | # Step 1: Create batch input file |
| 758 | print("Step 1: Creating batch input file...") |
| 759 | |
| 760 | def create_gemini_batch_json(num_requests: int) -> str: |
| 761 | requests_list = [] |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 425 | {"custom_id": "req-2", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "What is the capital of France?"}], "max_tokens": 100}}''' |
| 426 | |
| 427 | # Step 2: Upload file (uses OpenAI's native file storage) |
| 428 | print("Step 1: Uploading batch input file...") |
| 429 | uploaded_file = client.files.create( |
| 430 | file=("batch_e2e.jsonl", jsonl_content.encode(), "application/jsonl"), |
| 431 | purpose="batch", |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 363 | args = parser.parse_args() |
| 364 | |
| 365 | base_path = Path(__file__).parent.resolve() |
| 366 | print(f"Bundling OpenAPI spec from: {base_path / args.input}") |
| 367 | |
| 368 | try: |
| 369 | bundler = OpenAPIBundler(base_path) |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 781 | bedrock_client.meta.events.register("before-send", add_provider_header) |
| 782 | |
| 783 | # Step 1: Create JSONL content |
| 784 | print("Step 1: Creating batch input file...") |
| 785 | |
| 786 | def create_batch_jsonl(num_requests: int) -> str: |
| 787 | lines = [] |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 605 | {"custom_id": "req-2", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gemini-1.5-flash", "messages": [{"role": "user", "content": "What is the capital of France?"}], "max_tokens": 100}}''' |
| 606 | |
| 607 | # Step 2: Upload file (uses Gemini's native file storage) |
| 608 | print("Step 1: Uploading batch input file...") |
| 609 | uploaded_file = client.files.create( |
| 610 | file=("batch_e2e.jsonl", jsonl_content.encode(), "application/jsonl"), |
| 611 | purpose="batch", |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 1034 | jsonl_content = create_gemini_jsonl(num_requests=3) |
| 1035 | |
| 1036 | # Step 2: Upload input file (bucket/key are routing identifiers) |
| 1037 | print("Step 2: Uploading input file...") |
| 1038 | timestamp = int(time.time()) |
| 1039 | |
| 1040 | upload_response = s3_client.put_object( |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 1011 | bedrock_client.meta.events.register("before-send", add_provider_header) |
| 1012 | |
| 1013 | # Step 1: Create Gemini JSONL content |
| 1014 | print("Step 1: Creating Gemini batch input file...") |
| 1015 | |
| 1016 | def create_gemini_jsonl(num_requests: int) -> str: |
| 1017 | lines = [] |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 926 | jsonl_content = create_openai_jsonl(num_requests=3) |
| 927 | |
| 928 | # Step 2: Upload input file (bucket/key are routing identifiers) |
| 929 | print("Step 2: Uploading input file...") |
| 930 | timestamp = int(time.time()) |
| 931 | |
| 932 | upload_response = s3_client.put_object( |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
lodash.isequal==4.5.0 last released 3398 days ago (>730d) — possible abandoned package
Remediation
Typosquat: verify you meant the popular package. If so, correct the spelling; if you truly intended the less-common name, suppress with an inline waiver. Stale release: check whether the package has a maintained fork or successor. If no patched release exists, vendor the code or migrate to an active alternative before the unmaintained code accrues unfixed CVEs.
vite-plugin-monaco-editor==1.1.0 last released 1399 days ago (>730d) — possible abandoned package
Remediation
Typosquat: verify you meant the popular package. If so, correct the spelling; if you truly intended the less-common name, suppress with an inline waiver. Stale release: check whether the package has a maintained fork or successor. If no patched release exists, vendor the code or migrate to an active alternative before the unmaintained code accrues unfixed CVEs.
@types/lodash.isequal==4.5.8 last released 906 days ago (>730d) — possible abandoned package
Remediation
Typosquat: verify you meant the popular package. If so, correct the spelling; if you truly intended the less-common name, suppress with an inline waiver. Stale release: check whether the package has a maintained fork or successor. If no patched release exists, vendor the code or migrate to an active alternative before the unmaintained code accrues unfixed CVEs.
clsx==2.1.1 last released 738 days ago (>730d) — possible abandoned package
Remediation
Typosquat: verify you meant the popular package. If so, correct the spelling; if you truly intended the less-common name, suppress with an inline waiver. Stale release: check whether the package has a maintained fork or successor. If no patched release exists, vendor the code or migrate to an active alternative before the unmaintained code accrues unfixed CVEs.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 273 | // Check if a specific version exists on the download server |
| 274 | async function checkVersionExists(version, platformDir, archDir, binaryName) { |
| 275 | const url = `${BASE_URL}/bifrost/${version}/${platformDir}/${archDir}/${binaryName}`; |
| 276 | const res = await fetch(url, { method: "HEAD" }); |
| 277 | return res.ok; |
| 278 | } |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 92 | } |
| 93 | |
| 94 | async function downloadBinary(url, dest) { |
| 95 | const res = await fetch(url); |
| 96 | |
| 97 | if (!res.ok) { |
| 98 | console.error(`❌ Download failed: ${res.status} ${res.statusText}`); |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 595 | if (!root) return |
| 596 | |
| 597 | try { |
| 598 | const response = await fetch('https://getbifrost.ai/datasheet') |
| 599 | if (!response.ok) { |
| 600 | throw new Error('Failed to fetch models') |
| 601 | } |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 1051 | } |
| 1052 | ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) |
| 1053 | defer cancel() |
| 1054 | models, err := fetch(ctx, baseURL, vk) |
| 1055 | return modelsMsg{models: models, err: err} |
| 1056 | } |
| 1057 | } |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 146 | // Check if a specific version exists on the download server |
| 147 | async function checkVersionExists(version, platformDir, archDir, binaryName) { |
| 148 | const url = `${BASE_URL}/bifrost-cli/${version}/${platformDir}/${archDir}/${binaryName}`; |
| 149 | const res = await fetch(url, { method: "HEAD" }); |
| 150 | return res.ok; |
| 151 | } |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 152 | // Verify the downloaded binary against its SHA-256 checksum |
| 153 | async function verifyChecksum(binaryPath, checksumUrl) { |
| 154 | const res = await fetch(checksumUrl); |
| 155 | if (!res.ok) { |
| 156 | console.warn(`⚠️ Checksum file not available (${res.status}), skipping verification`); |
| 157 | return; |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 58 | } |
| 59 | |
| 60 | const { api_key_id: _, ...requestParams } = config.modelParams; |
| 61 | const response = await fetch(`${getBaseUrl()}/v1/chat/completions`, { |
| 62 | method: "POST", |
| 63 | headers, |
| 64 | body: JSON.stringify({ |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 101 | useEffect(() => { |
| 102 | async function fetchModels () { |
| 103 | try { |
| 104 | const response = await fetch('https://getbifrost.ai/datasheet') |
| 105 | if (!response.ok) { |
| 106 | throw new Error(`Failed to fetch models: ${response.status}`) |
| 107 | } |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 262 | // gets the latest version number for transport |
| 263 | async function getLatestVersion() { |
| 264 | const releaseUrl = "https://getbifrost.ai/latest-release"; |
| 265 | const res = await fetch(releaseUrl); |
| 266 | if (!res.ok) { |
| 267 | return null; |
| 268 | } |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 190 | async function downloadBinary(url, dest) { |
| 191 | // console.log(`🔄 Downloading binary from ${url}...`); |
| 192 | |
| 193 | const res = await fetch(url); |
| 194 | |
| 195 | if (!res.ok) { |
| 196 | console.error(`❌ Download failed: ${res.status} ${res.statusText}`); |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 67 | // Obtain a short-lived, single-use ticket for WS auth instead of putting the session token in the URL. |
| 68 | let wsUrlWithAuth = wsUrl; |
| 69 | try { |
| 70 | const resp = await fetch(`${getApiBaseUrl()}/session/ws-ticket`, { |
| 71 | method: "POST", |
| 72 | credentials: "include", |
| 73 | }); |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Overly permissive file mode or IAM wildcard. chmod 0777 and IAM "Action": "*" or "Resource": "*" grant far more access than a least-privilege MCP server needs.
Evidence
| 1295 | "Version": "2012-10-17", |
| 1296 | "Statement": [ |
| 1297 | { |
| 1298 | "Effect": "Allow", |
| 1299 | "Action": [ |
| 1300 | "ecr:GetAuthorizationToken", |
| 1301 | "ecr:BatchCheckLayerAvailability", |
| 1302 | "ecr:GetDownloadUrlForLayer", |
| 1303 | "ecr:BatchGetImage" |
| 1304 | ], |
| 1305 | "Resource": "*" |
| 1306 | }, |
| 1307 | { |
| 1308 | "Effect": "Allow", |
Remediation
File modes: use 0600 for secrets, 0644 for read-only data, 0755 for directories. IAM: scope Action to the specific service+verb (s3:GetObject) and Resource to exact ARNs. Never use * for both.
Overly permissive file mode or IAM wildcard. chmod 0777 and IAM "Action": "*" or "Resource": "*" grant far more access than a least-privilege MCP server needs.
Evidence
| 1331 | "Version": "2012-10-17", |
| 1332 | "Statement": [ |
| 1333 | { |
| 1334 | "Effect": "Allow", |
| 1335 | "Action": [ |
| 1336 | "ecr:GetAuthorizationToken", |
| 1337 | "ecr:BatchCheckLayerAvailability", |
| 1338 | "ecr:GetDownloadUrlForLayer", |
| 1339 | "ecr:BatchGetImage" |
| 1340 | ], |
| 1341 | "Resource": "*" |
| 1342 | }, |
| 1343 | { |
| 1344 | "Effect": "Allow", |
Remediation
File modes: use 0600 for secrets, 0644 for read-only data, 0755 for directories. IAM: scope Action to the specific service+verb (s3:GetObject) and Resource to exact ARNs. Never use * for both.
Overly permissive file mode or IAM wildcard. chmod 0777 and IAM "Action": "*" or "Resource": "*" grant far more access than a least-privilege MCP server needs.
Evidence
| 50 | "Statement": [ |
| 51 | { |
| 52 | "Sid": "ECRAuth", |
| 53 | "Effect": "Allow", |
| 54 | "Action": [ |
| 55 | "ecr:GetAuthorizationToken" |
| 56 | ], |
| 57 | "Resource": "*" |
| 58 | }, |
| 59 | { |
| 60 | "Sid": "ECRPullFromBifrost", |
Remediation
File modes: use 0600 for secrets, 0644 for read-only data, 0755 for directories. IAM: scope Action to the specific service+verb (s3:GetObject) and Resource to exact ARNs. Never use * for both.
Overly permissive file mode or IAM wildcard. chmod 0777 and IAM "Action": "*" or "Resource": "*" grant far more access than a least-privilege MCP server needs.
Evidence
| 253 | "Resource": "arn:aws:ecr:us-east-1:BIFROST_ACCOUNT_ID:repository/YOUR_HUB_SLUG" |
| 254 | }, |
| 255 | { |
| 256 | "Effect": "Allow", |
| 257 | "Action": [ |
| 258 | "logs:CreateLogStream", |
| 259 | "logs:PutLogEvents" |
| 260 | ], |
| 261 | "Resource": "*" |
| 262 | } |
| 263 | ] |
| 264 | } |
Remediation
File modes: use 0600 for secrets, 0644 for read-only data, 0755 for directories. IAM: scope Action to the specific service+verb (s3:GetObject) and Resource to exact ARNs. Never use * for both.
Overly permissive file mode or IAM wildcard. chmod 0777 and IAM "Action": "*" or "Resource": "*" grant far more access than a least-privilege MCP server needs.
Evidence
| 237 | "Version": "2012-10-17", |
| 238 | "Statement": [ |
| 239 | { |
| 240 | "Effect": "Allow", |
| 241 | "Action": [ |
| 242 | "ecr:GetAuthorizationToken" |
| 243 | ], |
| 244 | "Resource": "*" |
| 245 | }, |
| 246 | { |
| 247 | "Effect": "Allow", |
Remediation
File modes: use 0600 for secrets, 0644 for read-only data, 0755 for directories. IAM: scope Action to the specific service+verb (s3:GetObject) and Resource to exact ARNs. Never use * for both.
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 3169 | "vllm_key_config": { |
| 3170 | "type": "object", |
| 3171 | "properties": { |
| 3172 | "url": { |
| 3173 | "type": "string", |
| 3174 | "description": "VLLM server base URL (can use env. prefix)" |
| 3175 | }, |
| 3176 | "model_name": { |
| 3177 | "type": "string", |
| 3178 | "description": "Exact model name served on this VLLM instance" |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 887 | "then": { |
| 888 | "type": "object", |
| 889 | "properties": { |
| 890 | "path": { |
| 891 | "type": "string", |
| 892 | "description": "Database file path" |
| 893 | } |
| 894 | }, |
| 895 | "required": ["path"], |
| 896 | "additionalProperties": false |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 61 | }); |
| 62 | |
| 63 | const ReadFileSchema = z.object({ |
| 64 | path: z.string().describe("The file path to read"), |
| 65 | }); |
| 66 | |
| 67 | const DelaySchema = z.object({ |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 3448 | "stdioConfig": { |
| 3449 | "type": "object", |
| 3450 | "properties": { |
| 3451 | "command": { |
| 3452 | "type": "string" |
| 3453 | }, |
| 3454 | "args": { |
| 3455 | "type": "array", |
| 3456 | "items": { |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 980 | "enabled": { |
| 981 | "type": "boolean" |
| 982 | }, |
| 983 | "path": { |
| 984 | "type": "string" |
| 985 | }, |
| 986 | "version": { |
| 987 | "type": "integer", |
| 988 | "minimum": 1 |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 986 | }, |
| 987 | "then": { |
| 988 | "properties": { |
| 989 | "path": { |
| 990 | "type": "string", |
| 991 | "description": "Database file path" |
| 992 | } |
| 993 | }, |
| 994 | "required": ["path"], |
| 995 | "additionalProperties": false |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 2763 | "stdio_config": { |
| 2764 | "type": "object", |
| 2765 | "properties": { |
| 2766 | "command": { |
| 2767 | "type": "string", |
| 2768 | "description": "Command to execute" |
| 2769 | }, |
| 2770 | "args": { |
| 2771 | "type": "array", |
| 2772 | "items": { |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 9 | const ProxyConfigSchema = z |
| 10 | .object({ |
| 11 | type: ProxyTypeSchema, |
| 12 | url: z.string().optional(), |
| 13 | username: z.string().optional(), |
| 14 | password: z.string().optional(), |
| 15 | }) |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 3876 | "vllm_key_config": { |
| 3877 | "type": "object", |
| 3878 | "properties": { |
| 3879 | "url": { |
| 3880 | "type": "string", |
| 3881 | "description": "VLLM server base URL (can use env. prefix)" |
| 3882 | }, |
| 3883 | "model_name": { |
| 3884 | "type": "string", |
| 3885 | "description": "Exact model name served on this VLLM instance" |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 3479 | "httpConfig": { |
| 3480 | "type": "object", |
| 3481 | "properties": { |
| 3482 | "url": { |
| 3483 | "type": "string", |
| 3484 | "format": "uri" |
| 3485 | } |
| 3486 | }, |
| 3487 | "required": ["url"] |
| 3488 | }, |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 132 | "items": { |
| 133 | "type": "object", |
| 134 | "properties": { |
| 135 | "path": { |
| 136 | "type": "string" |
| 137 | }, |
| 138 | "pathType": { |
| 139 | "type": "string", |
| 140 | "enum": ["Prefix", "Exact", "ImplementationSpecific"] |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 53 | }); |
| 54 | |
| 55 | const SearchSchema = z.object({ |
| 56 | query: z.string().describe("The search query"), |
| 57 | }); |
| 58 | |
| 59 | const GetTimeSchema = z.object({ |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 24 | const pluginFormSchema = z.object({ |
| 25 | name: z.string().min(1, "Name is required"), |
| 26 | enabled: z.boolean(), |
| 27 | path: z.string().optional(), |
| 28 | config: z.string().optional(), |
| 29 | hasConfig: z.boolean(), |
| 30 | }); |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 2332 | "sgl_key_config": { |
| 2333 | "type": "object", |
| 2334 | "properties": { |
| 2335 | "url": { |
| 2336 | "type": "string", |
| 2337 | "minLength": 1, |
| 2338 | "description": "SGLang server base URL (can use env. prefix)" |
| 2339 | } |
| 2340 | }, |
| 2341 | "required": ["url"], |
| 2342 | "additionalProperties": false |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 1187 | "type": "object", |
| 1188 | "description": "Configuration for the plugin" |
| 1189 | }, |
| 1190 | "path": { |
| 1191 | "type": "string", |
| 1192 | "description": "Path to the plugin (optional, required for dynamic plugins)", |
| 1193 | "optional": true |
| 1194 | }, |
| 1195 | "version": { |
| 1196 | "type": "integer", |
| 1197 | "minimum": 1, |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 3469 | "websocketConfig": { |
| 3470 | "type": "object", |
| 3471 | "properties": { |
| 3472 | "url": { |
| 3473 | "type": "string", |
| 3474 | "format": "uri" |
| 3475 | } |
| 3476 | }, |
| 3477 | "required": ["url"] |
| 3478 | }, |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 1123 | .object({ |
| 1124 | enabled: z.boolean(), |
| 1125 | type: globalProxyTypeSchema, |
| 1126 | url: z.string(), |
| 1127 | username: z.string().optional(), |
| 1128 | password: z.string().optional(), |
| 1129 | ca_cert_pem: z.string().optional(), |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 2307 | "ollama_key_config": { |
| 2308 | "type": "object", |
| 2309 | "properties": { |
| 2310 | "url": { |
| 2311 | "type": "string", |
| 2312 | "minLength": 1, |
| 2313 | "description": "Ollama server base URL (can use env. prefix)" |
| 2314 | } |
| 2315 | }, |
| 2316 | "required": ["url"], |
| 2317 | "additionalProperties": false |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 2255 | "vllm_key_config": { |
| 2256 | "type": "object", |
| 2257 | "properties": { |
| 2258 | "url": { |
| 2259 | "type": "string", |
| 2260 | "minLength": 1, |
| 2261 | "description": "VLLM server base URL (can use env. prefix)" |
| 2262 | }, |
| 2263 | "model_name": { |
| 2264 | "type": "string", |
| 2265 | "minLength": 1, |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
Package declares an install-time hook (npm postinstall/preinstall/prepare, setup.py cmdclass override, custom setuptools install class, or non-default pyproject build-backend). Anyone installing this package runs the hook. Confirm the hook is necessary and review its contents; prefer shipping a plain library without install-time execution.
Evidence
| 8 | }, |
| 9 | "scripts": { |
| 10 | "build": "tsc && chmod +x dist/index.js", |
| 11 | "prepare": "npm run build" |
| 12 | }, |
| 13 | "dependencies": { |
| 14 | "@modelcontextprotocol/sdk": "^1.0.4", |
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
Package declares an install-time hook (npm postinstall/preinstall/prepare, setup.py cmdclass override, custom setuptools install class, or non-default pyproject build-backend). Anyone installing this package runs the hook. Confirm the hook is necessary and review its contents; prefer shipping a plain library without install-time execution.
Evidence
| 8 | }, |
| 9 | "scripts": { |
| 10 | "build": "tsc && chmod +x dist/index.js", |
| 11 | "prepare": "npm run build" |
| 12 | }, |
| 13 | "dependencies": { |
| 14 | "@modelcontextprotocol/sdk": "^1.0.4", |
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
Package declares an install-time hook (npm postinstall/preinstall/prepare, setup.py cmdclass override, custom setuptools install class, or non-default pyproject build-backend). Anyone installing this package runs the hook. Confirm the hook is necessary and review its contents; prefer shipping a plain library without install-time execution.
Evidence
| 8 | }, |
| 9 | "scripts": { |
| 10 | "build": "tsc && chmod +x dist/index.js", |
| 11 | "prepare": "npm run build" |
| 12 | }, |
| 13 | "dependencies": { |
| 14 | "@modelcontextprotocol/sdk": "^1.0.4", |
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
Package declares an install-time hook (npm postinstall/preinstall/prepare, setup.py cmdclass override, custom setuptools install class, or non-default pyproject build-backend). Anyone installing this package runs the hook. Confirm the hook is necessary and review its contents; prefer shipping a plain library without install-time execution.
Evidence
| 8 | }, |
| 9 | "scripts": { |
| 10 | "build": "tsc && chmod +x dist/index.js", |
| 11 | "prepare": "npm run build" |
| 12 | }, |
| 13 | "dependencies": { |
| 14 | "@modelcontextprotocol/sdk": "^1.0.4", |
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
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
| 120 | }), |
| 121 | ); |
| 122 | } |
| 123 | } catch {} |
| 124 | }, |
| 125 | }), |
| 126 | }), |
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
| 48 | async onQueryStarted(arg, { queryFulfilled }) { |
| 49 | try { |
| 50 | await queryFulfilled; |
| 51 | } catch { |
| 52 | } finally { |
| 53 | clearAuthStorage(); |
| 54 | } |
| 55 | }, |
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
| 42 | onBlur={() => { |
| 43 | try { |
| 44 | setCurrentValue(JSON.stringify(JSON.parse(currentValue), null, 2)); |
| 45 | } catch {} |
| 46 | }} |
| 47 | lang="json" |
| 48 | wrap={true} |
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
| 37 | setCurrentValue(v); |
| 38 | try { |
| 39 | props.onChange(JSON.parse(v)); |
| 40 | } catch {} |
| 41 | }} |
| 42 | onBlur={() => { |
| 43 | try { |
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
| 237 | } |
| 238 | }), |
| 239 | ); |
| 240 | } catch {} |
| 241 | }, |
| 242 | }), |
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
| 80 | }), |
| 81 | ); |
| 82 | } |
| 83 | } catch {} |
| 84 | }, |
| 85 | }), |
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
| 80 | } |
| 81 | }), |
| 82 | ); |
| 83 | } catch {} |
| 84 | }, |
| 85 | }), |
| 86 | }), |
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
| 92 | ); |
| 93 | } |
| 94 | dispatch(routingRulesApi.util.updateQueryData("getRoutingRule", updatedRule.id, () => updatedRule)); |
| 95 | } catch {} |
| 96 | }, |
| 97 | }), |
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
| 207 | } |
| 208 | }), |
| 209 | ); |
| 210 | } catch {} |
| 211 | }, |
| 212 | }), |
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
| 304 | await verifyChecksum(tempBinaryPath, checksumUrl); |
| 305 | renameSync(tempBinaryPath, binaryPath); |
| 306 | } catch (err) { |
| 307 | try { unlinkSync(tempBinaryPath); } catch {} |
| 308 | throw err; |
| 309 | } |
| 310 | console.log(`✅ Installed bifrost to ${binaryPath}`); |
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
| 44 | dispatch(mcpApi.util.invalidateTags(["MCPClients"])); |
| 45 | break; |
| 46 | } |
| 47 | } catch {} |
| 48 | }, |
| 49 | }), |
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
| 108 | }), |
| 109 | ); |
| 110 | } |
| 111 | } catch {} |
| 112 | }, |
| 113 | }), |
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
| 63 | ); |
| 64 | } |
| 65 | dispatch(routingRulesApi.util.updateQueryData("getRoutingRule", newRule.id, () => newRule)); |
| 66 | } catch {} |
| 67 | }, |
| 68 | }), |
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
| 172 | }), |
| 173 | ); |
| 174 | dispatch(providersApi.util.updateQueryData("getProvider", arg.name, () => updatedProvider)); |
| 175 | } catch {} |
| 176 | }, |
| 177 | }), |
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
| 34 | ); |
| 35 | // Also update the individual plugin cache |
| 36 | dispatch(pluginsApi.util.updateQueryData("getPlugin", newPlugin.name, () => newPlugin)); |
| 37 | } catch {} |
| 38 | }, |
| 39 | }), |
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
| 148 | draft.sort(sortProviders); |
| 149 | }), |
| 150 | ); |
| 151 | } catch {} |
| 152 | }, |
| 153 | }), |
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
| 295 | dispatch( |
| 296 | providersApi.util.updateQueryData("getAllKeys", undefined, (draft) => draft.filter((key) => key.provider !== providerName)), |
| 297 | ); |
| 298 | } catch {} |
| 299 | }, |
| 300 | }), |
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
| 613 | if (log.params?.tools) { |
| 614 | try { |
| 615 | toolsParameter = JSON.stringify(log.params.tools, null, 2); |
| 616 | } catch { } |
| 617 | } |
| 618 | |
| 619 | const audioFormat = |
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
| 265 | } |
| 266 | }), |
| 267 | ); |
| 268 | } catch {} |
| 269 | }, |
| 270 | }), |
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
| 59 | ); |
| 60 | // Also update the individual plugin cache |
| 61 | dispatch(pluginsApi.util.updateQueryData("getPlugin", arg.name, () => updatedPlugin)); |
| 62 | } catch {} |
| 63 | }, |
| 64 | }), |
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
| 636 | if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) { |
| 637 | return Object.values(parsed).reduce<number>((sum, v) => sum + (Array.isArray(v) ? v.length : 0), 0); |
| 638 | } |
| 639 | } catch { } |
| 640 | return 0; |
| 641 | })(); |
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
| 142 | } else if (typeof parsedValue === "string") { |
| 143 | valueToUse = parsedValue; |
| 144 | } |
| 145 | } catch(error) {} |
| 146 | } |
| 147 | |
| 148 | // For single operators (=, !=), use single select |
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.