Skip to content

Security: lemur47/lemurkit

SECURITY.md

Security Policy

Reporting a vulnerability

Please report vulnerabilities privately via GitHub's security advisories: Security → Report a vulnerability on this repository (or https://github.com/lemur47/lemurkit/security/advisories/new).

Do not open a public issue for a security report. You should receive an acknowledgement within a week. Coordinated disclosure is appreciated; you'll be credited in the advisory unless you prefer otherwise.

Scope

This project is a self-hosted, single-user MCP connector. Reports of particular interest:

  • Auth-gate bypass: any way to reach /mcp tool calls, or obtain a grant, without being the allowlisted GitHub account (OAuth flow, state/CSRF handling, token issuance).
  • Cross-deployment impact: anything that lets one deployment affect another.
  • Secret disclosure: any response path that reflects secret values (the not-configured guard intentionally names missing secret names — that is by design).
  • Injection through stored content: object keys/bodies or memory fragments breaking out of their role in tool results.

Out of scope: vulnerabilities requiring the deployer's own Cloudflare or GitHub account to already be compromised; the security of Cloudflare R2/KV/D1/Workers themselves.

Deployment security notes

  • The authorized identity and all OAuth material live in Worker secrets — never commit them.
  • The allowlist pins the immutable numeric GitHub id as the primary check; the login is defence-in-depth. If you rename your GitHub account, update GITHUB_ALLOWED_USERNAME.
  • Install-time supply-chain defenses live in .npmrc (registry pin, ignore-scripts=true, 3-day release cooldown). Keep them when modifying the project.
  • OAuth state/carrier tokens are HMAC-signed and expire after 10 minutes (signed iat); a captured token stops replaying once stale. Every HTML response (consent, errors, the not-configured checklist) carries a strict CSP, frame denial, nosniff, and no-store.
  • The Worker ships no application-level rate limiting. The pre-auth endpoints (/authorize, /register, /token, /callback) are necessarily open — the MCP spec requires dynamic client registration to be unauthenticated — so an unthrottled caller can spam client records into your OAuth KV namespace (storage/cost amplification against your own account). Mitigate at the edge: put the Worker behind a custom domain on a zone you own and add a zone WAF rate-limiting rule (free plan includes one) scoped to those four paths — e.g. 10 requests / 10 s per IP, block. Do not include /mcp in the rule: it's already OAuth-gated and your MCP client calls it on every tool use. A bare workers.dev deployment has no zone, so it can't use this — Cloudflare's platform DDoS protection still applies, but not per-path throttling.

Known, accepted risks

These are documented trade-offs, not open bugs — reports about them are welcome only if you've found an escalation beyond what's described here.

  • Worker observability captures tool traffic. wrangler.jsonc ships with observability.enabled: true. Tool invocations — including object keys and, on writes, file content passed as arguments — appear in your Cloudflare account's Workers logs and live tail. This is your own account and your own data, but be aware that everything the connector reads and writes is visible there, subject to your account's log retention. Disable observability in wrangler.jsonc if you don't want this.
  • Semantic prompt injection through stored content. Tool results are JSON-encoded, so stored content cannot structurally escape its envelope — but file bodies and memory fragments flow to the model as tool results and can carry instruction-like text. Content you wrote yourself is as trustworthy as you are; content that arrived out-of-band (dashboard uploads, syncs from elsewhere) is ingested verbatim by index_bucket and should be treated as untrusted input to the model. There is no sanitizer that can distinguish "text about instructions" from instructions; the mitigation is what you put in the bucket.

Supported versions

The main branch. There are no maintained release lines; redeploy from current main to pick up fixes (pushes to your clone's production branch auto-deploy via Workers Builds).

There aren't any published security advisories