# CopyCat MCP security — v1.0.0

Public, read-only reference access is deliberate. There is no authentication or
write capability in v1. It cannot access a client computer, shell, filesystem,
administration API, arbitrary URL, model API, or credential store. The Worker has
only an asset-read binding and a Cloudflare rate-limit binding. Build/deploy
scripts run locally and are not exposed as tools. No execution endpoint exists.

## Enforced boundaries

- HTTPS required outside loopback. Explicit Host validation plus the service's
  own workers.dev hostname pattern. Exact endpoint paths only; unknown/admin/data
  paths return 404, unsupported methods 405. Arbitrary client URLs are not fetched.
- Every present Origin must exactly match configured scheme/host/port. Opaque,
  malformed and unknown Origins return 403. Origin-less non-browser clients work.
  Cloudflare handler Origin checks are explicitly delegated to this stricter
  middleware; CORS is reflected only after validation. New browser Origins must
  be explicitly reviewed/configured. CORS is not authentication.
- Zod strict input objects reject extra properties; article IDs are 1–12 digits;
  queries/issues max 512 characters; filters/error codes max 120; limit integer
  1–20. No caller-controlled asset paths or URLs.
- Request body max 16 KiB, including bodies without Content-Length. JSON only,
  valid UTF-8, no JSON-RPC batches. Ten-second request deadline, five-second asset
  read deadline. Oversized requests return 413; unexpected failures are sanitized.
- Tool JSON data max 96 KiB. Structured data and text fallback can duplicate this
  data; total transport response cap is 256 KiB. Oversized tool results return
  `RESPONSE_TOO_LARGE` rather than silently truncating command text. Use smaller
  search/related limits or command retrieval to reduce result size.
- Required Cloudflare rate-limit binding: approximate 120 requests/60 seconds per
  trusted CF-Connecting-IP and Cloudflare location, including discovery/health/
  preflight requests. Missing binding fails closed (503); denied quota returns 429
  with Retry-After: 60. Shared NAT users share quota. This is abuse resistance, not
  a strict global billing quota; Cloudflare counters are eventually consistent.
- Public exports exclude explicit private/internal/draft/admin/unpublished flags.
  Normalization allowlists fields and drops local admin state. Generated assets
  contain no raw source packs, configuration, credentials, or arbitrary files.
  New articles without publication flags retain the existing public-source
  semantics; do not put private documents into `database_source.js`.

## Untrusted content and command safety

All article text, source labels, commands and snippets are untrusted reference data.
They remain structured fields, never dynamic prompts, executable code, transport
configuration, HTML, or server instructions. Server instructions explicitly prohibit
obeying embedded instructions. Exact command text is preserved and not repaired.
Unknown environments/purposes/prerequisites remain null; recorded risk/admin/restart
metadata is retained. Article warnings accompany command retrieval. This boundary
prevents server-side execution or permission changes, but cannot guarantee that an
external AI client will resist every prompt injection. Clients must maintain their
own instruction hierarchy, approval policy and sandbox.

Verify OS, product, firmware, model, maintenance authorization, backup/redundancy,
and official vendor guidance before disruptive operations. Troubleshoot results
are references with potential causes, not verified diagnoses or tested fixes.

## Privacy and operational controls

No request bodies, search queries, conversation contents, IPs, or tool outputs are
written by application logging or storage. Wrangler observability is disabled in
tracked configuration. The hosting provider necessarily processes connection
metadata and temporary rate-limit counters; account-side logging, WAF and retention
must be reviewed by the operator. Users must not submit secrets or transcripts.
Local Wrangler dev logs request paths/status for development.

Deploy only the selected Worker subdirectory/assets, not the repository as Worker
assets. Keep `.env*`, `.dev.vars*`, `.wrangler/`, node_modules and build artifacts
ignored. No production credentials belong in Git. Commit dependency lockfile,
review updates, and run `pnpm audit --prod` before rollout. Do not enable Cloudflare
interactive bot challenges on MCP routes: non-browser clients cannot solve them.

Future private/write APIs require a separate deployment and OAuth resource server:
scoped permissions, consent, token validation/audience isolation, least privilege,
audit retention and a distinct write-tool boundary. Do not add a hidden admin mode
to this public endpoint or treat Origin as authorization.

References: [Cloudflare rate-limit semantics](https://developers.cloudflare.com/workers/runtime-apis/bindings/rate-limit/),
[Cloudflare MCP Origin policy](https://developers.cloudflare.com/agents/model-context-protocol/apis/handler-api/).
