# Security Audit Report — mcp-server-screeny

- **Report ID:** `ac39317a-7a9a-480d-904d-4c5a41a2359f`
- **Generated:** 2026-07-21T23:06:28.697362+00:00
- **Signature:** unsigned (cosign keyless signing runs in CI; Req 22.4)

## 1. Executive Summary

**Badge:** Unsafe (composite)  
**Security score:** 47.55

| Scanner | Badge |
| --- | --- |
| agent-audit-kit | Caution |
| agentshield | unavailable |
| bearer | Verified |
| cisco-skill-scanner | Verified |
| nerlo-behavioral | Verified |
| nerlo-install-instruction | Verified |
| osv-scanner | Unsafe |
| trivy | Unsafe |

| Severity | Findings |
| --- | --- |
| critical | 0 |
| high | 22 |
| medium | 15 |
| low | 10 |

mcp-server-screeny is NOT recommended for integration: the scan surfaced 0 critical and 22 high-severity findings. Treat the Per-Scanner Detail section as a remediation worklist and re-scan before reconsidering.

## 2. Source Provenance

- **Repository:** https://github.com/rohanrav/screeny
- **Commit scanned:** `unknown`
- **License:** MIT
- **Maintainer:** Rohan Ravindran
- **Version:** 0.3.6

## 3. Per-Scanner Detail

### agentshield (v1.4.0) — unavailable / n/a

No findings.

### cisco-skill-scanner (v2.0.11) — Verified / 97.5

- **[low] Vague skill description** — Skill description is too short (16 chars). Provide detailed explanation. (/repo/SKILL.md:None)
- **[informational] Skill does not specify a license** — Skill manifest does not include a 'license' field. Specifying a license helps users understand usage terms. (/repo/SKILL.md:None)

### agent-audit-kit (v0.3.26) — Caution / 78.0

- **[low] MCP server repo missing SECURITY.md or security_contact** — A repository whose name or pyproject keywords declare it as an MCP server ships without a top-level SECURITY.md AND without a 'security_contact' entry in marketplace.json / pyproject.toml / package.json. Anthropic's April 2026 SECURITY.md guidance makes this the baseline expectation so researchers have a channel. (SECURITY.md:None)
- **[medium] Repo depends on a third-party agent-platform SDK** — The project depends on an agent-platform SDK (context-ai, langsmith, helicone, langfuse, humanloop, MCP SDK). Informational finding so reviewers audit the vendor's OAuth-scope footprint before merging. Raised to MEDIUM because the April 19 2026 Vercel × Context.ai incident showed a single vendor compromise can turn into a production breach via transitive OAuth grants. (pyproject.toml:2)
- **[high] Vulnerable MCP SDK version pinned (DNS-rebinding fix missing)** — A project dependency manifest (requirements.txt, pyproject.toml, package.json, pom.xml, build.gradle) pins an MCP SDK at a version below the DNS-rebinding fix. Patched versions: Python 'mcp' >= 1.23.0, TS '@modelcontextprotocol/sdk' >= 1.21.1, Java 'io.modelcontextprotocol.sdk:mcp-core' >= 0.11.0, '@apollo/mcp-server' >= 1.7.0. Even if the project never serves over StreamableHTTP itself, transitive servers built on the SDK inherit the bug. (pyproject.toml:23)

### bearer (v2.0.2) — Verified / 100.0

No findings.

### nerlo-behavioral (v0.1.0) — Verified / 100.0

No findings.

### nerlo-install-instruction (v0.1.0) — Verified / 100.0

No findings.

### trivy (v0.71.0) — Unsafe / 0.0

- **[medium] python-idna: idna: Denial of Service via specially crafted long inputs** — Internationalized Domain Names in Applications (IDNA) for Python provides support for Internationalized Domain Names in Applications (IDNA) and Unicode IDNA Compatibility Processing. In versions prior to 3.15, payloads such as '"\u0660" * N' or '"\u30fb" * N + "\u6f22"' utilize the 'valid_contexto' function prior to length rejection, and for high values of 'N' will take a long time to process. This is the same issue as CVE-2024-3651, however the original remediation in 2024 was not a complete fi (uv.lock:None)
- **[high] mcp: MCP Server Crash via ClosedResourceError** — The MCP Python SDK, called 'mcp' on PyPI, is a Python implementation of the Model Context Protocol (MCP). Prior to version 1.10.0, if a client deliberately triggers an exception after establishing a streamable HTTP session, this can lead to an uncaught ClosedResourceError on the server side, causing the server to crash and requiring a restart to restore service. Impact may vary depending on the deployment conditions, and presence of infrastructure-level resilience measures. Version 1.10.0 contai (uv.lock:None)
- **[high] mcp: DNS Rebinding Protection Disabled by Default in Model Context Protocol Python SDK** — The MCP Python SDK, called 'mcp' on PyPI, is a Python implementation of the Model Context Protocol (MCP). Prior to version 1.23.0, tThe Model Context Protocol (MCP) Python SDK does not enable DNS rebinding protection by default for HTTP-based servers. When an HTTP-based MCP server is run on localhost without authentication using FastMCP with streamable HTTP or SSE transport, and has not configured TransportSecuritySettings, a malicious website could exploit DNS rebinding to bypass same-origin po (uv.lock:None)
- **[high] MCP Python SDK: HTTP transports serve session requests without verifying the authenticated principal** — The MCP Python SDK, called mcp on PyPI, is a Python implementation of the Model Context Protocol (MCP). Prior to 1.27.2, the SSE and stateful Streamable HTTP transports mcp.server.sse.SseServerTransport and mcp.server.streamable_http_manager.StreamableHTTPSessionManager route requests to existing sessions using only the session_id query parameter or Mcp-Session-Id header without verifying the authenticated principal that created the session, allowing a different bearer-token-authenticated client (uv.lock:None)
- **[high] MCP Python SDK: WebSocket server transport does not support Host/Origin validation** — The MCP Python SDK, called mcp on PyPI, is a Python implementation of the Model Context Protocol (MCP). Prior to 1.28.1, the deprecated mcp.server.websocket.websocket_server transport accepted WebSocket handshakes without applying Host or Origin header validation, leaving no SDK-level way to restrict which origins could connect to applications that exposed that transport. This issue is fixed in version 1.28.1. (uv.lock:None)
- **[medium] python-dotenv: python-dotenv: Arbitrary file overwrite via symbolic link following** — python-dotenv reads key-value pairs from a .env file and can set them as environment variables. Prior to version 1.2.2, 'set_key()' and 'unset_key()' in python-dotenv follow symbolic links when rewriting '.env' files, allowing a local attacker to overwrite arbitrary files via a crafted symlink when a cross-device rename fallback is triggered. Users should upgrade to v.1.2.2 or, as a workaround, apply the patch manually. (uv.lock:None)
- **[high] python-multipart: Python-Multipart: Arbitrary file write via path traversal vulnerability** — Python-Multipart is a streaming multipart parser for Python. Prior to version 0.0.22, a Path Traversal vulnerability exists when using non-default configuration options 'UPLOAD_DIR' and 'UPLOAD_KEEP_FILENAME=True'. An attacker can write uploaded files to arbitrary locations on the filesystem by crafting a malicious filename. Users should upgrade to version 0.0.22 to receive a patch or, as a workaround, avoid using 'UPLOAD_KEEP_FILENAME=True' in project configurations. (uv.lock:None)
- **[high] python-multipart: python-multipart: Denial of Service via excessive multipart part headers** — Python-Multipart is a streaming multipart parser for Python. Prior to 0.0.27, python-multipart has a denial of service vulnerability in multipart part header parsing. When parsing multipart/form-data, MultipartParser previously had no limit on the number of part headers or the size of an individual part header. An attacker could send a request with either many repeated headers without terminating the header block or a single very large header value, causing excessive CPU work before request reje (uv.lock:None)
- **[high] python-multipart: Python-Multipart: Denial of Service via crafted form-urlencoded bodies** — Python-Multipart is a streaming multipart parser for Python. Prior to 0.0.30, when parsing application/x-www-form-urlencoded bodies, QuerystringParser located the field separator with a two step lookup: it first scanned the entire remaining buffer for &, and only when no & existed anywhere ahead did it fall back to scanning for ;. For a body that uses ; as the separator and contains no &, every field iteration performed a full failed & scan over the entire remaining buffer before locating the ne (uv.lock:None)
- **[medium] python-multipart: Python-Multipart: Denial of Service via crafted multipart/form-data requests** — Python-Multipart is a streaming multipart parser for Python. Versions prior to 0.0.26 have a denial of service vulnerability when parsing crafted 'multipart/form-data' requests with large preamble or epilogue sections. Upgrade to version 0.0.26 or later, which skips ahead to the next boundary candidate when processing leading CR/LF data and immediately discards epilogue data after the closing boundary. (uv.lock:None)
- **[low] multipart: Python-Multipart: Information disclosure via header parsing discrepancy** — Python-Multipart is a streaming multipart parser for Python. Prior to 0.0.30, parse_options_header parsed Content-Disposition (and Content-Type) headers with email.message.Message, which transparently applies RFC 2231/5987 decoding. The extended parameter syntax (filename*=charset'lang'value, name*=..., and the filename*0/filename*1 continuation form) is decoded and surfaced under the bare filename/name key, and overrides the plain parameter when both are present. RFC 7578 §4.2 explicitly forbid (uv.lock:None)
- **[low] python-multipart: Python-Multipart: Information disclosure due to parser differential in form data handling** — Python-Multipart is a streaming multipart parser for Python. Prior to 0.0.30, QuerystringParser treated ; as a field separator in application/x-www-form-urlencoded bodies, in addition to &. The WHATWG URL standard, modern browsers, and Python's urllib.parse (since the CVE-2021-23336 fix) treat only & as a separator. This creates a parser differential: the same bytes are tokenized into different fields than a WHATWG compliant intermediary would produce, allowing an attacker to smuggle extra form  (uv.lock:None)
- **[low] python-multipart: Python-Multipart: Negative Content-Length in parse_form buffers the entire body in memory** — Python-Multipart is a streaming multipart parser for Python. Prior to 0.0.31, parse_form() did not validate the Content-Length header before using it to bound its chunked read of the request body. A negative Content-Length turned the bounded read into a read-until-EOF, so the entire body was loaded into memory in a single read instead of in fixed-size chunks. This vulnerability is fixed in 0.0.31. (uv.lock:None)
- **[high] starlette: Starlette DoS via Range header merging** — Starlette is a lightweight ASGI framework/toolkit. Starting in version 0.39.0 and prior to version 0.49.1 , an unauthenticated attacker can send a crafted HTTP Range header that triggers quadratic-time processing in Starlette's FileResponse Range parsing/merging logic. This enables CPU exhaustion per request, causing denial‑of‑service for endpoints serving files (e.g., StaticFiles or any use of FileResponse). This vulnerability is fixed in 0.49.1. (uv.lock:None)
- **[high] starlette: Starlette: SSRF and NTLM credential theft via UNC paths in StaticFiles on Windows** — Starlette is a lightweight ASGI framework/toolkit. In versions 1.0.1 and earlier, StaticFiles on Windows is vulnerable to SSRF. An UNC path such as \\attacker.com\share can cause os.path.realpath to initiate an outbound SMB connection before the path is rejected, exposing the service account’s NTLMv2 credentials for offline cracking or relay even though the HTTP response is only a 404. The issue affects default follow_symlink=False deployments, including frameworks built on Starlette such as Fas (uv.lock:None)
- **[high] starlette: Starlette: request.form() limits silently ignored for application/x-www-form-urlencoded enable DoS** — Starlette is a lightweight ASGI framework/toolkit. From 0.4.1 until 1.3.1, request.form() accepts max_fields and max_part_size to bound resource consumption while parsing form data. These limits are enforced for multipart/form-data, but silently ignored for application/x-www-form-urlencoded. An unauthenticated attacker can therefore send a urlencoded body with an arbitrarily large number of fields or an arbitrarily large field, even when the application configured limits it believed would apply. (uv.lock:None)
- **[medium] starlette: Starlette denial-of-service** — Starlette is a lightweight ASGI (Asynchronous Server Gateway Interface) framework/toolkit, designed for building async web services in Python. In versions 0.47.1 and below, when parsing a multi-part form with large files (greater than the default max spool size) starlette will block the main thread to roll the file over to disk. This blocks the event thread which means the application can't accept new connections. The UploadFile code has a minor bug where instead of just checking for self._in_me (uv.lock:None)
- **[medium] starlette: Starlette: Security restriction bypass via malformed HTTP Host header** — Starlette is a lightweight ASGI framework/toolkit. Prior to version 1.0.1, the HTTP 'Host' request header was not validated before being used to reconstruct 'request.url'. Because the routing algorithm relies on the raw HTTP path while 'request.url' is rebuilt from the 'Host' header, a malformed header could make 'request.url.path' differ from the path that was actually requested. Middleware and endpoints that apply security restrictions based on 'request.url' (rather than the raw 'scope' path)  (uv.lock:None)
- **[medium] starlette: Starlette: Information disclosure and unintended method execution via non-standard HTTP methods** — Starlette is a lightweight ASGI framework/toolkit. In versions 1.0.1 and below, when dispatching a request, HTTPEndpoint selects the handler by lowercasing the HTTP method and looking it up as an attribute with getattr, without restricting the lookup to a known set of HTTP verbs. When an HTTPEndpoint subclass is registered through Route(...) without an explicit methods= argument, the route does not constrain the method and every method reaches the endpoint. If a non-standard HTTP method whose lo (uv.lock:None)
- **[low] starlette: Starlette: Information disclosure due to improper HTTP request path validation** — Starlette is a lightweight ASGI framework/toolkit. Prior to 1.3.0, the HTTP request path is not validated before being used to reconstruct request.url. Because request.url is rebuilt by concatenating {scheme}://{host}{path} and re-parsing the result, a path that does not begin with / (for example @google.com) moves the authority boundary during re-parsing, so request.url.hostname and request.url.netloc become attacker-controlled. Code that reads request.url.hostname (rather than the Host header  (uv.lock:None)

### osv-scanner (v2.3.8) — Unsafe / 0.0

- **[high] PYSEC-2026-2132 — PyPI click@8.2.1** — aliases: CVE-2026-7246, GHSA-47fr-3ffg-hgmw, PYSEC-2026-2132 \| CVSS: 7.2 (/repo/uv.lock:None)
- **[medium] PYSEC-2026-215 — PyPI idna@3.10** — aliases: CVE-2026-45409, GHSA-65pc-fj4g-8rjx, PYSEC-2026-215 \| CVSS: 6.9 (/repo/uv.lock:None)
- **[high] PYSEC-2026-1617 — PyPI mcp@1.9.4** — aliases: CVE-2025-66416, GHSA-9h52-p55h-vw2f, PYSEC-2026-1617 \| CVSS: 7.6 (/repo/uv.lock:None)
- **[high] PYSEC-2026-1618 — PyPI mcp@1.9.4** — aliases: CVE-2025-53365, GHSA-j975-95f5-7wqh, PYSEC-2026-1618 \| CVSS: 8.7 (/repo/uv.lock:None)
- **[high] GHSA-jpw9-pfvf-9f58 — PyPI mcp@1.9.4** — aliases: CVE-2026-52869, GHSA-jpw9-pfvf-9f58 \| CVSS: 7.1 (/repo/uv.lock:None)
- **[high] GHSA-vj7q-gjh5-988w — PyPI mcp@1.9.4** — aliases: CVE-2026-59950, GHSA-vj7q-gjh5-988w \| CVSS: 7.6 (/repo/uv.lock:None)
- **[low] PYSEC-2026-2987 — PyPI pygments@2.19.2** — aliases: CVE-2026-4539, GHSA-5239-wwwm-4pmq, PYSEC-2026-2987 \| CVSS: 3.3 (/repo/uv.lock:None)
- **[medium] PYSEC-2026-1845 — PyPI pytest@8.4.1** — aliases: CVE-2025-71176, GHSA-6w46-j5rx-g56g, PYSEC-2026-1845 \| CVSS: 6.8 (/repo/uv.lock:None)
- **[medium] PYSEC-2026-2270 — PyPI python-dotenv@1.1.1** — aliases: CVE-2026-28684, GHSA-mf9w-mj56-hr94, PYSEC-2026-2270 \| CVSS: 6.6 (/repo/uv.lock:None)
- **[high] PYSEC-2026-1852 — PyPI python-multipart@0.0.20** — aliases: CVE-2026-24486, GHSA-wp53-j4wj-2cfg, PYSEC-2026-1852 \| CVSS: 8.6 (/repo/uv.lock:None)
- **[high] PYSEC-2026-3036 — PyPI python-multipart@0.0.20** — aliases: CVE-2026-53539, GHSA-5rvq-cxj2-64vf, PYSEC-2026-3036 \| CVSS: 7.5 (/repo/uv.lock:None)
- **[low] PYSEC-2026-3037 — PyPI python-multipart@0.0.20** — aliases: CVE-2026-53538, GHSA-6jv3-5f52-599m, PYSEC-2026-3037 \| CVSS: 3.7 (/repo/uv.lock:None)
- **[medium] PYSEC-2026-3038 — PyPI python-multipart@0.0.20** — aliases: CVE-2026-40347, GHSA-mj87-hwqh-73pj, PYSEC-2026-3038 \| CVSS: 5.3 (/repo/uv.lock:None)
- **[high] PYSEC-2026-3039 — PyPI python-multipart@0.0.20** — aliases: CVE-2026-42561, GHSA-pp6c-gr5w-3c5g, PYSEC-2026-3039 \| CVSS: 7.5 (/repo/uv.lock:None)
- **[low] PYSEC-2026-3040 — PyPI python-multipart@0.0.20** — aliases: CVE-2026-53540, GHSA-v9pg-7xvm-68hf, PYSEC-2026-3040 \| CVSS: 3.7 (/repo/uv.lock:None)
- **[low] PYSEC-2026-3041 — PyPI python-multipart@0.0.20** — aliases: CVE-2026-53537, GHSA-vffw-93wf-4j4q, PYSEC-2026-3041 \| CVSS: 3.7 (/repo/uv.lock:None)
- **[medium] PYSEC-2026-161 — PyPI starlette@0.47.1** — aliases: CVE-2026-48710, GHSA-86qp-5c8j-p5mr, PYSEC-2026-161, X41-2026-002 \| CVSS: 6.5 (/repo/uv.lock:None)
- **[medium] PYSEC-2026-1941 — PyPI starlette@0.47.1** — aliases: CVE-2025-54121, GHSA-2c2j-9gv5-cj73, PYSEC-2026-1941 \| CVSS: 5.3 (/repo/uv.lock:None)
- **[high] PYSEC-2026-1942 — PyPI starlette@0.47.1** — aliases: CVE-2025-62727, GHSA-7f5h-v6xp-fcq8, PYSEC-2026-1942 \| CVSS: 7.5 (/repo/uv.lock:None)
- **[medium] PYSEC-2026-2280 — PyPI starlette@0.47.1** — aliases: CVE-2026-48817, GHSA-x746-7m8f-x49c, PYSEC-2026-2280 \| CVSS: 5.3 (/repo/uv.lock:None)
- **[high] PYSEC-2026-2281 — PyPI starlette@0.47.1** — aliases: CVE-2026-48818, GHSA-wqp7-x3pw-xc5r, PYSEC-2026-2281 \| CVSS: 7.5 (/repo/uv.lock:None)
- **[medium] PYSEC-2026-248 — PyPI starlette@0.47.1** — aliases: CVE-2026-54282, GHSA-jp82-jpqv-5vv3, PYSEC-2026-248 \| CVSS: 5.3 (/repo/uv.lock:None)
- **[high] PYSEC-2026-249 — PyPI starlette@0.47.1** — aliases: CVE-2026-54283, GHSA-82w8-qh3p-5jfq, PYSEC-2026-249 \| CVSS: 7.5 (/repo/uv.lock:None)

## 4. Threat Model

Threat model synthesis has not yet run for this scan. This section is generated by the registry's LLM pipeline (Req 22.3) and will appear in the next regeneration of this report.

## 5. Audit Chain

- **Scan job:** `43f70be3-15c1-4df8-b12e-fa98e4f114d5`
- **Completed:** 2026-07-21T02:53:06.538959+00:00
- **Scanner base image:** `us-central1-docker.pkg.dev/nerlo-vsk-prod/nerlo/scanner-base@sha256:5f2eb3b83083e1887537d1f7485cc3ceecdbc45a6a7b1ae17fb77f9e0e67a10b`
- **AI decision log entries:** 1
  - `ddde04a3-4b2c-43eb-8faf-0c7b1db4c110`

## 6. Appendix — Raw Scanner Output

```json
[
  {
    "scanner_name": "agentshield",
    "scanner_version": "1.4.0",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 1.5183603290061,
    "status": "not_applicable",
    "metadata": {
      "source": "npm",
      "source_url": "https://www.npmjs.com/package/ecc-agentshield",
      "install_command": "npm install -g ecc-agentshield@1.4.0",
      "scans_performed": []
    },
    "display_score": null,
    "display_badge": "unavailable"
  },
  {
    "scanner_name": "cisco-skill-scanner",
    "scanner_version": "2.0.11",
    "score": 97.5,
    "scanner_badge": "Verified",
    "findings": [
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "low",
        "category": "social_engineering",
        "file_path": "/repo/SKILL.md",
        "line_number": null,
        "rule_identifier": "SOCIAL_ENG_VAGUE_DESCRIPTION",
        "title": "Vague skill description",
        "description": "Skill description is too short (16 chars). Provide detailed explanation.",
        "remediation": "Provide a clear, detailed description of what the skill does and when to use it"
      },
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "informational",
        "category": "policy_violation",
        "file_path": "/repo/SKILL.md",
        "line_number": null,
        "rule_identifier": "MANIFEST_MISSING_LICENSE",
        "title": "Skill does not specify a license",
        "description": "Skill manifest does not include a 'license' field. Specifying a license helps users understand usage terms.",
        "remediation": "Add 'license' field to SKILL.md frontmatter (e.g., MIT, Apache-2.0)"
      }
    ],
    "execution_duration_seconds": 38.446874228000524,
    "status": "complete",
    "metadata": {
      "source": "pypi",
      "source_url": "https://pypi.org/project/cisco-ai-skill-scanner/2.0.11/",
      "report_type": "cisco-skill-sast",
      "analyzers_used": [
        "bytecode",
        "pipeline",
        "static_analyzer"
      ],
      "skills_scanned": [
        "repo"
      ],
      "install_command": "pip install --require-hashes -r docker/scanner-base/cisco-skill-scanner/requirements.txt",
      "severity_counts": {
        "low": 1,
        "high": 0,
        "medium": 0,
        "critical": 0,
        "informational": 1
      }
    },
    "display_score": 97.5,
    "display_badge": "Verified"
  },
  {
    "scanner_name": "agent-audit-kit",
    "scanner_version": "0.3.26",
    "score": 78.0,
    "scanner_badge": "Caution",
    "findings": [
      {
        "tool_name": "agent-audit-kit",
        "severity": "low",
        "category": "supply-chain",
        "file_path": "SECURITY.md",
        "line_number": null,
        "rule_identifier": "AAK-SEC-MD-001",
        "title": "MCP server repo missing SECURITY.md or security_contact",
        "description": "A repository whose name or pyproject keywords declare it as an MCP server ships without a top-level SECURITY.md AND without a `security_contact` entry in marketplace.json / pyproject.toml / package.json. Anthropic's April 2026 SECURITY.md guidance makes this the baseline expectation so researchers have a channel.",
        "remediation": "Add SECURITY.md at the repo root with a disclosure email and response SLA; OR add `security_contact` to the project manifest."
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "medium",
        "category": "supply-chain",
        "file_path": "pyproject.toml",
        "line_number": 2,
        "rule_identifier": "AAK-OAUTH-3P-001",
        "title": "Repo depends on a third-party agent-platform SDK",
        "description": "The project depends on an agent-platform SDK (context-ai, langsmith, helicone, langfuse, humanloop, MCP SDK). Informational finding so reviewers audit the vendor's OAuth-scope footprint before merging. Raised to MEDIUM because the April 19 2026 Vercel \u00d7 Context.ai incident showed a single vendor compromise can turn into a production breach via transitive OAuth grants.",
        "remediation": "Pin the SDK to an exact version, audit the OAuth scopes it requests, and keep any deployment-level grants (Vercel, GCP, Workspace) in a secrets vault \u2014 never in a committed env file. See Vercel's bulletin for sensitive-env-var guidance: https://vercel.com/kb/bulletin/vercel-april-2026-security-incident"
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "high",
        "category": "supply-chain",
        "file_path": "pyproject.toml",
        "line_number": 23,
        "rule_identifier": "AAK-DNS-REBIND-002",
        "title": "Vulnerable MCP SDK version pinned (DNS-rebinding fix missing)",
        "description": "A project dependency manifest (requirements.txt, pyproject.toml, package.json, pom.xml, build.gradle) pins an MCP SDK at a version below the DNS-rebinding fix. Patched versions: Python `mcp` >= 1.23.0, TS `@modelcontextprotocol/sdk` >= 1.21.1, Java `io.modelcontextprotocol.sdk:mcp-core` >= 0.11.0, `@apollo/mcp-server` >= 1.7.0. Even if the project never serves over StreamableHTTP itself, transitive servers built on the SDK inherit the bug.",
        "remediation": "Bump the SDK to the patched version listed in the rule title. If a bump is not yet possible, ensure every transport surface has its own Host-header allow-list (see AAK-DNS-REBIND-001 remediation)."
      }
    ],
    "execution_duration_seconds": 13.795155180996517,
    "status": "complete",
    "metadata": {
      "source": "pypi",
      "source_url": "https://pypi.org/project/agent-audit-kit/0.3.26/",
      "report_type": "agent-audit-kit-sast",
      "files_scanned": 8,
      "install_command": "pip install --require-hashes -r docker/scanner-base/agent-audit-kit/requirements.txt",
      "rules_evaluated": 211,
      "severity_counts": {
        "low": 1,
        "high": 1,
        "medium": 1,
        "critical": 0,
        "informational": 0
      }
    },
    "display_score": 78.0,
    "display_badge": "Caution"
  },
  {
    "scanner_name": "bearer",
    "scanner_version": "2.0.2",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 15.895851977009443,
    "status": "complete",
    "metadata": {
      "source": "github-releases",
      "source_url": "https://github.com/Bearer/bearer",
      "report_type": "security",
      "rules_loaded": 1,
      "install_command": "curl -sfL https://raw.githubusercontent.com/Bearer/bearer/main/contrib/install.sh | sh -s -- -b /usr/local/bin \"v2.0.2\""
    },
    "display_score": 100.0,
    "display_badge": "Verified"
  },
  {
    "scanner_name": "nerlo-behavioral",
    "scanner_version": "0.1.0",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 48.08724779600743,
    "status": "complete",
    "metadata": {
      "source": "nerlo-original",
      "source_url": "https://github.com/nerlo-ai/nerlo",
      "report_type": "nerlo-behavioral",
      "ruleset_path": "/opt/nerlo-rules/exfiltration.yaml",
      "files_scanned": 4,
      "install_command": "pip install 'semgrep==1.97.0'"
    },
    "display_score": 100.0,
    "display_badge": "Verified"
  },
  {
    "scanner_name": "nerlo-install-instruction",
    "scanner_version": "0.1.0",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 47.088477077995776,
    "status": "complete",
    "metadata": {
      "source": "nerlo-original",
      "source_url": "https://github.com/nerlo-ai/nerlo",
      "report_type": "nerlo-install-instruction",
      "ruleset_path": "/opt/nerlo-rules/install_instructions.yaml",
      "files_scanned": 1,
      "install_command": "pip install 'semgrep==1.97.0'"
    },
    "display_score": 100.0,
    "display_badge": "Verified"
  },
  {
    "scanner_name": "trivy",
    "scanner_version": "0.71.0",
    "score": 0.0,
    "scanner_badge": "Unsafe",
    "findings": [
      {
        "tool_name": "trivy",
        "severity": "medium",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2026-45409",
        "title": "python-idna: idna: Denial of Service via specially crafted long inputs",
        "description": "Internationalized Domain Names in Applications (IDNA) for Python provides support for Internationalized Domain Names in Applications (IDNA) and Unicode IDNA Compatibility Processing. In versions prior to 3.15, payloads such as `\"\\u0660\" * N` or `\"\\u30fb\" * N + \"\\u6f22\"` utilize the `valid_contexto` function prior to length rejection, and for high values of `N` will take a long time to process. This is the same issue as CVE-2024-3651, however the original remediation in 2024 was not a complete fi",
        "remediation": "Upgrade idna from 3.10 to 3.15 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "high",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2025-53365",
        "title": "mcp: MCP Server Crash via ClosedResourceError",
        "description": "The MCP Python SDK, called `mcp` on PyPI, is a Python implementation of the Model Context Protocol (MCP). Prior to version 1.10.0, if a client deliberately triggers an exception after establishing a streamable HTTP session, this can lead to an uncaught ClosedResourceError on the server side, causing the server to crash and requiring a restart to restore service. Impact may vary depending on the deployment conditions, and presence of infrastructure-level resilience measures. Version 1.10.0 contai",
        "remediation": "Upgrade mcp from 1.9.4 to 1.10.0 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "high",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2025-66416",
        "title": "mcp: DNS Rebinding Protection Disabled by Default in Model Context Protocol Python SDK",
        "description": "The MCP Python SDK, called `mcp` on PyPI, is a Python implementation of the Model Context Protocol (MCP). Prior to version 1.23.0, tThe Model Context Protocol (MCP) Python SDK does not enable DNS rebinding protection by default for HTTP-based servers. When an HTTP-based MCP server is run on localhost without authentication using FastMCP with streamable HTTP or SSE transport, and has not configured TransportSecuritySettings, a malicious website could exploit DNS rebinding to bypass same-origin po",
        "remediation": "Upgrade mcp from 1.9.4 to 1.23.0 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "high",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2026-52869",
        "title": "MCP Python SDK: HTTP transports serve session requests without verifying the authenticated principal",
        "description": "The MCP Python SDK, called mcp on PyPI, is a Python implementation of the Model Context Protocol (MCP). Prior to 1.27.2, the SSE and stateful Streamable HTTP transports mcp.server.sse.SseServerTransport and mcp.server.streamable_http_manager.StreamableHTTPSessionManager route requests to existing sessions using only the session_id query parameter or Mcp-Session-Id header without verifying the authenticated principal that created the session, allowing a different bearer-token-authenticated client",
        "remediation": "Upgrade mcp from 1.9.4 to 1.27.2 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "high",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2026-59950",
        "title": "MCP Python SDK: WebSocket server transport does not support Host/Origin validation",
        "description": "The MCP Python SDK, called mcp on PyPI, is a Python implementation of the Model Context Protocol (MCP). Prior to 1.28.1, the deprecated mcp.server.websocket.websocket_server transport accepted WebSocket handshakes without applying Host or Origin header validation, leaving no SDK-level way to restrict which origins could connect to applications that exposed that transport. This issue is fixed in version 1.28.1.",
        "remediation": "Upgrade mcp from 1.9.4 to 1.28.1 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "medium",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2026-28684",
        "title": "python-dotenv: python-dotenv: Arbitrary file overwrite via symbolic link following",
        "description": "python-dotenv reads key-value pairs from a .env file and can set them as environment variables. Prior to version 1.2.2, `set_key()` and `unset_key()` in python-dotenv follow symbolic links when rewriting `.env` files, allowing a local attacker to overwrite arbitrary files via a crafted symlink when a cross-device rename fallback is triggered. Users should upgrade to v.1.2.2 or, as a workaround, apply the patch manually.",
        "remediation": "Upgrade python-dotenv from 1.1.1 to 1.2.2 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "high",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2026-24486",
        "title": "python-multipart: Python-Multipart: Arbitrary file write via path traversal vulnerability",
        "description": "Python-Multipart is a streaming multipart parser for Python. Prior to version 0.0.22, a Path Traversal vulnerability exists when using non-default configuration options `UPLOAD_DIR` and `UPLOAD_KEEP_FILENAME=True`. An attacker can write uploaded files to arbitrary locations on the filesystem by crafting a malicious filename. Users should upgrade to version 0.0.22 to receive a patch or, as a workaround, avoid using `UPLOAD_KEEP_FILENAME=True` in project configurations.",
        "remediation": "Upgrade python-multipart from 0.0.20 to 0.0.22 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "high",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2026-42561",
        "title": "python-multipart: python-multipart: Denial of Service via excessive multipart part headers",
        "description": "Python-Multipart is a streaming multipart parser for Python. Prior to 0.0.27, python-multipart has a denial of service vulnerability in multipart part header parsing. When parsing multipart/form-data, MultipartParser previously had no limit on the number of part headers or the size of an individual part header. An attacker could send a request with either many repeated headers without terminating the header block or a single very large header value, causing excessive CPU work before request reje",
        "remediation": "Upgrade python-multipart from 0.0.20 to 0.0.27 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "high",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2026-53539",
        "title": "python-multipart: Python-Multipart: Denial of Service via crafted form-urlencoded bodies",
        "description": "Python-Multipart is a streaming multipart parser for Python. Prior to 0.0.30, when parsing application/x-www-form-urlencoded bodies, QuerystringParser located the field separator with a two step lookup: it first scanned the entire remaining buffer for &, and only when no & existed anywhere ahead did it fall back to scanning for ;. For a body that uses ; as the separator and contains no &, every field iteration performed a full failed & scan over the entire remaining buffer before locating the ne",
        "remediation": "Upgrade python-multipart from 0.0.20 to 0.0.30 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "medium",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2026-40347",
        "title": "python-multipart: Python-Multipart: Denial of Service via crafted multipart/form-data requests",
        "description": "Python-Multipart is a streaming multipart parser for Python. Versions prior to 0.0.26 have a denial of service vulnerability when parsing crafted `multipart/form-data` requests with large preamble or epilogue sections. Upgrade to version 0.0.26 or later, which skips ahead to the next boundary candidate when processing leading CR/LF data and immediately discards epilogue data after the closing boundary.",
        "remediation": "Upgrade python-multipart from 0.0.20 to 0.0.26 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "low",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2026-53537",
        "title": "multipart: Python-Multipart: Information disclosure via header parsing discrepancy",
        "description": "Python-Multipart is a streaming multipart parser for Python. Prior to 0.0.30, parse_options_header parsed Content-Disposition (and Content-Type) headers with email.message.Message, which transparently applies RFC 2231/5987 decoding. The extended parameter syntax (filename*=charset'lang'value, name*=..., and the filename*0/filename*1 continuation form) is decoded and surfaced under the bare filename/name key, and overrides the plain parameter when both are present. RFC 7578 \u00a74.2 explicitly forbid",
        "remediation": "Upgrade python-multipart from 0.0.20 to 0.0.30 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "low",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2026-53538",
        "title": "python-multipart: Python-Multipart: Information disclosure due to parser differential in form data handling",
        "description": "Python-Multipart is a streaming multipart parser for Python. Prior to 0.0.30, QuerystringParser treated ; as a field separator in application/x-www-form-urlencoded bodies, in addition to &. The WHATWG URL standard, modern browsers, and Python's urllib.parse (since the CVE-2021-23336 fix) treat only & as a separator. This creates a parser differential: the same bytes are tokenized into different fields than a WHATWG compliant intermediary would produce, allowing an attacker to smuggle extra form ",
        "remediation": "Upgrade python-multipart from 0.0.20 to 0.0.30 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "low",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2026-53540",
        "title": "python-multipart: Python-Multipart: Negative Content-Length in parse_form buffers the entire body in memory",
        "description": "Python-Multipart is a streaming multipart parser for Python. Prior to 0.0.31, parse_form() did not validate the Content-Length header before using it to bound its chunked read of the request body. A negative Content-Length turned the bounded read into a read-until-EOF, so the entire body was loaded into memory in a single read instead of in fixed-size chunks. This vulnerability is fixed in 0.0.31.",
        "remediation": "Upgrade python-multipart from 0.0.20 to 0.0.31 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "high",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2025-62727",
        "title": "starlette: Starlette DoS via Range header merging",
        "description": "Starlette is a lightweight ASGI framework/toolkit. Starting in version 0.39.0 and prior to version 0.49.1 , an unauthenticated attacker can send a crafted HTTP Range header that triggers quadratic-time processing in Starlette's FileResponse Range parsing/merging logic. This enables CPU exhaustion per request, causing denial\u2011of\u2011service for endpoints serving files (e.g., StaticFiles or any use of FileResponse). This vulnerability is fixed in 0.49.1.",
        "remediation": "Upgrade starlette from 0.47.1 to 0.49.1 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "high",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2026-48818",
        "title": "starlette: Starlette: SSRF and NTLM credential theft via UNC paths in StaticFiles on Windows",
        "description": "Starlette is a lightweight ASGI framework/toolkit. In versions 1.0.1 and earlier, StaticFiles on Windows is vulnerable to SSRF. An UNC path such as \\\\attacker.com\\share can cause os.path.realpath to initiate an outbound SMB connection before the path is rejected, exposing the service account\u2019s NTLMv2 credentials for offline cracking or relay even though the HTTP response is only a 404. The issue affects default follow_symlink=False deployments, including frameworks built on Starlette such as Fas",
        "remediation": "Upgrade starlette from 0.47.1 to 1.1.0 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "high",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2026-54283",
        "title": "starlette: Starlette: request.form() limits silently ignored for application/x-www-form-urlencoded enable DoS",
        "description": "Starlette is a lightweight ASGI framework/toolkit. From 0.4.1 until 1.3.1, request.form() accepts max_fields and max_part_size to bound resource consumption while parsing form data. These limits are enforced for multipart/form-data, but silently ignored for application/x-www-form-urlencoded. An unauthenticated attacker can therefore send a urlencoded body with an arbitrarily large number of fields or an arbitrarily large field, even when the application configured limits it believed would apply.",
        "remediation": "Upgrade starlette from 0.47.1 to 1.3.1 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "medium",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2025-54121",
        "title": "starlette: Starlette denial-of-service",
        "description": "Starlette is a lightweight ASGI (Asynchronous Server Gateway Interface) framework/toolkit, designed for building async web services in Python. In versions 0.47.1 and below, when parsing a multi-part form with large files (greater than the default max spool size) starlette will block the main thread to roll the file over to disk. This blocks the event thread which means the application can't accept new connections. The UploadFile code has a minor bug where instead of just checking for self._in_me",
        "remediation": "Upgrade starlette from 0.47.1 to 0.47.2 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "medium",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2026-48710",
        "title": "starlette: Starlette: Security restriction bypass via malformed HTTP Host header",
        "description": "Starlette is a lightweight ASGI framework/toolkit. Prior to version 1.0.1, the HTTP `Host` request header was not validated before being used to reconstruct `request.url`. Because the routing algorithm relies on the raw HTTP path while `request.url` is rebuilt from the `Host` header, a malformed header could make `request.url.path` differ from the path that was actually requested. Middleware and endpoints that apply security restrictions based on `request.url` (rather than the raw `scope` path) ",
        "remediation": "Upgrade starlette from 0.47.1 to 1.0.1 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "medium",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2026-48817",
        "title": "starlette: Starlette: Information disclosure and unintended method execution via non-standard HTTP methods",
        "description": "Starlette is a lightweight ASGI framework/toolkit. In versions 1.0.1 and below, when dispatching a request, HTTPEndpoint selects the handler by lowercasing the HTTP method and looking it up as an attribute with getattr, without restricting the lookup to a known set of HTTP verbs. When an HTTPEndpoint subclass is registered through Route(...) without an explicit methods= argument, the route does not constrain the method and every method reaches the endpoint. If a non-standard HTTP method whose lo",
        "remediation": "Upgrade starlette from 0.47.1 to 1.1.0 or later"
      },
      {
        "tool_name": "trivy",
        "severity": "low",
        "category": "uv",
        "file_path": "uv.lock",
        "line_number": null,
        "rule_identifier": "CVE-2026-54282",
        "title": "starlette: Starlette: Information disclosure due to improper HTTP request path validation",
        "description": "Starlette is a lightweight ASGI framework/toolkit. Prior to 1.3.0, the HTTP request path is not validated before being used to reconstruct request.url. Because request.url is rebuilt by concatenating {scheme}://{host}{path} and re-parsing the result, a path that does not begin with / (for example @google.com) moves the authority boundary during re-parsing, so request.url.hostname and request.url.netloc become attacker-controlled. Code that reads request.url.hostname (rather than the Host header ",
        "remediation": "Upgrade starlette from 0.47.1 to 1.3.0 or later"
      }
    ],
    "execution_duration_seconds": 0.6699284600035753,
    "status": "complete",
    "metadata": {
      "source": "github-releases",
      "source_url": "https://github.com/aquasecurity/trivy/releases/tag/v0.71.0",
      "report_type": "filesystem-vulnerability",
      "install_command": "curl -sfL -o /tmp/trivy.deb https://github.com/aquasecurity/trivy/releases/download/v0.71.0/trivy_0.71.0_Linux-64bit.deb && echo '<sha256>  /tmp/trivy.deb' | sha256sum -c - && dpkg -i /tmp/trivy.deb",
      "severity_counts": {
        "low": 4,
        "high": 10,
        "medium": 6,
        "critical": 0,
        "informational": 0
      },
      "manifests_scanned": [
        "uv.lock"
      ]
    },
    "display_score": 0.0,
    "display_badge": "Unsafe"
  },
  {
    "scanner_name": "osv-scanner",
    "scanner_version": "2.3.8",
    "score": 0.0,
    "scanner_badge": "Unsafe",
    "findings": [
      {
        "tool_name": "osv-scanner",
        "severity": "high",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-2132",
        "title": "PYSEC-2026-2132 \u2014 PyPI click@8.2.1",
        "description": "aliases: CVE-2026-7246, GHSA-47fr-3ffg-hgmw, PYSEC-2026-2132 | CVSS: 7.2",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "medium",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-215",
        "title": "PYSEC-2026-215 \u2014 PyPI idna@3.10",
        "description": "aliases: CVE-2026-45409, GHSA-65pc-fj4g-8rjx, PYSEC-2026-215 | CVSS: 6.9",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "high",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-1617",
        "title": "PYSEC-2026-1617 \u2014 PyPI mcp@1.9.4",
        "description": "aliases: CVE-2025-66416, GHSA-9h52-p55h-vw2f, PYSEC-2026-1617 | CVSS: 7.6",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "high",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-1618",
        "title": "PYSEC-2026-1618 \u2014 PyPI mcp@1.9.4",
        "description": "aliases: CVE-2025-53365, GHSA-j975-95f5-7wqh, PYSEC-2026-1618 | CVSS: 8.7",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "high",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "GHSA-jpw9-pfvf-9f58",
        "title": "GHSA-jpw9-pfvf-9f58 \u2014 PyPI mcp@1.9.4",
        "description": "aliases: CVE-2026-52869, GHSA-jpw9-pfvf-9f58 | CVSS: 7.1",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "high",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "GHSA-vj7q-gjh5-988w",
        "title": "GHSA-vj7q-gjh5-988w \u2014 PyPI mcp@1.9.4",
        "description": "aliases: CVE-2026-59950, GHSA-vj7q-gjh5-988w | CVSS: 7.6",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "low",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-2987",
        "title": "PYSEC-2026-2987 \u2014 PyPI pygments@2.19.2",
        "description": "aliases: CVE-2026-4539, GHSA-5239-wwwm-4pmq, PYSEC-2026-2987 | CVSS: 3.3",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "medium",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-1845",
        "title": "PYSEC-2026-1845 \u2014 PyPI pytest@8.4.1",
        "description": "aliases: CVE-2025-71176, GHSA-6w46-j5rx-g56g, PYSEC-2026-1845 | CVSS: 6.8",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "medium",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-2270",
        "title": "PYSEC-2026-2270 \u2014 PyPI python-dotenv@1.1.1",
        "description": "aliases: CVE-2026-28684, GHSA-mf9w-mj56-hr94, PYSEC-2026-2270 | CVSS: 6.6",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "high",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-1852",
        "title": "PYSEC-2026-1852 \u2014 PyPI python-multipart@0.0.20",
        "description": "aliases: CVE-2026-24486, GHSA-wp53-j4wj-2cfg, PYSEC-2026-1852 | CVSS: 8.6",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "high",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-3036",
        "title": "PYSEC-2026-3036 \u2014 PyPI python-multipart@0.0.20",
        "description": "aliases: CVE-2026-53539, GHSA-5rvq-cxj2-64vf, PYSEC-2026-3036 | CVSS: 7.5",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "low",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-3037",
        "title": "PYSEC-2026-3037 \u2014 PyPI python-multipart@0.0.20",
        "description": "aliases: CVE-2026-53538, GHSA-6jv3-5f52-599m, PYSEC-2026-3037 | CVSS: 3.7",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "medium",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-3038",
        "title": "PYSEC-2026-3038 \u2014 PyPI python-multipart@0.0.20",
        "description": "aliases: CVE-2026-40347, GHSA-mj87-hwqh-73pj, PYSEC-2026-3038 | CVSS: 5.3",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "high",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-3039",
        "title": "PYSEC-2026-3039 \u2014 PyPI python-multipart@0.0.20",
        "description": "aliases: CVE-2026-42561, GHSA-pp6c-gr5w-3c5g, PYSEC-2026-3039 | CVSS: 7.5",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "low",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-3040",
        "title": "PYSEC-2026-3040 \u2014 PyPI python-multipart@0.0.20",
        "description": "aliases: CVE-2026-53540, GHSA-v9pg-7xvm-68hf, PYSEC-2026-3040 | CVSS: 3.7",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "low",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-3041",
        "title": "PYSEC-2026-3041 \u2014 PyPI python-multipart@0.0.20",
        "description": "aliases: CVE-2026-53537, GHSA-vffw-93wf-4j4q, PYSEC-2026-3041 | CVSS: 3.7",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "medium",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-161",
        "title": "PYSEC-2026-161 \u2014 PyPI starlette@0.47.1",
        "description": "aliases: CVE-2026-48710, GHSA-86qp-5c8j-p5mr, PYSEC-2026-161, X41-2026-002 | CVSS: 6.5",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "medium",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-1941",
        "title": "PYSEC-2026-1941 \u2014 PyPI starlette@0.47.1",
        "description": "aliases: CVE-2025-54121, GHSA-2c2j-9gv5-cj73, PYSEC-2026-1941 | CVSS: 5.3",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "high",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-1942",
        "title": "PYSEC-2026-1942 \u2014 PyPI starlette@0.47.1",
        "description": "aliases: CVE-2025-62727, GHSA-7f5h-v6xp-fcq8, PYSEC-2026-1942 | CVSS: 7.5",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "medium",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-2280",
        "title": "PYSEC-2026-2280 \u2014 PyPI starlette@0.47.1",
        "description": "aliases: CVE-2026-48817, GHSA-x746-7m8f-x49c, PYSEC-2026-2280 | CVSS: 5.3",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "high",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-2281",
        "title": "PYSEC-2026-2281 \u2014 PyPI starlette@0.47.1",
        "description": "aliases: CVE-2026-48818, GHSA-wqp7-x3pw-xc5r, PYSEC-2026-2281 | CVSS: 7.5",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "medium",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-248",
        "title": "PYSEC-2026-248 \u2014 PyPI starlette@0.47.1",
        "description": "aliases: CVE-2026-54282, GHSA-jp82-jpqv-5vv3, PYSEC-2026-248 | CVSS: 5.3",
        "remediation": null
      },
      {
        "tool_name": "osv-scanner",
        "severity": "high",
        "category": "PyPI",
        "file_path": "/repo/uv.lock",
        "line_number": null,
        "rule_identifier": "PYSEC-2026-249",
        "title": "PYSEC-2026-249 \u2014 PyPI starlette@0.47.1",
        "description": "aliases: CVE-2026-54283, GHSA-82w8-qh3p-5jfq, PYSEC-2026-249 | CVSS: 7.5",
        "remediation": null
      }
    ],
    "execution_duration_seconds": 3.9322215220017824,
    "status": "complete",
    "metadata": {
      "source": "github-releases",
      "source_url": "https://github.com/google/osv-scanner/releases/tag/v2.3.8",
      "report_type": "osv-vulnerability",
      "ecosystems_seen": [
        "PyPI"
      ],
      "install_command": "curl -sfL -o /usr/local/bin/osv-scanner https://github.com/google/osv-scanner/releases/download/v2.3.8/osv-scanner_linux_amd64 && echo '<sha256>  /usr/local/bin/osv-scanner' | sha256sum -c - && chmod +x /usr/local/bin/osv-scanner",
      "severity_counts": {
        "low": 4,
        "high": 11,
        "medium": 8,
        "critical": 0,
        "informational": 0
      },
      "manifests_scanned": [
        "/repo/uv.lock"
      ],
      "finding_id_aliases": {
        "PYSEC-2026-161": [
          "CVE-2026-48710",
          "GHSA-86qp-5c8j-p5mr",
          "X41-2026-002"
        ],
        "PYSEC-2026-215": [
          "CVE-2026-45409",
          "GHSA-65pc-fj4g-8rjx"
        ],
        "PYSEC-2026-248": [
          "CVE-2026-54282",
          "GHSA-jp82-jpqv-5vv3"
        ],
        "PYSEC-2026-249": [
          "CVE-2026-54283",
          "GHSA-82w8-qh3p-5jfq"
        ],
        "PYSEC-2026-1617": [
          "CVE-2025-66416",
          "GHSA-9h52-p55h-vw2f"
        ],
        "PYSEC-2026-1618": [
          "CVE-2025-53365",
          "GHSA-j975-95f5-7wqh"
        ],
        "PYSEC-2026-1845": [
          "CVE-2025-71176",
          "GHSA-6w46-j5rx-g56g"
        ],
        "PYSEC-2026-1852": [
          "CVE-2026-24486",
          "GHSA-wp53-j4wj-2cfg"
        ],
        "PYSEC-2026-1941": [
          "CVE-2025-54121",
          "GHSA-2c2j-9gv5-cj73"
        ],
        "PYSEC-2026-1942": [
          "CVE-2025-62727",
          "GHSA-7f5h-v6xp-fcq8"
        ],
        "PYSEC-2026-2132": [
          "CVE-2026-7246",
          "GHSA-47fr-3ffg-hgmw"
        ],
        "PYSEC-2026-2270": [
          "CVE-2026-28684",
          "GHSA-mf9w-mj56-hr94"
        ],
        "PYSEC-2026-2280": [
          "CVE-2026-48817",
          "GHSA-x746-7m8f-x49c"
        ],
        "PYSEC-2026-2281": [
          "CVE-2026-48818",
          "GHSA-wqp7-x3pw-xc5r"
        ],
        "PYSEC-2026-2987": [
          "CVE-2026-4539",
          "GHSA-5239-wwwm-4pmq"
        ],
        "PYSEC-2026-3036": [
          "CVE-2026-53539",
          "GHSA-5rvq-cxj2-64vf"
        ],
        "PYSEC-2026-3037": [
          "CVE-2026-53538",
          "GHSA-6jv3-5f52-599m"
        ],
        "PYSEC-2026-3038": [
          "CVE-2026-40347",
          "GHSA-mj87-hwqh-73pj"
        ],
        "PYSEC-2026-3039": [
          "CVE-2026-42561",
          "GHSA-pp6c-gr5w-3c5g"
        ],
        "PYSEC-2026-3040": [
          "CVE-2026-53540",
          "GHSA-v9pg-7xvm-68hf"
        ],
        "PYSEC-2026-3041": [
          "CVE-2026-53537",
          "GHSA-vffw-93wf-4j4q"
        ],
        "GHSA-jpw9-pfvf-9f58": [
          "CVE-2026-52869"
        ],
        "GHSA-vj7q-gjh5-988w": [
          "CVE-2026-59950"
        ]
      },
      "cross_scanner_correlation": {
        "only_osv": [
          "PYSEC-2026-1845",
          "PYSEC-2026-2132",
          "PYSEC-2026-2987"
        ],
        "only_trivy": [],
        "intersection_ids": [
          "CVE-2025-53365",
          "CVE-2025-54121",
          "CVE-2025-62727",
          "CVE-2025-66416",
          "CVE-2026-24486",
          "CVE-2026-28684",
          "CVE-2026-40347",
          "CVE-2026-42561",
          "CVE-2026-45409",
          "CVE-2026-48710",
          "CVE-2026-48817",
          "CVE-2026-48818",
          "CVE-2026-52869",
          "CVE-2026-53537",
          "CVE-2026-53538",
          "CVE-2026-53539",
          "CVE-2026-53540",
          "CVE-2026-54282",
          "CVE-2026-54283",
          "CVE-2026-59950"
        ]
      }
    },
    "display_score": 0.0,
    "display_badge": "Unsafe"
  }
]
```
