ai.klavis/strata
version 1.0.0
- scanned 2026-10-16
- source github.com/Klavis-AI/klavis
- commit 45c9f7da83d1
- transport streamable-http
- files read 1286
- methodology 0.2.0
- ruleset 0.1.1
No tag matching version 1.0.0 was found in this repository, so the scan read the default branch instead. The findings below describe that code, not necessarily the released version.
8measured on 99% of this axis
2 vendored or minified paths were excluded before scanning; machine-generated bundles are not the server's own code; 6 files could not be parsed and were not scanned
75
0measured on 49% of this axis
56 vulnerabilities could not be placed in `03` §6's table and are listed but not scored; the dependencies in 63 requirements files (examples/agno-klavis/requirements.txt, examples/claude-klavis/python/requirements.txt, examples/crewai-klavis/python/requirements.txt) were not measured — they pin no exact version, or could not be read whole — so the score covers the 65 lockfiles that were
59measured on 90% of this axis
83measured on 80% of this axis
The evidence
Every deduction below names the artefact that produced it. Nothing on this page was executed: the source was read, never run, and no running server was contacted.
Code Safety
Showing the 50 most severe of 77 findings on this axis. The score was computed over all of them — findings beyond the fourth of a severity still deduct at a tenth of their weight — so the remainder is omitted from this page, not from the arithmetic.
- mcp_servers/12306/src/index.ts:1458mcp-js-dynamic-code-execution (critical/medium)
Caller-influenced input reaches an evaluator. eval, the Function constructor and vm.runInNewContext all execute their argument; none of them sandbox anything by default, vm least of all despite the name.
throw new Error('Error: get station name js file failed.'); } const rawData = eval(stationNameJS.replace('var station_names =', '')); const stationsData = parseStationsData(rawData); // 加上缺失的车站信息 - mcp_servers/local/terminal/src/cli_mcp_server/server.py:344mcp-python-shell-true-nonliteral (critical/medium)
A subprocess is spawned with shell=True on a value that is not a string literal. Any caller-supplied component of that value is shell-injectable: `; rm -rf ~` in an argument is executed, not passed.
if use_shell: # For commands with shell operators, execute with shell=True return subprocess.run( command, # command is the full command string in this case shell=True, - mcp_servers/tavily/tools/extract.py:44mcp-python-archive-extract-unconfined (critical/medium)
An archive is extracted without validating member paths. A tar or zip entry may name `../` or an absolute path and write outside the destination; Python's extractall has historically done exactly that.
logger.info(f"tavily_extract: {len(urls)} url(s)") return client.extract(**{k: v for k, v in params.items() if v is not None}) - mcp_servers/12306/src/index.ts:890mcp-js-prototype-pollution-merge-loop (medium/medium)
Keys from a caller-supplied object are copied onto a target without excluding __proto__ / constructor / prototype. A tool argument carrying __proto__ then mutates Object.prototype for the whole process, which can turn an unrelated later property read into attacker-controlled data.
for (const city of citys.split('|')) { if (!(city in CITY_CODES)) { result[city] = { error: '未检索到城市。' }; } else { result[city] = CITY_CODES[city]; - mcp_servers/12306/src/index.ts:892mcp-js-prototype-pollution-merge-loop (medium/medium)
Keys from a caller-supplied object are copied onto a target without excluding __proto__ / constructor / prototype. A tool argument carrying __proto__ then mutates Object.prototype for the whole process, which can turn an unrelated later property read into attacker-controlled data.
result[city] = { error: '未检索到城市。' }; } else { result[city] = CITY_CODES[city]; } } - mcp_servers/12306/src/index.ts:918mcp-js-prototype-pollution-merge-loop (medium/medium)
Keys from a caller-supplied object are copied onto a target without excluding __proto__ / constructor / prototype. A tool argument carrying __proto__ then mutates Object.prototype for the whole process, which can turn an unrelated later property read into attacker-controlled data.
: stationName; if (!(stationName in NAME_STATIONS)) { result[stationName] = { error: '未检索到城市。' }; } else { result[stationName] = NAME_STATIONS[stationName]; - mcp_servers/12306/src/index.ts:920mcp-js-prototype-pollution-merge-loop (medium/medium)
Keys from a caller-supplied object are copied onto a target without excluding __proto__ / constructor / prototype. A tool argument carrying __proto__ then mutates Object.prototype for the whole process, which can turn an unrelated later property read into attacker-controlled data.
result[stationName] = { error: '未检索到城市。' }; } else { result[stationName] = NAME_STATIONS[stationName]; } } - mcp_servers/hugging_face/packages/app/src/server/utils/mcp-api-client.ts:164mcp-js-prototype-pollution-merge-loop (medium/medium)
Keys from a caller-supplied object are copied onto a target without excluding __proto__ / constructor / prototype. A tool argument carrying __proto__ then mutates Object.prototype for the whole process, which can turn an unrelated later property read into attacker-controlled data.
const toolStates: Record<string, boolean> = {}; for (const toolId of ALL_BUILTIN_TOOL_IDS) { toolStates[toolId] = settings.builtInTools.includes(toolId); } - mcp_servers/hugging_face/packages/app/src/server/utils/mcp-api-client.ts:171mcp-js-prototype-pollution-merge-loop (medium/medium)
Keys from a caller-supplied object are copied onto a target without excluding __proto__ / constructor / prototype. A tool argument carrying __proto__ then mutates Object.prototype for the whole process, which can turn an unrelated later property read into attacker-controlled data.
for (const id of settings.builtInTools) { if (!(id in toolStates)) { toolStates[id] = true; } } - mcp_servers/notion_atlas/src/openapi-mcp-server/client/http-client.ts:141mcp-js-prototype-pollution-merge-loop (medium/medium)
Keys from a caller-supplied object are copied onto a target without excluding __proto__ / constructor / prototype. A tool argument carrying __proto__ then mutates Object.prototype for the whole process, which can turn an unrelated later property read into attacker-controlled data.
for (const key in bodyParams) { if (bodyParams[key] !== undefined) { urlParameters[key] = bodyParams[key] delete bodyParams[key] } - mcp_servers/notion_mcpmark/src/openapi-mcp-server/client/http-client.ts:148mcp-js-prototype-pollution-merge-loop (medium/medium)
Keys from a caller-supplied object are copied onto a target without excluding __proto__ / constructor / prototype. A tool argument carrying __proto__ then mutates Object.prototype for the whole process, which can turn an unrelated later property read into attacker-controlled data.
for (const key in bodyParams) { if (bodyParams[key] !== undefined) { urlParameters[key] = bodyParams[key] delete bodyParams[key] } - mcp_servers/notion_official/src/openapi-mcp-server/client/http-client.ts:141mcp-js-prototype-pollution-merge-loop (medium/medium)
Keys from a caller-supplied object are copied onto a target without excluding __proto__ / constructor / prototype. A tool argument carrying __proto__ then mutates Object.prototype for the whole process, which can turn an unrelated later property read into attacker-controlled data.
for (const key in bodyParams) { if (bodyParams[key] !== undefined) { urlParameters[key] = bodyParams[key] delete bodyParams[key] } - mcp_servers/notion_toolathlon/src/openapi-mcp-server/client/http-client.ts:161mcp-js-prototype-pollution-merge-loop (medium/medium)
Keys from a caller-supplied object are copied onto a target without excluding __proto__ / constructor / prototype. A tool argument carrying __proto__ then mutates Object.prototype for the whole process, which can turn an unrelated later property read into attacker-controlled data.
for (const key in bodyParams) { if (bodyParams[key] !== undefined) { urlParameters[key] = bodyParams[key] delete bodyParams[key] } - mcp_servers/youtube_toolathlon/src/functions/content/translations.ts:85mcp-js-prototype-pollution-merge-loop (medium/medium)
Keys from a caller-supplied object are copied onto a target without excluding __proto__ / constructor / prototype. A tool argument carrying __proto__ then mutates Object.prototype for the whole process, which can turn an unrelated later property read into attacker-controlled data.
const [translation] = await this.translate.translate(track.data, lang); if (!results[lang]) { results[lang] = []; } results[lang].push(translation); - mcp_servers/youtube_toolathlon/src/functions/content/translations.ts:138mcp-js-prototype-pollution-merge-loop (medium/medium)
Keys from a caller-supplied object are copied onto a target without excluding __proto__ / constructor / prototype. A tool argument carrying __proto__ then mutates Object.prototype for the whole process, which can turn an unrelated later property read into attacker-controlled data.
for (const lang of targetLanguages) { translations[lang] = {}; const snippet = video.data.items[0].snippet; - mcp_servers/youtube_toolathlon/src/functions/content/translations.ts:154mcp-js-prototype-pollution-merge-loop (medium/medium)
Keys from a caller-supplied object are copied onto a target without excluding __proto__ / constructor / prototype. A tool argument carrying __proto__ then mutates Object.prototype for the whole process, which can turn an unrelated later property read into attacker-controlled data.
if (content) { const [translation] = await this.translate.translate(content, lang); translations[lang][field] = translation; } } - mcp_servers/youtube_toolathlon/src/utils/dataUtils.ts:26mcp-js-prototype-pollution-merge-loop (medium/medium)
Keys from a caller-supplied object are copied onto a target without excluding __proto__ / constructor / prototype. A tool argument carrying __proto__ then mutates Object.prototype for the whole process, which can turn an unrelated later property read into attacker-controlled data.
for (const key in cleaned) { if (typeof cleaned[key] === 'object' && cleaned[key] !== null) { cleaned[key] = removeThumbnails(cleaned[key]); } } - examples/openai-klavis/strata-python/requests_main.py:29mcp-python-ssrf-nonliteral-url (medium/low)
An outbound HTTP request is made to a URL that is not a literal. If any part of it is caller-supplied, the server can be steered at internal hosts — cloud metadata endpoints, admin ports, other tenants.
url = f"{self.base_url}/mcp-server/strata/create" payload = {"userId": user_id, "servers": servers} response = requests.post(url, headers=self.headers, json=payload) response.raise_for_status() return response.json() - examples/openai-klavis/strata-python/requests_main.py:37mcp-python-ssrf-nonliteral-url (medium/low)
An outbound HTTP request is made to a URL that is not a literal. If any part of it is caller-supplied, the server can be steered at internal hosts — cloud metadata endpoints, admin ports, other tenants.
url = f"{self.base_url}/mcp-server/list-tools" payload = {"serverUrl": server_url, "format": format} response = requests.post(url, headers=self.headers, json=payload) response.raise_for_status() return response.json() - examples/openai-klavis/strata-python/requests_main.py:45mcp-python-ssrf-nonliteral-url (medium/low)
An outbound HTTP request is made to a URL that is not a literal. If any part of it is caller-supplied, the server can be steered at internal hosts — cloud metadata endpoints, admin ports, other tenants.
url = f"{self.base_url}/mcp-server/call-tool" payload = {"serverUrl": server_url, "toolName": tool_name, "toolArgs": tool_args} response = requests.post(url, headers=self.headers, json=payload) response.raise_for_status() return response.json() - examples/openai-klavis/strata-python/requests_main.py:168mcp-python-ssrf-nonliteral-url (medium/low)
An outbound HTTP request is made to a URL that is not a literal. If any part of it is caller-supplied, the server can be steered at internal hosts — cloud metadata endpoints, admin ports, other tenants.
} response = requests.post(openai_url, headers=openai_headers, json=payload) response.raise_for_status() response_data = response.json() - mcp_servers/12306/src/index.ts:775mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
): Promise<T | null> { try { const response = await axios.get(url + '?' + scheme.toString(), { headers: headers, timeout: 30000, - mcp_servers/attio/index.ts:41mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
}; const response = await fetch(url, { ...options, headers, - mcp_servers/brave_search_atlas/index.ts:188mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
url.searchParams.set('offset', offset.toString()); const response = await fetch(url, { headers: { 'Accept': 'application/json', - mcp_servers/brave_search_atlas/index.ts:220mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
webUrl.searchParams.set('count', Math.min(count, 20).toString()); const webResponse = await fetch(webUrl, { headers: { 'Accept': 'application/json', - mcp_servers/brave_search_atlas/index.ts:251mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
const url = new URL('https://api.search.brave.com/res/v1/local/pois'); ids.filter(Boolean).forEach(id => url.searchParams.append('ids', id)); const response = await fetch(url, { headers: { 'Accept': 'application/json', - mcp_servers/brave_search_atlas/index.ts:270mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
const url = new URL('https://api.search.brave.com/res/v1/local/descriptions'); ids.filter(Boolean).forEach(id => url.searchParams.append('ids', id)); const response = await fetch(url, { headers: { 'Accept': 'application/json', - mcp_servers/context7/packages/cli/src/utils/github.ts:95mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
const treeUrl = `${GITHUB_API}/repos/${owner}/${repo}/git/trees/${branch}?recursive=1`; const treeResponse = await fetch(treeUrl, { headers: { Accept: "application/vnd.github.v3+json", - mcp_servers/context7/packages/cli/src/utils/github.ts:119mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
for (const item of skillFiles) { const rawUrl = `${GITHUB_RAW}/${owner}/${repo}/${branch}/${item.path}`; const fileResponse = await fetch(rawUrl); if (!fileResponse.ok) { - mcp_servers/context7/packages/mcp/src/lib/api.ts:61mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
const headers = generateHeaders(context); const response = await fetch(url, { headers }); if (!response.ok) { const errorMessage = await parseErrorResponse(response, context.apiKey); - mcp_servers/context7/packages/mcp/src/lib/api.ts:87mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
const headers = generateHeaders(context); const response = await fetch(url, { headers }); if (!response.ok) { const errorMessage = await parseErrorResponse(response, context.apiKey); - mcp_servers/context7/packages/sdk/src/http/index.ts:155mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
for (let i = 0; i <= this.retry.attempts; i++) { try { res = await fetch(url, requestOptions as RequestInit); break; } catch (error_) { - mcp_servers/fetch_toolathlon/src/Fetcher.ts:14mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
}: RequestPayload): Promise<Response> { try { const response = await fetch(url, { headers: { "User-Agent": - mcp_servers/freshdesk/tools/base.py:337mcp-python-ssrf-nonliteral-url (medium/low)
An outbound HTTP request is made to a URL that is not a literal. If any part of it is caller-supplied, the server can be steered at internal hosts — cloud metadata endpoints, admin ports, other tenants.
)) elif attachment["type"] == "url": file_content = requests.get(attachment["content"]).content file_name = attachment.get("name", gen_random_password(15)) resolved_attachments.append(( - mcp_servers/github_mcpmark/pkg/github/actions.go:750mcp-go-ssrf-nonliteral-url (medium/low)
An outbound HTTP request is made to a URL that is not a literal. If any component is caller-supplied the server can be aimed at hosts it can reach and the caller cannot.
finish := prof.Start(ctx, "log_buffer_processing") httpResp, err := http.Get(logURL) //nolint:gosec if err != nil { return "", 0, httpResp, fmt.Errorf("failed to download logs: %w", err) - mcp_servers/github_official/pkg/github/actions.go:876mcp-go-ssrf-nonliteral-url (medium/low)
An outbound HTTP request is made to a URL that is not a literal. If any component is caller-supplied the server can be aimed at hosts it can reach and the caller cannot.
finish := prof.Start(ctx, "log_buffer_processing") httpResp, err := http.Get(logURL) //nolint:gosec if err != nil { return "", 0, httpResp, fmt.Errorf("failed to download logs: %w", err) - mcp_servers/github_official/pkg/scopes/fetcher.go:77mcp-go-ssrf-nonliteral-url (medium/low)
An outbound HTTP request is made to a URL that is not a literal. If any component is caller-supplied the server can be aimed at hosts it can reach and the caller cannot.
} req, err := http.NewRequestWithContext(ctx, http.MethodHead, endpoint, nil) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) - mcp_servers/google_maps/index.ts:350mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
url.searchParams.append("key", getApiKey()); const response = await fetch(url.toString()); const data = await response.json() as GeocodeResponse; - mcp_servers/google_maps/index.ts:381mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
url.searchParams.append("key", getApiKey()); const response = await fetch(url.toString()); const data = await response.json() as GeocodeResponse; - mcp_servers/google_maps/index.ts:423mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
} const response = await fetch(url.toString()); const data = await response.json() as PlacesSearchResponse; - mcp_servers/google_maps/index.ts:459mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
url.searchParams.append("key", getApiKey()); const response = await fetch(url.toString()); const data = await response.json() as PlaceDetailsResponse; - mcp_servers/google_maps/index.ts:500mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
url.searchParams.append("key", getApiKey()); const response = await fetch(url.toString()); const data = await response.json() as DistanceMatrixResponse; - mcp_servers/google_maps/index.ts:540mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
url.searchParams.append("key", getApiKey()); const response = await fetch(url.toString()); const data = await response.json() as ElevationResponse; - mcp_servers/google_maps/index.ts:579mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
url.searchParams.append("key", getApiKey()); const response = await fetch(url.toString()); const data = await response.json() as DirectionsResponse; - mcp_servers/google_meet/tools/meet_api.py:41mcp-python-ssrf-nonliteral-url (medium/low)
An outbound HTTP request is made to a URL that is not a literal. If any part of it is caller-supplied, the server can be steered at internal hosts — cloud metadata endpoints, admin ports, other tenants.
"Accept": "application/json", }) with urlopen(req, timeout=15) as resp: data = resp.read().decode("utf-8") return json.loads(data) if data else {} - mcp_servers/hugging_face/packages/app/src/server/gradio-endpoint-connector.ts:199mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
// Fetch schema directly const response = await fetch(schemaUrl, { method: 'GET', headers, - mcp_servers/hugging_face/packages/app/src/server/gradio-endpoint-connector.ts:430mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
try { const resp = await fetch(url); if (resp.ok) { const buf = Buffer.from(await resp.arrayBuffer()); - mcp_servers/hugging_face/packages/app/src/server/utils/gradio-discovery.ts:136mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
} const response = await fetch(url, { headers, signal: controller.signal, - mcp_servers/hugging_face/packages/app/src/server/utils/gradio-discovery.ts:294mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
try { const response = await fetch(schemaUrl, { method: 'GET', headers, - mcp_servers/hugging_face/packages/app/src/server/utils/mcp-api-client.ts:108mcp-js-ssrf-nonliteral-url (medium/low)
An outbound request is made to a URL that is not a literal. If any part is caller-supplied the server can be aimed at internal hosts it can reach and the caller cannot.
const timeoutId = setTimeout(() => controller.abort(), apiTimeout); logger.debug(`Fetching external settings from ${this.config.externalUrl} with timeout ${apiTimeout}ms`); const response = await fetch(this.config.externalUrl, { headers, signal: controller.signal,
Auth Posture
- authentication_model
auth enforcement present at a call site in the source (inbound token verification) and documented in the README; "refused without credentials" (`03` §4) established by reading the code rather than by connecting
- transport_security
declared endpoint(s) are HTTPS: https://strata.klavis.ai/mcp/; scored 80, not 100: `03` §4 reserves 100 for HTTPS *with HSTS*, and an HSTS header can only be seen by connecting, which `04` §9 does not do. This is an unverifiable band, not an observed absence.
- secret_handling
GitHub Token at mcp_servers/github_official/pkg/http/middleware/pat_scope_test.go:49; GitHub Token at mcp_servers/github_official/pkg/http/middleware/pat_scope_test.go:69; GitHub Token at mcp_servers/github_official/pkg/http/middleware/token_test.go:42; GitHub Token at mcp_servers/github_official/pkg/http/middleware/token_test.go:84; GitHub Token at mcp_servers/github_official/pkg/http/middleware/token_test.go:101; GitHub Token at mcp_servers/github_official/pkg/http/middleware/token_test.go:118; …and 1314 more matches
- authorization_granularity
40 tool registrations with conditional access logic present in the same source
Dependency Health
Showing the 49 most severe of 3669 findings on this axis. The score was computed over all of them — findings beyond the fourth of a severity still deduct at a tenth of their weight — so the remainder is omitted from this page, not from the arithmetic.
- examples/agno-klavis/requirements.txtunpinned requirements
1079 vulnerabilities osv-scanner reported at versions it resolved rather than read from a pin (examples/agno-klavis/requirements.txt, examples/claude-klavis/python/requirements.txt, examples/crewai-klavis/python/requirements.txt) are not attributed — nobody pinned those versions, so they say nothing about what this server ships
- mcp_servers/google_cloud_toolathlon/requirements.txtfastmcp 2.10.6 — PYSEC-2026-338
direct, CVSS 10.0, fixed in 3.2.0
https://osv.dev/vulnerability/PYSEC-2026-338 - mcp_servers/local/Poste.io/uv.lockfastmcp 2.11.1 — PYSEC-2026-338
direct, CVSS 10.0, fixed in 3.2.0
https://osv.dev/vulnerability/PYSEC-2026-338 - mcp_servers/local/excel/uv.lockfastmcp 2.11.0 — PYSEC-2026-338
direct, CVSS 10.0, fixed in 3.2.0
https://osv.dev/vulnerability/PYSEC-2026-338 - mcp_servers/google_cloud_toolathlon/requirements.txtcryptography 45.0.5 — PYSEC-2026-36
direct, CVSS 9.8, fixed in 46.0.7
https://osv.dev/vulnerability/PYSEC-2026-36 - mcp_servers/google_sheets_toolathlon/uv.lockcryptography 46.0.3 — PYSEC-2026-36
direct, CVSS 9.8, fixed in 46.0.7
https://osv.dev/vulnerability/PYSEC-2026-36 - mcp_servers/local/Poste.io/uv.lockcryptography 45.0.5 — PYSEC-2026-36
direct, CVSS 9.8, fixed in 46.0.7
https://osv.dev/vulnerability/PYSEC-2026-36 - mcp_servers/local/excel/uv.lockcryptography 45.0.5 — PYSEC-2026-36
direct, CVSS 9.8, fixed in 46.0.7
https://osv.dev/vulnerability/PYSEC-2026-36 - mcp_servers/youtube_transcript_toolathlon/uv.lockcryptography 46.0.5 — PYSEC-2026-36
direct, CVSS 9.8, fixed in 46.0.7
https://osv.dev/vulnerability/PYSEC-2026-36 - open-strata/uv.lockcryptography 46.0.3 — PYSEC-2026-36
direct, CVSS 9.8, fixed in 46.0.7
https://osv.dev/vulnerability/PYSEC-2026-36 - mcp_servers/local/git/uv.lockgitpython 3.1.45 — PYSEC-2026-2161
direct, CVSS 9.8, fixed in 3.1.47
https://osv.dev/vulnerability/PYSEC-2026-2161 - mcp_servers/local/git/uv.lockgitpython 3.1.45 — PYSEC-2026-3786
direct, CVSS 9.8, fixed in 3.1.59
https://osv.dev/vulnerability/PYSEC-2026-3786 - mcp_servers/snowflake_toolathlon/uv.lockpyopenssl 24.3.0 — PYSEC-2026-2269
direct, CVSS 9.8, fixed in 26.0.0
https://osv.dev/vulnerability/PYSEC-2026-2269 - mcp_servers/context7/pnpm-lock.yamlvitest 4.0.14 — GHSA-5xrq-8626-4rwp
direct, CVSS 9.8, fixed in 4.1.0
https://osv.dev/vulnerability/GHSA-5xrq-8626-4rwp - mcp_servers/hugging_face/pnpm-lock.yamlvitest 3.2.4 — GHSA-5xrq-8626-4rwp
direct, CVSS 9.8, fixed in 3.2.6
https://osv.dev/vulnerability/GHSA-5xrq-8626-4rwp - mcp_servers/local/filesystem/package-lock.jsonvitest 4.0.15 — GHSA-5xrq-8626-4rwp
direct, CVSS 9.8, fixed in 4.1.0
https://osv.dev/vulnerability/GHSA-5xrq-8626-4rwp - mcp_servers/notion_atlas/package-lock.jsonvitest 3.1.1 — GHSA-5xrq-8626-4rwp
direct, CVSS 9.8, fixed in 3.2.6
https://osv.dev/vulnerability/GHSA-5xrq-8626-4rwp - mcp_servers/notion_mcpmark/package-lock.jsonvitest 3.1.1 — GHSA-5xrq-8626-4rwp
direct, CVSS 9.8, fixed in 3.2.6
https://osv.dev/vulnerability/GHSA-5xrq-8626-4rwp - mcp_servers/notion_official/package-lock.jsonvitest 3.1.1 — GHSA-5xrq-8626-4rwp
direct, CVSS 9.8, fixed in 3.2.6
https://osv.dev/vulnerability/GHSA-5xrq-8626-4rwp - mcp_servers/notion_toolathlon/package-lock.jsonvitest 3.1.1 — GHSA-5xrq-8626-4rwp
direct, CVSS 9.8, fixed in 3.2.6
https://osv.dev/vulnerability/GHSA-5xrq-8626-4rwp - mcp_servers/supabase/package-lock.jsonvitest 3.2.4 — GHSA-5xrq-8626-4rwp
direct, CVSS 9.8, fixed in 3.2.6
https://osv.dev/vulnerability/GHSA-5xrq-8626-4rwp - mcp_servers/airtable_atlas/package-lock.jsonform-data 4.0.1 — GHSA-fjxv-7rqg-78g4
direct, CVSS 9.4, fixed in 4.0.4
https://osv.dev/vulnerability/GHSA-fjxv-7rqg-78g4 - mcp_servers/exa_atlas/package-lock.jsonform-data 4.0.1 — GHSA-fjxv-7rqg-78g4
direct, CVSS 9.4, fixed in 4.0.4
https://osv.dev/vulnerability/GHSA-fjxv-7rqg-78g4 - mcp_servers/notion_atlas/package-lock.jsonform-data 4.0.2 — GHSA-fjxv-7rqg-78g4
direct, CVSS 9.4, fixed in 4.0.4
https://osv.dev/vulnerability/GHSA-fjxv-7rqg-78g4 - mcp_servers/notion_toolathlon/package-lock.jsonform-data 4.0.2 — GHSA-fjxv-7rqg-78g4
direct, CVSS 9.4, fixed in 4.0.4
https://osv.dev/vulnerability/GHSA-fjxv-7rqg-78g4 - mcp-clients/uv.lockanyio 4.9.0 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp_servers/arxiv_latex/uv.lockanyio 4.9.0 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp_servers/duckduckgo_atlas/uv.lockanyio 4.8.0 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp_servers/google_cloud_toolathlon/requirements.txtanyio 4.9.0 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp_servers/google_meet/uv.lockanyio 4.10.0 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp_servers/google_sheets_toolathlon/uv.lockanyio 4.12.0 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp_servers/hubspot/requirements.txtanyio 4.9.0 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp_servers/local/Poste.io/uv.lockanyio 4.10.0 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp_servers/local/excel/uv.lockanyio 4.8.0 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp_servers/local/git/uv.lockanyio 4.6.2.post1 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp_servers/local/terminal/uv.lockanyio 4.9.0 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp_servers/local/word/uv.lockanyio 4.9.0 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp_servers/onedrive/uv.lockanyio 4.11.0 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp_servers/outlook/uv.lockanyio 4.11.0 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp_servers/scholarly_toolathlon/uv.lockanyio 4.7.0 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp_servers/snowflake_toolathlon/uv.lockanyio 4.12.1 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp_servers/youtube_transcript_toolathlon/uv.lockanyio 4.12.1 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - open-strata/uv.lockanyio 4.10.0 — PYSEC-2026-4025
direct, CVSS 9.3, fixed in 4.14.2
https://osv.dev/vulnerability/PYSEC-2026-4025 - mcp-clients/uv.lockmammoth 1.9.0 — PYSEC-2026-1603
direct, CVSS 9.3, fixed in 1.11.0
https://osv.dev/vulnerability/PYSEC-2026-1603 - examples/mastra-klavis/package-lock.jsonshell-quote 1.8.3 — GHSA-w7jw-789q-3m8p
direct, CVSS 9.2, fixed in 1.8.4
https://osv.dev/vulnerability/GHSA-w7jw-789q-3m8p - mcp_servers/hugging_face/pnpm-lock.yamlshell-quote 1.8.3 — GHSA-w7jw-789q-3m8p
direct, CVSS 9.2, fixed in 1.8.4
https://osv.dev/vulnerability/GHSA-w7jw-789q-3m8p - mcp_servers/snowflake_toolathlon/uv.locksnowflake-connector-python 3.13.2 — PYSEC-2026-3920
direct, CVSS 9.2, fixed in 3.18.1
https://osv.dev/vulnerability/PYSEC-2026-3920 - mcp-clients/uv.lockaiohttp 3.11.16 — PYSEC-2026-2102
direct, CVSS 9.1, fixed in 3.13.4
https://osv.dev/vulnerability/PYSEC-2026-2102 - mcp_servers/google_cloud_toolathlon/requirements.txtauthlib 1.6.1 — PYSEC-2026-287
direct, CVSS 9.1, fixed in 1.6.9
https://osv.dev/vulnerability/PYSEC-2026-287 - mcp_servers/local/Poste.io/uv.lockauthlib 1.6.1 — PYSEC-2026-287
direct, CVSS 9.1, fixed in 1.6.9
https://osv.dev/vulnerability/PYSEC-2026-287
Maintenance
- recency
last commit 137 day(s) before 2026-10-16
- issue_responsiveness
median over 13 issue(s) in the last 6 months: 63.2 day(s) to first maintainer comment
- release_cadence
median release gap 0 days (by releases), last release 260 day(s) ago
- bus_factor
3 authors with >= 5 commits in 12 months
- repository_signals
`03` §5 scores this by quartile WITHIN the server's category, which needs a distribution across every scanned server and so cannot be computed while scanning one. It is a post-pass over the crawl and that pass does not exist yet.
Transparency
- license
LICENSE present with no SPDX-License-Identifier tag; identified as 'Apache-2.0' from its text
- readme_quality
README.md: installation instructions (+25), exposed tools or resources enumerated (+30), states what the server does in the first 200 words (+20)
- declared_scopes
specific scope or access documentation is present, but `03` §7's 100 and 60 bands both compare it against scopes INFERRED from static analysis, which is not built yet. Scoring 100 on an empty inference would be a vacuous truth — 'all ∅ inferred scopes are documented'.
- changelog
mcp_servers/context7/packages/mcp/CHANGELOG.md present
- security_contact
mcp_servers/context7/SECURITY.md present
Contest a finding
Every number here comes from a rule reading published source, and rules get things wrong. If something on this page is incorrect — or correct but mitigated by a check the rule cannot see — open an issue and we answer it in writing. A finding we got wrong is removed and the rule is fixed; one that stands is answered on the record.
Anyone can file: the maintainer, a researcher who disagrees with the classification, or a user who tested the server and could not reproduce it. Name this server and the rule or advisory ID shown beside the finding above. We aim to reply within five business days and to resolve within ten.