mcpprobe-scanner 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcpprobe_scanner-0.1.0/.gitignore +12 -0
- mcpprobe_scanner-0.1.0/CHANGELOG.md +44 -0
- mcpprobe_scanner-0.1.0/CHECKS.md +484 -0
- mcpprobe_scanner-0.1.0/LICENSE +21 -0
- mcpprobe_scanner-0.1.0/PKG-INFO +240 -0
- mcpprobe_scanner-0.1.0/README.md +202 -0
- mcpprobe_scanner-0.1.0/SECURITY.md +47 -0
- mcpprobe_scanner-0.1.0/mcpprobe/__init__.py +21 -0
- mcpprobe_scanner-0.1.0/mcpprobe/action.py +69 -0
- mcpprobe_scanner-0.1.0/mcpprobe/authz.py +313 -0
- mcpprobe_scanner-0.1.0/mcpprobe/catalogue.py +125 -0
- mcpprobe_scanner-0.1.0/mcpprobe/checks/__init__.py +100 -0
- mcpprobe_scanner-0.1.0/mcpprobe/checks/_util.py +102 -0
- mcpprobe_scanner-0.1.0/mcpprobe/checks/active_stubs.py +212 -0
- mcpprobe_scanner-0.1.0/mcpprobe/checks/auth.py +473 -0
- mcpprobe_scanner-0.1.0/mcpprobe/checks/base.py +228 -0
- mcpprobe_scanner-0.1.0/mcpprobe/checks/baseline.py +219 -0
- mcpprobe_scanner-0.1.0/mcpprobe/checks/capability.py +171 -0
- mcpprobe_scanner-0.1.0/mcpprobe/checks/metadata.py +341 -0
- mcpprobe_scanner-0.1.0/mcpprobe/checks/poisoning.py +480 -0
- mcpprobe_scanner-0.1.0/mcpprobe/checks/robustness.py +266 -0
- mcpprobe_scanner-0.1.0/mcpprobe/checks/transport_conformance.py +429 -0
- mcpprobe_scanner-0.1.0/mcpprobe/cli.py +295 -0
- mcpprobe_scanner-0.1.0/mcpprobe/dnsutil.py +67 -0
- mcpprobe_scanner-0.1.0/mcpprobe/governance.py +74 -0
- mcpprobe_scanner-0.1.0/mcpprobe/models.py +264 -0
- mcpprobe_scanner-0.1.0/mcpprobe/policy.py +140 -0
- mcpprobe_scanner-0.1.0/mcpprobe/py.typed +0 -0
- mcpprobe_scanner-0.1.0/mcpprobe/redact.py +101 -0
- mcpprobe_scanner-0.1.0/mcpprobe/report/__init__.py +7 -0
- mcpprobe_scanner-0.1.0/mcpprobe/report/json_report.py +33 -0
- mcpprobe_scanner-0.1.0/mcpprobe/report/sarif.py +329 -0
- mcpprobe_scanner-0.1.0/mcpprobe/report/terminal.py +172 -0
- mcpprobe_scanner-0.1.0/mcpprobe/scanner.py +211 -0
- mcpprobe_scanner-0.1.0/mcpprobe/transport/__init__.py +34 -0
- mcpprobe_scanner-0.1.0/mcpprobe/transport/base.py +156 -0
- mcpprobe_scanner-0.1.0/mcpprobe/transport/evidence.py +135 -0
- mcpprobe_scanner-0.1.0/mcpprobe/transport/fingerprint.py +154 -0
- mcpprobe_scanner-0.1.0/mcpprobe/transport/http.py +366 -0
- mcpprobe_scanner-0.1.0/mcpprobe/transport/ratelimit.py +47 -0
- mcpprobe_scanner-0.1.0/mcpprobe/transport/stdio.py +201 -0
- mcpprobe_scanner-0.1.0/pyproject.toml +98 -0
- mcpprobe_scanner-0.1.0/tests/__init__.py +0 -0
- mcpprobe_scanner-0.1.0/tests/conftest.py +100 -0
- mcpprobe_scanner-0.1.0/tests/data/sarif-schema-2.1.0.json +3389 -0
- mcpprobe_scanner-0.1.0/tests/fake_server.py +559 -0
- mcpprobe_scanner-0.1.0/tests/fake_stdio_server.py +81 -0
- mcpprobe_scanner-0.1.0/tests/test_checks_auth.py +152 -0
- mcpprobe_scanner-0.1.0/tests/test_checks_meta.py +305 -0
- mcpprobe_scanner-0.1.0/tests/test_checks_robustness.py +99 -0
- mcpprobe_scanner-0.1.0/tests/test_checks_transport.py +129 -0
- mcpprobe_scanner-0.1.0/tests/test_docs_and_action.py +110 -0
- mcpprobe_scanner-0.1.0/tests/test_gate_and_policy.py +291 -0
- mcpprobe_scanner-0.1.0/tests/test_reports_and_cli.py +356 -0
- mcpprobe_scanner-0.1.0/tests/test_transport.py +169 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
|
|
5
|
+
[Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [0.1.0]
|
|
8
|
+
|
|
9
|
+
- Published on PyPI as `mcpprobe-scanner` (PyPI blocks `mcpprobe` and `mcpprobe-cli` as too similar to existing projects). The command and the Python package are both `mcpprobe`.
|
|
10
|
+
- 2026-10-27
|
|
11
|
+
|
|
12
|
+
First public release of the open-source scanner core.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- MCP client for Streamable HTTP (JSON-RPC over POST, JSON or SSE responses)
|
|
17
|
+
and stdio, written to send deliberately non-conformant requests.
|
|
18
|
+
- Protocol fingerprinting: `server/discover` (2026-07-28) first, then
|
|
19
|
+
`initialize` with 2025-11-25 and 2025-06-18, then the deprecated
|
|
20
|
+
2024-11-05 HTTP+SSE transport.
|
|
21
|
+
- Evidence log: every request/response with timestamp, method, status, a
|
|
22
|
+
header subset, bodies truncated to 4 KB, `Authorization` values and known
|
|
23
|
+
secret patterns redacted.
|
|
24
|
+
- Passive checks: AUTH-01..04, TRANS-01..05, META-01..05, ERR-01, DOS-01.
|
|
25
|
+
- Active checks INJ-01..05, SUPPLY-01/02 and SANDBOX-01 registered as gated
|
|
26
|
+
stubs (report `not_implemented`; no payloads are sent).
|
|
27
|
+
- Governance items GOV-01..05 listed as attestation-only in every report.
|
|
28
|
+
- Authorisation gate for active mode: `--authorised-by`, `--scope` and
|
|
29
|
+
ownership verification (`--verify dns-txt` via `_mcpprobe.<host>` TXT, or
|
|
30
|
+
`--verify local` for stdio); an authorisation record JSON is written next to
|
|
31
|
+
the report.
|
|
32
|
+
- Opt-out: DNS TXT `mcpprobe-opt-out=all` at `_mcpprobe.<host>` and
|
|
33
|
+
`/.well-known/mcpprobe-opt-out`, both checked before any MCP request.
|
|
34
|
+
- Rate limiting: 5 requests/second by default, hard ceiling 10.
|
|
35
|
+
- Reports: JSON (with evidence), SARIF 2.1.0 (validated against the official
|
|
36
|
+
schema in tests) and a rich terminal summary. Exit codes 0 / 1 / 2.
|
|
37
|
+
- META-02 baselines: canonical SHA-256 of tools, prompts, resources and
|
|
38
|
+
instructions with diffing against a stored baseline (rug-pull detection).
|
|
39
|
+
- Optional LLM-judge hook for META-01 (`ScanOptions.judge`); mcpprobe makes no
|
|
40
|
+
LLM or third-party network calls itself.
|
|
41
|
+
- Docker container GitHub Action, CI (ruff, strict mypy, pytest on Python
|
|
42
|
+
3.11 to 3.13) and PyPI Trusted Publishing release workflow.
|
|
43
|
+
|
|
44
|
+
[0.1.0]: https://github.com/mcpprobe-dev/mcpprobe/releases/tag/v0.1.0
|
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
# mcpprobe checks catalogue
|
|
2
|
+
|
|
3
|
+
Generated from the check metadata of mcpprobe 0.1.0 (`mcpprobe checks --format markdown`). Do not edit by hand.
|
|
4
|
+
|
|
5
|
+
Standards: OWASP MCP Top 10 (IDs `MCP0x:2025`, still a beta list, so shown with `(beta)`), OWASP Top 10 for Agentic Applications (`ASI0x`), OWASP Top 10 for LLM Applications 2026 (`LLM0x:2026`, primary) and 2025 (`LLM0x:2025`, kept for one release cycle). Severities are defaults; a check can raise or lower the severity of an individual finding (for example loopback-only servers are reported one level lower), and heuristic checks never rate a finding Critical on their own.
|
|
6
|
+
|
|
7
|
+
Passive checks send only what a normal MCP client would send plus a few benign malformed requests. They never call a tool. Active checks are listed so coverage is reported honestly; in this release they are stubs that run only behind the authorisation gate and report `not_implemented`.
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
| ID | Mode | Default severity | Title | Standards |
|
|
12
|
+
|---|---|---|---|---|
|
|
13
|
+
| [AUTH-01](#auth-01---remote-mcp-endpoint-accepts-requests-without-authentication) | passive | high | Remote MCP endpoint accepts requests without authentication | MCP07:2025 (beta), ASI03, LLM04:2026, LLM03:2026, LLM03:2025, LLM06:2025 |
|
|
14
|
+
| [AUTH-02](#auth-02---protected-resource-metadata-rfc-9728-missing-or-invalid) | passive | high | Protected resource metadata (RFC 9728) missing or invalid | MCP07:2025 (beta) |
|
|
15
|
+
| [AUTH-03](#auth-03---authorization-server-metadata-weak-or-missing-pkce-s256--https) | passive | high | Authorization server metadata weak or missing (PKCE S256 / HTTPS) | MCP07:2025 (beta), MCP01:2025 (beta) |
|
|
16
|
+
| [AUTH-04](#auth-04---server-accepts-a-self-minted-token-with-the-wrong-audienceissuer) | passive | critical | Server accepts a self-minted token with the wrong audience/issuer | MCP07:2025 (beta), MCP01:2025 (beta), ASI03 |
|
|
17
|
+
| [TRANS-01](#trans-01---origin-header-not-validated-dns-rebinding-exposure) | passive | medium | Origin header not validated (DNS-rebinding exposure) | MCP07:2025 (beta) |
|
|
18
|
+
| [TRANS-02](#trans-02---unsupported-mcp-protocol-version-header-not-rejected) | passive | low | Unsupported MCP-Protocol-Version header not rejected | MCP spec conformance / hygiene (no OWASP item) |
|
|
19
|
+
| [TRANS-03](#trans-03---weak-predictable-or-unvalidated-mcp-session-id) | passive | high | Weak, predictable or unvalidated Mcp-Session-Id | MCP07:2025 (beta) |
|
|
20
|
+
| [TRANS-04](#trans-04---deprecated-httpsse-2024-11-05-transport-in-use) | passive | info | Deprecated HTTP+SSE (2024-11-05) transport in use | MCP spec conformance / hygiene (no OWASP item) |
|
|
21
|
+
| [TRANS-05](#trans-05---plain-http-weak-tls-or-missing-security-headers) | passive | high | Plain HTTP, weak TLS or missing security headers | MCP01:2025 (beta) |
|
|
22
|
+
| [META-01](#meta-01---possible-tool-description-poisoning) | passive | high | Possible tool-description poisoning | MCP03:2025 (beta), ASI01, ASI04, LLM01:2026, LLM01:2025 |
|
|
23
|
+
| [META-02](#meta-02---tool-surface-changed-since-the-stored-baseline-rug-pull-indicator) | passive | medium | Tool surface changed since the stored baseline (rug-pull indicator) | MCP03:2025 (beta), ASI04 |
|
|
24
|
+
| [META-03](#meta-03---tool-annotations-contradict-the-tools-apparent-capability) | passive | medium | Tool annotations contradict the tool's apparent capability | MCP02:2025 (beta), MCP05:2025 (beta), ASI02, ASI05, LLM03:2026, LLM06:2025 |
|
|
25
|
+
| [META-04](#meta-04---tool-schema-hygiene-problems) | passive | low | Tool schema hygiene problems | MCP05:2025 (beta) |
|
|
26
|
+
| [META-05](#meta-05---secret-material-in-server-metadata-or-configuration) | passive | high | Secret material in server metadata or configuration | MCP01:2025 (beta), LLM02:2026, LLM02:2025 |
|
|
27
|
+
| [ERR-01](#err-01---verbose-error-responses-leak-stack-traces-paths-or-versions) | passive | medium | Verbose error responses leak stack traces, paths or versions | MCP08:2025 (beta), LLM02:2026, LLM02:2025 |
|
|
28
|
+
| [DOS-01](#dos-01---no-visible-limits-on-request-size-nesting-or-rate) | passive | low | No visible limits on request size, nesting or rate | ASI08, LLM06:2026, LLM10:2025 |
|
|
29
|
+
| [INJ-01](#inj-01---commandcode-injection-safe-canaries) | active | critical | Command/code injection (safe canaries) | MCP05:2025 (beta), ASI05, LLM10:2026 |
|
|
30
|
+
| [INJ-02](#inj-02---path-traversal--arbitrary-file-read) | active | high | Path traversal / arbitrary file read | MCP05:2025 (beta), ASI02 |
|
|
31
|
+
| [INJ-03](#inj-03---server-side-request-forgery) | active | high | Server-side request forgery | MCP05:2025 (beta), ASI02 |
|
|
32
|
+
| [INJ-04](#inj-04---sql-injection-safe-markers) | active | high | SQL injection (safe markers) | MCP05:2025 (beta) |
|
|
33
|
+
| [INJ-05](#inj-05---tool-output-returned-without-sanitisation-contextual-payload-path) | active | medium | Tool output returned without sanitisation (contextual payload path) | MCP06:2025 (beta), MCP10:2025 (beta), ASI06, LLM01:2026, LLM01:2025 |
|
|
34
|
+
| [SUPPLY-01](#supply-01---package-provenance-and-known-vulnerabilities-stdio) | active | medium | Package provenance and known vulnerabilities (stdio) | MCP04:2025 (beta), ASI04, LLM04:2026, LLM03:2025 |
|
|
35
|
+
| [SUPPLY-02](#supply-02---stdio-configuration-launches-risky-commands) | active | high | stdio configuration launches risky commands | MCP05:2025 (beta), MCP04:2025 (beta), ASI05 |
|
|
36
|
+
| [SANDBOX-01](#sandbox-01---unexpected-runtime-behaviour-during-listing-stdio) | active | high | Unexpected runtime behaviour during listing (stdio) | MCP04:2025 (beta), ASI10, ASI04 |
|
|
37
|
+
| GOV-01 | attestation | - | Audit logging and telemetry for tool invocations | MCP08:2025 (beta) |
|
|
38
|
+
| GOV-02 | attestation | - | Shadow MCP servers (inventory of servers in use) | MCP09:2025 (beta) |
|
|
39
|
+
| GOV-03 | attestation | - | Data and model poisoning in training or fine-tuning pipelines | LLM05:2026, LLM04:2025 |
|
|
40
|
+
| GOV-04 | attestation | - | Inter-agent communication, cascading failures, human trust, rogue agents | ASI07, ASI08, ASI09, ASI10 |
|
|
41
|
+
| GOV-05 | attestation | - | Memory and context poisoning persistence | ASI06 |
|
|
42
|
+
|
|
43
|
+
## Passive checks
|
|
44
|
+
|
|
45
|
+
### AUTH-01 - Remote MCP endpoint accepts requests without authentication
|
|
46
|
+
|
|
47
|
+
| | |
|
|
48
|
+
|---|---|
|
|
49
|
+
| Mode | passive (implemented) |
|
|
50
|
+
| Default severity | high |
|
|
51
|
+
| Transports | http |
|
|
52
|
+
| Standards | MCP07:2025 (beta), ASI03, LLM04:2026, LLM03:2026, LLM03:2025, LLM06:2025 |
|
|
53
|
+
| Evidence | The unauthenticated tools/list request and the 200 response. |
|
|
54
|
+
|
|
55
|
+
POSTs initialize (or server/discover) and tools/list with no Authorization header. If the server answers with a tool list, anyone who can reach the endpoint can drive its tools. Missing authentication was the single most common issue in public MCP server studies.
|
|
56
|
+
|
|
57
|
+
**False positives.** Servers protected by a network boundary (VPN, mTLS at a proxy, IP allow-list) will still be flagged because the scanner only sees what the endpoint returns. Local development servers bound to loopback are reported at reduced severity but are still exposed to DNS-rebinding and browser-based attacks (see CVE-2025-49596 class).
|
|
58
|
+
|
|
59
|
+
**Fix.** Put the endpoint behind OAuth 2.1 as described in the MCP authorization spec: return 401 with WWW-Authenticate pointing at RFC 9728 protected-resource metadata, validate token audience, and reject requests without a valid bearer token. For local servers, bind to 127.0.0.1 and still require a token.
|
|
60
|
+
|
|
61
|
+
### AUTH-02 - Protected resource metadata (RFC 9728) missing or invalid
|
|
62
|
+
|
|
63
|
+
| | |
|
|
64
|
+
|---|---|
|
|
65
|
+
| Mode | passive (implemented) |
|
|
66
|
+
| Default severity | high |
|
|
67
|
+
| Transports | http |
|
|
68
|
+
| Standards | MCP07:2025 (beta) |
|
|
69
|
+
| Evidence | The 401 response headers and each metadata GET with its status/body. |
|
|
70
|
+
|
|
71
|
+
On a 401 the scanner parses WWW-Authenticate for resource_metadata, then tries /.well-known/oauth-protected-resource[/path] and the host root. The document must be JSON with a non-empty authorization_servers list. Without it, conformant clients cannot start the OAuth flow and users are pushed toward pasting long-lived static tokens.
|
|
72
|
+
|
|
73
|
+
**False positives.** Servers that use a non-OAuth scheme (API keys at a gateway) will be flagged; the MCP spec still expects RFC 9728 metadata for HTTP transports.
|
|
74
|
+
|
|
75
|
+
**Fix.** Serve /.well-known/oauth-protected-resource (path-aware variant preferred) with 'resource' and 'authorization_servers', and include WWW-Authenticate: Bearer resource_metadata="<url>" on every 401.
|
|
76
|
+
|
|
77
|
+
### AUTH-03 - Authorization server metadata weak or missing (PKCE S256 / HTTPS)
|
|
78
|
+
|
|
79
|
+
| | |
|
|
80
|
+
|---|---|
|
|
81
|
+
| Mode | passive (implemented) |
|
|
82
|
+
| Default severity | high |
|
|
83
|
+
| Transports | http |
|
|
84
|
+
| Standards | MCP07:2025 (beta), MCP01:2025 (beta) |
|
|
85
|
+
| Evidence | Each metadata GET with status and body. |
|
|
86
|
+
|
|
87
|
+
For each authorization server listed in the protected resource metadata, fetches /.well-known/oauth-authorization-server (RFC 8414, path-aware) then /.well-known/openid-configuration. Flags a missing document, a code_challenge_methods_supported list without S256 (MCP clients MUST refuse to proceed), and non-HTTPS endpoints. This may make one GET to a third-party host; disable with --no-follow-as.
|
|
88
|
+
|
|
89
|
+
**False positives.** Some authorization servers support PKCE but omit code_challenge_methods_supported; per the MCP spec that is still a conformance failure for clients.
|
|
90
|
+
|
|
91
|
+
**Fix.** Publish RFC 8414 metadata with code_challenge_methods_supported including S256 and HTTPS-only endpoints. If you use a third-party identity provider, confirm it exposes the metadata document at the issuer URL you advertise.
|
|
92
|
+
|
|
93
|
+
### AUTH-04 - Server accepts a self-minted token with the wrong audience/issuer
|
|
94
|
+
|
|
95
|
+
| | |
|
|
96
|
+
|---|---|
|
|
97
|
+
| Mode | passive (implemented) |
|
|
98
|
+
| Default severity | critical |
|
|
99
|
+
| Transports | http |
|
|
100
|
+
| Standards | MCP07:2025 (beta), MCP01:2025 (beta), ASI03 |
|
|
101
|
+
| Evidence | Each probe request (token redacted) and the response status/body. |
|
|
102
|
+
|
|
103
|
+
Mints two syntactically valid JWTs the server cannot have issued (HS256 with a random scanner key, and alg=none) with a foreign issuer and audience, and presents them as Bearer tokens. Any non-401/403 answer means the server is not validating signature or audience (RFC 8707). Also presents the token in the access_token query parameter, which the spec forbids. Only self-minted tokens are used; no real credentials.
|
|
104
|
+
|
|
105
|
+
**False positives.** A proxy that strips Authorization and answers 200 for health reasons could be flagged; check the response body in the evidence actually contains an MCP result.
|
|
106
|
+
|
|
107
|
+
**Fix.** Validate the token signature against the authorization server's keys, require 'aud' to equal this server's canonical URI (RFC 8707), reject alg=none, and never read tokens from query strings.
|
|
108
|
+
|
|
109
|
+
### TRANS-01 - Origin header not validated (DNS-rebinding exposure)
|
|
110
|
+
|
|
111
|
+
| | |
|
|
112
|
+
|---|---|
|
|
113
|
+
| Mode | passive (implemented) |
|
|
114
|
+
| Default severity | medium |
|
|
115
|
+
| Transports | http |
|
|
116
|
+
| Standards | MCP07:2025 (beta) |
|
|
117
|
+
| Evidence | The POST with the foreign Origin header and the non-403 response. |
|
|
118
|
+
|
|
119
|
+
Sends a normal negotiation request with 'Origin: https://evil.example'. The transport spec says servers MUST validate Origin and return 403 on an invalid one; otherwise a web page can drive a locally running MCP server through the victim's browser (DNS rebinding).
|
|
120
|
+
|
|
121
|
+
**False positives.** If the server answers 401 before looking at Origin the check is indeterminate and no finding is raised (see scan notes). Reverse proxies that strip Origin will cause a finding against the proxied endpoint even if the application validates it.
|
|
122
|
+
|
|
123
|
+
**Fix.** Reject requests whose Origin is not on an allow-list with HTTP 403 before processing the body. For local servers also bind to 127.0.0.1 rather than 0.0.0.0.
|
|
124
|
+
|
|
125
|
+
### TRANS-02 - Unsupported MCP-Protocol-Version header not rejected
|
|
126
|
+
|
|
127
|
+
| | |
|
|
128
|
+
|---|---|
|
|
129
|
+
| Mode | passive (implemented) |
|
|
130
|
+
| Default severity | low |
|
|
131
|
+
| Transports | http |
|
|
132
|
+
| Standards | MCP spec conformance / hygiene (no OWASP item) |
|
|
133
|
+
| Evidence | The request with the bogus version header and the response. |
|
|
134
|
+
|
|
135
|
+
Sends a request with 'MCP-Protocol-Version: 1999-01-01'. The spec requires HTTP 400 (or, on 2026-07-28, an UnsupportedProtocolVersionError). Accepting any version string suggests the server ignores version negotiation entirely.
|
|
136
|
+
|
|
137
|
+
**False positives.** Pre-2025-06-18 servers never defined the header, so an older server that ignores it is noted at low severity only.
|
|
138
|
+
|
|
139
|
+
**Fix.** Validate MCP-Protocol-Version against the supported list and reply 400 when it is unknown.
|
|
140
|
+
|
|
141
|
+
### TRANS-03 - Weak, predictable or unvalidated Mcp-Session-Id
|
|
142
|
+
|
|
143
|
+
| | |
|
|
144
|
+
|---|---|
|
|
145
|
+
| Mode | passive (implemented) |
|
|
146
|
+
| Default severity | high |
|
|
147
|
+
| Transports | http |
|
|
148
|
+
| Standards | MCP07:2025 (beta) |
|
|
149
|
+
| Evidence | The initialize responses (session header) and the forged-session request. |
|
|
150
|
+
|
|
151
|
+
Collects three session IDs from repeated initialize requests and checks length, character set, Shannon entropy and sequentiality. Then sends tools/list with a random forged session ID, expecting 400 or 404. Only runs on handshake revisions that issue Mcp-Session-Id (sessions were removed in 2026-07-28).
|
|
152
|
+
|
|
153
|
+
**False positives.** Entropy is estimated from three samples, so the test is conservative: only IDs shorter than 16 characters, obviously sequential, or with very low per-character entropy are flagged.
|
|
154
|
+
|
|
155
|
+
**Fix.** Generate session IDs with a CSPRNG (at least 128 bits, e.g. UUIDv4 or 32 random bytes base64url), store them server-side, and answer 404 for unknown IDs.
|
|
156
|
+
|
|
157
|
+
### TRANS-04 - Deprecated HTTP+SSE (2024-11-05) transport in use
|
|
158
|
+
|
|
159
|
+
| | |
|
|
160
|
+
|---|---|
|
|
161
|
+
| Mode | passive (implemented) |
|
|
162
|
+
| Default severity | info |
|
|
163
|
+
| Transports | http |
|
|
164
|
+
| Standards | MCP spec conformance / hygiene (no OWASP item) |
|
|
165
|
+
| Evidence | The GET request and the first SSE event. |
|
|
166
|
+
|
|
167
|
+
Reports when the endpoint answers a GET with an SSE 'endpoint' event, i.e. the 2024-11-05 HTTP+SSE transport that was deprecated in 2025-03-26 and formally classified Deprecated in 2026-07-28. Also noted when the negotiated revision predates 2025-06-18.
|
|
168
|
+
|
|
169
|
+
**False positives.** Informational only.
|
|
170
|
+
|
|
171
|
+
**Fix.** Migrate to Streamable HTTP (single endpoint, POST per message) and current protocol revision.
|
|
172
|
+
|
|
173
|
+
### TRANS-05 - Plain HTTP, weak TLS or missing security headers
|
|
174
|
+
|
|
175
|
+
| | |
|
|
176
|
+
|---|---|
|
|
177
|
+
| Mode | passive (implemented) |
|
|
178
|
+
| Default severity | high |
|
|
179
|
+
| Transports | http |
|
|
180
|
+
| Standards | MCP01:2025 (beta) |
|
|
181
|
+
| Evidence | Response headers of the negotiation/tools/list exchange and the observed TLS version. |
|
|
182
|
+
|
|
183
|
+
Flags non-loopback endpoints served over plain HTTP (bearer tokens in clear), TLS versions below 1.2 observed on the connection, and missing Strict-Transport-Security / X-Content-Type-Options headers on the MCP endpoint responses.
|
|
184
|
+
|
|
185
|
+
**False positives.** Loopback plain-HTTP is reported as informational. Header checks look at the MCP endpoint only; a CDN may add headers on other paths.
|
|
186
|
+
|
|
187
|
+
**Fix.** Serve the endpoint over HTTPS with TLS 1.2+ only, add Strict-Transport-Security and X-Content-Type-Options: nosniff.
|
|
188
|
+
|
|
189
|
+
### META-01 - Possible tool-description poisoning
|
|
190
|
+
|
|
191
|
+
| | |
|
|
192
|
+
|---|---|
|
|
193
|
+
| Mode | passive (implemented) |
|
|
194
|
+
| Default severity | high |
|
|
195
|
+
| Transports | http, stdio |
|
|
196
|
+
| Standards | MCP03:2025 (beta), ASI01, ASI04, LLM01:2026, LLM01:2025 |
|
|
197
|
+
| Evidence | The tools/list (or prompts/resources/initialize) response and the matched excerpts. |
|
|
198
|
+
|
|
199
|
+
Scans every tool, prompt and resource description, every inputSchema parameter description and the server 'instructions' for: prompt-style markup (<IMPORTANT>, <system>), instructions aimed at the model (conceal from user, override instructions, read-and-forward, prerequisite coercion, redirect/replace), credential file paths, references to other tools with behaviour-modifying language (shadowing), URLs and e-mail addresses with send/BCC wording, base64 blobs, zero-width/bidi/tag Unicode, mixed-script homoglyphs and excessive length. Findings carry tiered confidence and are never rated Critical on heuristics alone.
|
|
200
|
+
|
|
201
|
+
**False positives.** Legitimate guidance such as 'IMPORTANT: call authenticate before this tool' matches the markup and prerequisite heuristics at medium confidence. URLs to documentation and mentions of sibling tools without behaviour-modifying words are reported at low severity. Review the matched excerpts; a second-opinion judge can be plugged in through the Python API (ScanOptions.judge); mcpprobe itself makes no LLM calls.
|
|
202
|
+
|
|
203
|
+
**Fix.** Remove any text addressed to the model rather than describing the tool. Keep descriptions short and factual, strip invisible Unicode, and never reference other servers' tools. Pin and hash approved descriptions in clients (see META-02).
|
|
204
|
+
|
|
205
|
+
### META-02 - Tool surface changed since the stored baseline (rug-pull indicator)
|
|
206
|
+
|
|
207
|
+
| | |
|
|
208
|
+
|---|---|
|
|
209
|
+
| Mode | passive (implemented) |
|
|
210
|
+
| Default severity | medium |
|
|
211
|
+
| Transports | http, stdio |
|
|
212
|
+
| Standards | MCP03:2025 (beta), ASI04 |
|
|
213
|
+
| Evidence | The current tools/list response plus per-item hashes and the diff. |
|
|
214
|
+
|
|
215
|
+
Computes SHA-256 over the canonical JSON of each tool, prompt and resource definition and the server instructions. With --baseline FILE the current snapshot is compared to the stored one and any added, removed or changed definition is reported (a changed description after approval is the classic 'rug pull'). The snapshot is then written back to the file. Also notes when the server advertises tools.listChanged.
|
|
216
|
+
|
|
217
|
+
**False positives.** Any legitimate release that edits a description will trigger the diff; the finding says what changed so the reviewer can decide. Servers that embed timestamps or random data in descriptions will change on every scan.
|
|
218
|
+
|
|
219
|
+
**Fix.** Treat tool definitions as code: version them, review changes, and have clients pin and re-approve definitions when the hash changes.
|
|
220
|
+
|
|
221
|
+
### META-03 - Tool annotations contradict the tool's apparent capability
|
|
222
|
+
|
|
223
|
+
| | |
|
|
224
|
+
|---|---|
|
|
225
|
+
| Mode | passive (implemented) |
|
|
226
|
+
| Default severity | medium |
|
|
227
|
+
| Transports | http, stdio |
|
|
228
|
+
| Standards | MCP02:2025 (beta), MCP05:2025 (beta), ASI02, ASI05, LLM03:2026, LLM06:2025 |
|
|
229
|
+
| Evidence | The tools/list response; matched terms per tool are listed in details. |
|
|
230
|
+
|
|
231
|
+
Classifies each tool by name, description and parameter names into capability classes (exec, file_write, file_read, database_*, network, email, credentials, payments, delete, search) and cross-checks the declared annotations: a tool that looks like it runs commands or sends e-mail but is marked readOnlyHint:true, or an exec/delete tool marked destructiveHint:false, is reported. A summary of the dangerous surface is reported at low severity. Annotations are treated as untrusted hints, as the spec requires of clients.
|
|
232
|
+
|
|
233
|
+
**False positives.** Classification is keyword-based: a tool named 'delete_draft' that only removes the user's own draft will be classed 'delete'. Confidence is medium for contradictions and the dangerous-surface summary is informational.
|
|
234
|
+
|
|
235
|
+
**Fix.** Make annotations truthful (readOnlyHint only for tools with no side effects, destructiveHint:true for anything that deletes or executes), and consider splitting broad tools into narrower ones so clients can gate approval.
|
|
236
|
+
|
|
237
|
+
### META-04 - Tool schema hygiene problems
|
|
238
|
+
|
|
239
|
+
| | |
|
|
240
|
+
|---|---|
|
|
241
|
+
| Mode | passive (implemented) |
|
|
242
|
+
| Default severity | low |
|
|
243
|
+
| Transports | http, stdio |
|
|
244
|
+
| Standards | MCP05:2025 (beta) |
|
|
245
|
+
| Evidence | The tools/list response. |
|
|
246
|
+
|
|
247
|
+
Checks tool names against [A-Za-z0-9_.-]{1,128} and for duplicates; checks that inputSchema is a JSON Schema object of type 'object'; flags free-form string arguments whose names suggest paths, commands, URLs or queries and that carry no enum, pattern, format or maxLength constraint. Missing outputSchema cannot be judged without calling the tool and is not reported.
|
|
248
|
+
|
|
249
|
+
**False positives.** An unconstrained 'query' string is often unavoidable (search tools); the finding is Low severity and meant as a review prompt, not a defect.
|
|
250
|
+
|
|
251
|
+
**Fix.** Use valid names, give every tool an object inputSchema, and constrain risky string arguments with enum/pattern/format/maxLength so clients and servers can validate.
|
|
252
|
+
|
|
253
|
+
### META-05 - Secret material in server metadata or configuration
|
|
254
|
+
|
|
255
|
+
| | |
|
|
256
|
+
|---|---|
|
|
257
|
+
| Mode | passive (implemented) |
|
|
258
|
+
| Default severity | high |
|
|
259
|
+
| Transports | http, stdio |
|
|
260
|
+
| Standards | MCP01:2025 (beta), LLM02:2026, LLM02:2025 |
|
|
261
|
+
| Evidence | The listing response that contained the match; values redacted. |
|
|
262
|
+
|
|
263
|
+
Pattern and entropy scan for AWS/GitHub/Slack/Stripe/Google keys, private key blocks, JWTs, bearer tokens, connection strings with passwords and generic 'key=...' assignments across tool/prompt/resource descriptions, parameter descriptions, resource URIs, server instructions and, for stdio targets, the command line and environment supplied to the scanner. Matched values are redacted in the report.
|
|
264
|
+
|
|
265
|
+
**False positives.** Example keys from vendor documentation (for instance the AWS sample key IDs ending in EXAMPLE) match the patterns. High-entropy strings are reported at Low severity and low confidence; identifiers such as content hashes trigger them. Secrets in a stdio server's environment are expected (the spec says stdio servers take credentials from the environment) and are reported as Low so the operator can confirm least privilege.
|
|
266
|
+
|
|
267
|
+
**Fix.** Remove secrets from descriptions and resources, rotate anything that was exposed, and pass credentials through the environment or a secret store, never through metadata.
|
|
268
|
+
|
|
269
|
+
### ERR-01 - Verbose error responses leak stack traces, paths or versions
|
|
270
|
+
|
|
271
|
+
| | |
|
|
272
|
+
|---|---|
|
|
273
|
+
| Mode | passive (implemented) |
|
|
274
|
+
| Default severity | medium |
|
|
275
|
+
| Transports | http, stdio |
|
|
276
|
+
| Standards | MCP08:2025 (beta), LLM02:2026, LLM02:2025 |
|
|
277
|
+
| Evidence | Each malformed request and the error response body. |
|
|
278
|
+
|
|
279
|
+
Sends three malformed requests: truncated JSON, an unknown method and a request whose params is a string instead of an object. Error bodies and the Server header are inspected for stack traces, internal file paths and framework version strings.
|
|
280
|
+
|
|
281
|
+
**False positives.** A Server header with a version is reported as Info. Framework names without versions are not reported.
|
|
282
|
+
|
|
283
|
+
**Fix.** Return generic JSON-RPC errors (-32700/-32600/-32601/-32602) without 'data' containing exceptions, log details server-side, and strip the Server header version at the proxy.
|
|
284
|
+
|
|
285
|
+
### DOS-01 - No visible limits on request size, nesting or rate
|
|
286
|
+
|
|
287
|
+
| | |
|
|
288
|
+
|---|---|
|
|
289
|
+
| Mode | passive (implemented) |
|
|
290
|
+
| Default severity | low |
|
|
291
|
+
| Transports | http, stdio |
|
|
292
|
+
| Standards | ASI08, LLM06:2026, LLM10:2025 |
|
|
293
|
+
| Evidence | The oversized/nested requests (truncated) and timing; the burst responses' statuses. |
|
|
294
|
+
|
|
295
|
+
Three bounded probes, never more: (1) one tools/list whose 'cursor' is a 1 MB string, (2) one tools/list with params nested 64 levels deep, (3) 20 tools/list requests sent at the scan rate cap (5 req/s by default). A 5xx, a transport failure or a response slower than 5 s on (1)/(2) is reported; absence of any 429 during (3) is reported as informational. No tools are called.
|
|
296
|
+
|
|
297
|
+
**False positives.** The burst runs inside the scanner's own rate cap, so 'no 429 observed' is indicative only (low confidence) and many well-run servers legitimately allow 5 req/s. A 413 or connection reset on the oversized probe is treated as a correct defence.
|
|
298
|
+
|
|
299
|
+
**Fix.** Enforce a request body limit (e.g. 1 MB) and JSON depth limit at the edge, return 413/400 promptly, and rate-limit per client/session with 429 and Retry-After.
|
|
300
|
+
|
|
301
|
+
## Active checks (stubs)
|
|
302
|
+
|
|
303
|
+
Rules of engagement for when these are implemented: non-destructive, non-persistent canaries only; tools excluded with `--exclude-tool` or annotated `destructiveHint: true` are never called; at most one concurrent tool call; every payload is recorded as evidence; the scan stops on the first sign of an unintended side effect.
|
|
304
|
+
|
|
305
|
+
### INJ-01 - Command/code injection (safe canaries)
|
|
306
|
+
|
|
307
|
+
| | |
|
|
308
|
+
|---|---|
|
|
309
|
+
| Mode | active (stub (gated, not implemented)) |
|
|
310
|
+
| Default severity | critical |
|
|
311
|
+
| Transports | http, stdio |
|
|
312
|
+
| Standards | MCP05:2025 (beta), ASI05, LLM10:2026 |
|
|
313
|
+
| Evidence | tools/call request with the canary and the timed response. |
|
|
314
|
+
|
|
315
|
+
ACTIVE, NOT IMPLEMENTED. Will call exec-class tools with time-based, non-destructive canaries and compare response timing. requires --active and verified ownership.
|
|
316
|
+
|
|
317
|
+
**False positives.** Network jitter can mimic a timing delta; the probe will repeat and require consistency.
|
|
318
|
+
|
|
319
|
+
**Fix.** Never pass tool arguments to a shell; use argument vectors and allow-lists.
|
|
320
|
+
|
|
321
|
+
### INJ-02 - Path traversal / arbitrary file read
|
|
322
|
+
|
|
323
|
+
| | |
|
|
324
|
+
|---|---|
|
|
325
|
+
| Mode | active (stub (gated, not implemented)) |
|
|
326
|
+
| Default severity | high |
|
|
327
|
+
| Transports | http, stdio |
|
|
328
|
+
| Standards | MCP05:2025 (beta), ASI02 |
|
|
329
|
+
| Evidence | tools/call request with the traversal path and the response excerpt. |
|
|
330
|
+
|
|
331
|
+
ACTIVE, NOT IMPLEMENTED. Read-only traversal probes on path-typed arguments. requires --active and verified ownership.
|
|
332
|
+
|
|
333
|
+
**False positives.** Tools that intentionally expose the whole filesystem are a design decision, not a bug.
|
|
334
|
+
|
|
335
|
+
**Fix.** Canonicalise paths, resolve symlinks, and enforce a root directory check after resolution.
|
|
336
|
+
|
|
337
|
+
### INJ-03 - Server-side request forgery
|
|
338
|
+
|
|
339
|
+
| | |
|
|
340
|
+
|---|---|
|
|
341
|
+
| Mode | active (stub (gated, not implemented)) |
|
|
342
|
+
| Default severity | high |
|
|
343
|
+
| Transports | http, stdio |
|
|
344
|
+
| Standards | MCP05:2025 (beta), ASI02 |
|
|
345
|
+
| Evidence | tools/call request with the callback URL and the callback log entry. |
|
|
346
|
+
|
|
347
|
+
ACTIVE, NOT IMPLEMENTED. Callback-based SSRF probes on URL-typed arguments. requires --active and verified ownership.
|
|
348
|
+
|
|
349
|
+
**False positives.** Fetch tools are often meant to fetch arbitrary URLs; the finding focuses on internal/metadata addresses.
|
|
350
|
+
|
|
351
|
+
**Fix.** Resolve and validate destination addresses, block link-local and private ranges, use an egress proxy.
|
|
352
|
+
|
|
353
|
+
### INJ-04 - SQL injection (safe markers)
|
|
354
|
+
|
|
355
|
+
| | |
|
|
356
|
+
|---|---|
|
|
357
|
+
| Mode | active (stub (gated, not implemented)) |
|
|
358
|
+
| Default severity | high |
|
|
359
|
+
| Transports | http, stdio |
|
|
360
|
+
| Standards | MCP05:2025 (beta) |
|
|
361
|
+
| Evidence | tools/call requests and differential responses. |
|
|
362
|
+
|
|
363
|
+
ACTIVE, NOT IMPLEMENTED. Boolean and timing markers on query/filter arguments, plus error fingerprinting. requires --active and verified ownership.
|
|
364
|
+
|
|
365
|
+
**False positives.** Tools that accept raw SQL by design are reported as a capability (META-03), not an injection.
|
|
366
|
+
|
|
367
|
+
**Fix.** Use parameterised queries; never interpolate tool arguments into SQL.
|
|
368
|
+
|
|
369
|
+
### INJ-05 - Tool output returned without sanitisation (contextual payload path)
|
|
370
|
+
|
|
371
|
+
| | |
|
|
372
|
+
|---|---|
|
|
373
|
+
| Mode | active (stub (gated, not implemented)) |
|
|
374
|
+
| Default severity | medium |
|
|
375
|
+
| Transports | http, stdio |
|
|
376
|
+
| Standards | MCP06:2025 (beta), MCP10:2025 (beta), ASI06, LLM01:2026, LLM01:2025 |
|
|
377
|
+
| Evidence | tools/call request and the returned content. |
|
|
378
|
+
|
|
379
|
+
ACTIVE, NOT IMPLEMENTED. Read-only tool calls against scanner-controlled canary content. requires --active and verified ownership.
|
|
380
|
+
|
|
381
|
+
**False positives.** Returning fetched content verbatim is normal; the finding documents the path for the client's risk assessment.
|
|
382
|
+
|
|
383
|
+
**Fix.** Mark tool output as untrusted data in content blocks and strip instruction-like markup where feasible.
|
|
384
|
+
|
|
385
|
+
### SUPPLY-01 - Package provenance and known vulnerabilities (stdio)
|
|
386
|
+
|
|
387
|
+
| | |
|
|
388
|
+
|---|---|
|
|
389
|
+
| Mode | active (stub (gated, not implemented)) |
|
|
390
|
+
| Default severity | medium |
|
|
391
|
+
| Transports | stdio |
|
|
392
|
+
| Standards | MCP04:2025 (beta), ASI04, LLM04:2026, LLM03:2025 |
|
|
393
|
+
| Evidence | Registry metadata documents and OSV responses. |
|
|
394
|
+
|
|
395
|
+
ACTIVE, NOT IMPLEMENTED. Registry metadata, OSV lookup and install-script review for the stdio package. requires --active and verified ownership.
|
|
396
|
+
|
|
397
|
+
**False positives.** Unpinned versions are common in examples; severity will depend on install-script presence.
|
|
398
|
+
|
|
399
|
+
**Fix.** Pin versions, commit lockfiles, publish with provenance attestations, avoid install scripts.
|
|
400
|
+
|
|
401
|
+
### SUPPLY-02 - stdio configuration launches risky commands
|
|
402
|
+
|
|
403
|
+
| | |
|
|
404
|
+
|---|---|
|
|
405
|
+
| Mode | active (stub (gated, not implemented)) |
|
|
406
|
+
| Default severity | high |
|
|
407
|
+
| Transports | stdio |
|
|
408
|
+
| Standards | MCP05:2025 (beta), MCP04:2025 (beta), ASI05 |
|
|
409
|
+
| Evidence | The configuration entry. |
|
|
410
|
+
|
|
411
|
+
ACTIVE, NOT IMPLEMENTED. Static review of a submitted client configuration file. requires --active and verified ownership.
|
|
412
|
+
|
|
413
|
+
**False positives.** npx -y with a pinned version is acceptable; unpinned is flagged.
|
|
414
|
+
|
|
415
|
+
**Fix.** Pin packages, avoid shell wrappers, keep secrets out of config files.
|
|
416
|
+
|
|
417
|
+
### SANDBOX-01 - Unexpected runtime behaviour during listing (stdio)
|
|
418
|
+
|
|
419
|
+
| | |
|
|
420
|
+
|---|---|
|
|
421
|
+
| Mode | active (stub (gated, not implemented)) |
|
|
422
|
+
| Default severity | high |
|
|
423
|
+
| Transports | stdio |
|
|
424
|
+
| Standards | MCP04:2025 (beta), ASI10, ASI04 |
|
|
425
|
+
| Evidence | Sandbox egress/file/process log. |
|
|
426
|
+
|
|
427
|
+
ACTIVE, NOT IMPLEMENTED. Sandboxed execution with egress and syscall logging. requires --active and verified ownership.
|
|
428
|
+
|
|
429
|
+
**False positives.** Telemetry and update checks are common; the finding will list hosts for review.
|
|
430
|
+
|
|
431
|
+
**Fix.** Do not contact the network or touch files outside the package during start-up and listing.
|
|
432
|
+
|
|
433
|
+
## Governance items (attestation only)
|
|
434
|
+
|
|
435
|
+
These cannot be assessed by an automated black-box scan. Every report lists them as `attestation-only` with the checklist below; mcpprobe never marks them passed or failed.
|
|
436
|
+
|
|
437
|
+
### GOV-01 - Audit logging and telemetry for tool invocations
|
|
438
|
+
|
|
439
|
+
Standards: MCP08:2025 (beta)
|
|
440
|
+
|
|
441
|
+
Whether a server logs and alerts on tool calls is not observable from outside.
|
|
442
|
+
|
|
443
|
+
- [ ] Every tools/call is logged with caller identity, tool name, arguments digest and outcome.
|
|
444
|
+
- [ ] Logs are shipped off-host, retained, and reviewed or alerted on.
|
|
445
|
+
- [ ] Authentication failures and authorisation denials are logged.
|
|
446
|
+
|
|
447
|
+
### GOV-02 - Shadow MCP servers (inventory of servers in use)
|
|
448
|
+
|
|
449
|
+
Standards: MCP09:2025 (beta)
|
|
450
|
+
|
|
451
|
+
An inventory problem across workstations and repositories, not an endpoint property.
|
|
452
|
+
|
|
453
|
+
- [ ] Maintain an inventory of approved MCP servers and their owners.
|
|
454
|
+
- [ ] Periodically review client configuration files (mcp.json and similar) for unapproved entries.
|
|
455
|
+
|
|
456
|
+
### GOV-03 - Data and model poisoning in training or fine-tuning pipelines
|
|
457
|
+
|
|
458
|
+
Standards: LLM05:2026, LLM04:2025
|
|
459
|
+
|
|
460
|
+
Training-pipeline integrity is not black-box testable.
|
|
461
|
+
|
|
462
|
+
- [ ] Training and retrieval data sources are provenance-tracked and access-controlled.
|
|
463
|
+
- [ ] Data changes are reviewed before they reach a model or index.
|
|
464
|
+
|
|
465
|
+
### GOV-04 - Inter-agent communication, cascading failures, human trust, rogue agents
|
|
466
|
+
|
|
467
|
+
Standards: ASI07, ASI08, ASI09, ASI10
|
|
468
|
+
|
|
469
|
+
Architecture and process items; multi-agent paths are not externally visible.
|
|
470
|
+
|
|
471
|
+
- [ ] Agent-to-agent channels are authenticated (the AUTH checks apply to any exposed endpoint).
|
|
472
|
+
- [ ] Failure of one tool or agent is contained (timeouts, circuit breakers, budgets).
|
|
473
|
+
- [ ] High-impact actions require explicit human approval with the full action shown.
|
|
474
|
+
- [ ] Agents can be stopped centrally and their credentials revoked.
|
|
475
|
+
|
|
476
|
+
### GOV-05 - Memory and context poisoning persistence
|
|
477
|
+
|
|
478
|
+
Standards: ASI06
|
|
479
|
+
|
|
480
|
+
Needs a customer-supplied test session across two conversations; not a server-side scan.
|
|
481
|
+
|
|
482
|
+
- [ ] Persistent memory is scoped per user and per tenant.
|
|
483
|
+
- [ ] Stored memories can be reviewed and deleted by the user.
|
|
484
|
+
- [ ] Content from tool output is not written to long-term memory without review.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 mcpprobe contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|