# Security Audit Report — a11y-mcp

- **Report ID:** `cab7625a-807f-4fcf-b6c7-9131e8e14022`
- **Generated:** 2026-08-12T19:03:58.567973+00:00
- **Signature:** unsigned (cosign keyless signing runs in CI; Req 22.4)

## 1. Executive Summary

**Badge:** Caution (composite)  
**Security score:** 94.08

| Scanner | Badge |
| --- | --- |
| agent-audit-kit | Caution |
| agentshield | Verified |
| bearer | Verified |
| capslock | not_applicable |
| cisco-skill-scanner | Verified |
| govulncheck | not_applicable |
| nerlo-behavioral | Verified |
| nerlo-install-instruction | Verified |
| osv-scanner | not_applicable |
| trivy | not_applicable |
| trivy_image | not_applicable |

| Severity | Findings |
| --- | --- |
| critical | 0 |
| high | 1 |
| medium | 3 |
| low | 2 |
| informational | 3 |

a11y-mcp may be integrated with compensating controls: review the 1 high-severity findings below, restrict granted permissions to the minimum the manifest declares, and subscribe to monitoring alerts for score changes.

## 2. Source Provenance

- **Repository:** https://github.com/priyankark/a11y-mcp
- **Commit scanned:** `unknown`
- **License:** MPL-2.0
- **Maintainer:** unknown
- **Version:** 1.0.6

## 3. Per-Scanner Detail

### agentshield (v1.4.0) — Verified / 100.0

No findings.

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

- **[informational] Moderate analyzability score** — [mcp_server policy: capability-matches-purpose class; severity medium -> informational] Only 86% of skill content could be analyzed. 1 of 8 files are opaque to the scanner. Some content could not be verified as safe. (/repo:None)
- **[informational] Vague skill description** — [mcp_server policy: capability-matches-purpose class; severity low -> informational] 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 / 66.0

- **[medium] MCP server uses npx/uvx to fetch and execute remote packages** — The command uses npx, uvx, bunx, or pnpx which fetches the latest version from a registry at runtime, vulnerable to typosquatting and dependency confusion. (config/mcp-config.json:4)
- **[low] MCP server lacks version pinning in args** — Package name in args lacks @version suffix when using npx/uvx. Unpinned packages can silently update to malicious versions. (config/mcp-config.json:5)
- **[medium] No lockfile present** — A package manifest exists but no lockfile was found. Without lockfiles, dependency versions float and can be silently updated. (package.json:None)
- **[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. (package.json:25)
- **[high] MCP server built on the upstream SDK without STDIO sanitizer** — Repository declares a dependency on the upstream Anthropic / ModelContextProtocol SDK (Python 'mcp' / 'modelcontextprotocol', TS '@modelcontextprotocol/sdk', Java 'io.modelcontextprotocol:*', Rust 'mcp' / 'modelcontextprotocol') and exposes a STDIO transport ('StdioServerTransport', 'stdio_server', etc.) without a sanitizer on argv assembly. Anthropic declined to CVE this as working as designed — sanitization is the developer's responsibility. The OX Security disclosure on 2026-04-15 rolled up L (src/index.js:None)

### 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.

### capslock (vv0.3.2) — not_applicable / n/a

No findings.

### trivy (v0.71.0) — not_applicable / n/a

No findings.

### osv-scanner (v2.3.8) — not_applicable / n/a

No findings.

### trivy_image (v0.71.0) — not_applicable / n/a

No findings.

### govulncheck (vv1.6.0) — not_applicable / n/a

No findings.

## 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:** `d9bf1152-9ad9-44f6-8e26-a6891cd10713`
- **Completed:** 2026-08-12T14:55:10.143790+00:00
- **Scanner base image:** `us-central1-docker.pkg.dev/nerlo-vsk-prod/nerlo/scanner-base@sha256:d5aaefa8b517d1f03832091ab094e20dc73160a07ae1102af1b2e395ce6ce852`
- **AI decision log entries:** 2
  - `0b0d87d9-3c31-4d66-9736-783745443895`
  - `1941f9df-dac6-4d64-a70e-c9af07525991`

## 6. Appendix — Raw Scanner Output

```json
[
  {
    "scanner_name": "agentshield",
    "scanner_version": "1.4.0",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 0.6614737490308471,
    "status": "complete",
    "examined": {
      "unit": "scan_targets",
      "count": 1
    },
    "metadata": {
      "source": "npm",
      "source_url": "https://www.npmjs.com/package/ecc-agentshield",
      "install_command": "npm install -g ecc-agentshield@1.4.0",
      "scans_performed": [
        "supply_chain"
      ]
    },
    "display_score": 100.0,
    "display_badge": "Verified"
  },
  {
    "scanner_name": "cisco-skill-scanner",
    "scanner_version": "2.0.11",
    "score": 98.5,
    "scanner_badge": "Verified",
    "findings": [
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "informational",
        "category": "policy_violation",
        "file_path": "/repo",
        "line_number": null,
        "rule_identifier": "LOW_ANALYZABILITY",
        "title": "Moderate analyzability score",
        "description": "[mcp_server policy: capability-matches-purpose class; severity medium -> informational] Only 86% of skill content could be analyzed. 1 of 8 files are opaque to the scanner. Some content could not be verified as safe.",
        "remediation": "Review opaque files and replace with inspectable formats where possible."
      },
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "informational",
        "category": "social_engineering",
        "file_path": "/repo/SKILL.md",
        "line_number": null,
        "rule_identifier": "SOCIAL_ENG_VAGUE_DESCRIPTION",
        "title": "Vague skill description",
        "description": "[mcp_server policy: capability-matches-purpose class; severity low -> informational] 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": 6.6878316620131955,
    "status": "complete",
    "examined": {
      "unit": "skills",
      "count": 1
    },
    "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": 0,
        "high": 0,
        "medium": 0,
        "critical": 0,
        "informational": 3
      },
      "artifact_type_policy": "mcp_server",
      "downweighted_findings": 2
    },
    "display_score": 98.5,
    "display_badge": "Verified"
  },
  {
    "scanner_name": "agent-audit-kit",
    "scanner_version": "0.3.26",
    "score": 66.0,
    "scanner_badge": "Caution",
    "findings": [
      {
        "tool_name": "agent-audit-kit",
        "severity": "medium",
        "category": "mcp-config",
        "file_path": "config/mcp-config.json",
        "line_number": 4,
        "rule_identifier": "AAK-MCP-005",
        "title": "MCP server uses npx/uvx to fetch and execute remote packages",
        "description": "The command uses npx, uvx, bunx, or pnpx which fetches the latest version from a registry at runtime, vulnerable to typosquatting and dependency confusion.",
        "remediation": "Pin exact package versions or use locally installed packages."
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "low",
        "category": "mcp-config",
        "file_path": "config/mcp-config.json",
        "line_number": 5,
        "rule_identifier": "AAK-MCP-007",
        "title": "MCP server lacks version pinning in args",
        "description": "Package name in args lacks @version suffix when using npx/uvx. Unpinned packages can silently update to malicious versions.",
        "remediation": "Pin with @x.y.z suffix, e.g., @modelcontextprotocol/server-filesystem@2025.1.1"
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "medium",
        "category": "supply-chain",
        "file_path": "package.json",
        "line_number": null,
        "rule_identifier": "AAK-SUPPLY-004",
        "title": "No lockfile present",
        "description": "A package manifest exists but no lockfile was found. Without lockfiles, dependency versions float and can be silently updated.",
        "remediation": "Generate and commit lockfile."
      },
      {
        "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": "package.json",
        "line_number": 25,
        "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": "src/index.js",
        "line_number": null,
        "rule_identifier": "AAK-ANTHROPIC-SDK-001",
        "title": "MCP server built on the upstream SDK without STDIO sanitizer",
        "description": "Repository declares a dependency on the upstream Anthropic / ModelContextProtocol SDK (Python `mcp` / `modelcontextprotocol`, TS `@modelcontextprotocol/sdk`, Java `io.modelcontextprotocol:*`, Rust `mcp` / `modelcontextprotocol`) and exposes a STDIO transport (`StdioServerTransport`, `stdio_server`, etc.) without a sanitizer on argv assembly. Anthropic declined to CVE this as working as designed \u2014 sanitization is the developer's responsibility. The OX Security disclosure on 2026-04-15 rolled up L",
        "remediation": "Wrap every argv the STDIO transport builds in an allow-list sanitizer \u2014 `shlex.quote` in Python, `execFile` with an explicit argv array in Node, equivalent in Java/Rust. OR switch the transport off STDIO (`transports=['http']` / `['sse']`). If you have deliberately accepted the risk, add `accepts_stdio_risk: true` plus a `justification:` field in `.agent-audit-kit.yml`."
      }
    ],
    "execution_duration_seconds": 0.6330428519868292,
    "status": "complete",
    "examined": {
      "unit": "files",
      "count": 6
    },
    "metadata": {
      "source": "pypi",
      "source_url": "https://pypi.org/project/agent-audit-kit/0.3.26/",
      "report_type": "agent-audit-kit-sast",
      "install_command": "pip install --require-hashes -r docker/scanner-base/agent-audit-kit/requirements.txt",
      "rules_evaluated": 211,
      "severity_counts": {
        "low": 2,
        "high": 1,
        "medium": 3,
        "critical": 0,
        "informational": 0
      }
    },
    "display_score": 66.0,
    "display_badge": "Caution"
  },
  {
    "scanner_name": "bearer",
    "scanner_version": "2.0.2",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 2.723660358984489,
    "status": "complete",
    "examined": {
      "unit": "files",
      "count": 1
    },
    "metadata": {
      "source": "github-releases",
      "source_url": "https://github.com/Bearer/bearer",
      "report_type": "security",
      "stderr_tail": "Analyzing codebase",
      "rules_loaded": 554,
      "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": 3.2218279109802097,
    "status": "complete",
    "examined": {
      "unit": "files",
      "count": 1
    },
    "metadata": {
      "source": "nerlo-original",
      "source_url": "https://github.com/nerlo-ai/nerlo",
      "report_type": "nerlo-behavioral",
      "ruleset_path": "/opt/nerlo-rules/exfiltration.yaml",
      "ruleset_paths": [
        "/opt/nerlo-rules/exfiltration.yaml",
        "/opt/nerlo-rules/clipboard_exfiltration.yaml",
        "/opt/nerlo-rules/rce_endpoint.yaml",
        "/opt/nerlo-rules/taint_egress.yaml"
      ],
      "install_command": "pip install 'semgrep==1.97.0'",
      "merged_invocation": true
    },
    "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": 3.222079320985358,
    "status": "complete",
    "examined": {
      "unit": "files",
      "count": 1
    },
    "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",
      "ruleset_paths": [
        "/opt/nerlo-rules/install_instructions.yaml",
        "/opt/nerlo-rules/cursor_rules.yaml"
      ],
      "install_command": "pip install 'semgrep==1.97.0'",
      "merged_invocation": true
    },
    "display_score": 100.0,
    "display_badge": "Verified"
  },
  {
    "scanner_name": "capslock",
    "scanner_version": "v0.3.2",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 0.1216016510152258,
    "status": "not_applicable",
    "examined": {
      "unit": "packages",
      "count": 0
    },
    "metadata": {
      "source": "go-module-proxy",
      "source_url": "https://github.com/google/capslock/releases/tag/v0.3.2",
      "report_type": "go-capability",
      "vendor_mode": false,
      "install_command": "GOTOOLCHAIN=local GOFLAGS=-mod=mod GOSUMDB=sum.golang.org GOBIN=/usr/local/bin go install github.com/google/capslock/cmd/capslock@v0.3.2  # github.com/google/capslock v0.3.2 h1:0ZQa9YR8s9ewFu1g5w6Rgd/lW/4dga7qJew3K6Ql7aM=",
      "environment_note": "capslock found no .go files to analyze; reported not_applicable rather than a clean 100 \u2014 the scanner never ran, so it has no verdict to contribute",
      "go_files_present": 0,
      "artifact_type_policy": "mcp_server",
      "expected_capabilities": [
        "CAPABILITY_FILES",
        "CAPABILITY_NETWORK",
        "CAPABILITY_READ_SYSTEM_STATE",
        "CAPABILITY_REFLECT",
        "CAPABILITY_RUNTIME"
      ],
      "artifact_type_explicit": true
    },
    "display_score": null,
    "display_badge": "not_applicable"
  },
  {
    "scanner_name": "trivy",
    "scanner_version": "0.71.0",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 0.17333269800292328,
    "status": "not_applicable",
    "examined": {
      "unit": "manifests",
      "count": 0
    },
    "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",
      "manifests_scanned": []
    },
    "display_score": null,
    "display_badge": "not_applicable"
  },
  {
    "scanner_name": "osv-scanner",
    "scanner_version": "2.3.8",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 0.14586052997037768,
    "status": "not_applicable",
    "examined": {
      "unit": "manifests",
      "count": 0
    },
    "metadata": {
      "source": "github-releases",
      "source_url": "https://github.com/google/osv-scanner/releases/tag/v2.3.8",
      "report_type": "osv-vulnerability",
      "ecosystems_seen": [],
      "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",
      "manifests_scanned": [],
      "finding_id_aliases": {},
      "cross_scanner_correlation": {
        "only_osv": [],
        "only_trivy": [],
        "intersection_ids": []
      }
    },
    "display_score": null,
    "display_badge": "not_applicable"
  },
  {
    "scanner_name": "trivy_image",
    "scanner_version": "0.71.0",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 3.6139972507953644e-05,
    "status": "not_applicable",
    "examined": {
      "unit": "image_targets",
      "count": 0
    },
    "metadata": {
      "reason": "no OCI image acquired for this artifact"
    },
    "display_score": null,
    "display_badge": "not_applicable"
  },
  {
    "scanner_name": "govulncheck",
    "scanner_version": "v1.6.0",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 0.06939577299635857,
    "status": "not_applicable",
    "examined": {
      "unit": "modules",
      "count": 0
    },
    "metadata": {
      "source": "go-module-proxy",
      "source_url": "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck",
      "report_type": "go-reachability",
      "vendor_mode": false,
      "go_mod_present": false,
      "install_command": "GOTOOLCHAIN=local GOFLAGS=-mod=mod GOSUMDB=sum.golang.org GOBIN=/usr/local/bin go install golang.org/x/vuln/cmd/govulncheck@v1.6.0  # golang.org/x/vuln v1.6.0 h1:FeMO9Rm/HwyduOztbvKcOw+zvDEPr4I4aQNSfevFcKY=",
      "offline_db_path": "/opt/govulncheck-db",
      "environment_note": "govulncheck found no go.mod, so this tree declares no Go module and no Go dependencies; reported not_applicable rather than a clean 100 \u2014 the scanner never ran, so it has no verdict to contribute"
    },
    "display_score": null,
    "display_badge": "not_applicable"
  }
]
```
