Skip to content

Security: hkrlogic/MCPEncode

SECURITY.md

Security policy

MCPEncode stores the facts an organization trusts its agents with, so security reports are taken seriously.

Reporting a vulnerability

Please do not open a public issue for a security problem.

Report it privately through GitHub: Security → Report a vulnerability on this repository (private vulnerability reporting). Include:

  • what an attacker can do, and what they need first (an account, a Reader key, network access);
  • steps to reproduce, or a proof of concept;
  • the version or commit you tested.

You can expect an acknowledgement within 7 days. This is a spare-time project, so a fix may take longer; you'll be kept informed, and credited in the advisory unless you'd rather not be.

Supported versions

Version Supported
main / latest 0.x release Yes
Older releases No

Scope

In scope: the publisher web app, the MCP server, authentication and access control, the publish gate, Reader keys, and anything that lets an agent read unpublished items, write without permission, or reach another library.

Out of scope: running with the example or placeholder secrets, exposing the built-in sign-in to the internet without TLS, and issues in third-party services (Postgres, your MCP client) — report those upstream.

Deployment hardening

  • Run scripts/init-env.sh to generate secrets. The app refuses to start with a placeholder SESSION_SECRET.
  • The default bind is 127.0.0.1. Put MCPEncode behind a TLS-terminating reverse proxy before exposing it, and set PUBLIC_BASE_URL to the https:// origin.
  • Responses carry an enforced Content-Security-Policy with script-src 'self' (no inline script or handlers, no framing, no third-party loads), nosniff, and HSTS on HTTPS. On an HTTPS address cookies are Secure and __Host- prefixed. Password hashes use scrypt at 64 MiB per hash, at most 2 at once, and older hashes are upgraded at sign-in.
  • Sign-in misses back off per username and address, per address, and per username across addresses; nothing is hard-locked, so an attacker cannot lock the SA out. Set TRUST_PROXY behind a proxy (off by default) and add a per-address limit at the proxy. See docs/deploy.md.
  • The first account always needs a setup code. Every deploy should set SETUP_TOKEN (16+ characters) before it is reachable; otherwise a one-time code is printed to the server log at first start. See docs/deploy.md.
  • MCP clients register their own client id. Only loopback and app-scheme callbacks are accepted by default; add hosted clients' hostnames to OAUTH_REDIRECT_HOSTS (for example claude.ai); there is no setting that accepts every https host. Every MCP sign-in shows a consent page with the client, callback host and library.
  • Refresh tokens rotate, are stored hashed, and a reused one revokes its sign-in. Sign-out and a password reset sign the account out everywhere. A sign-in ends 30 days after it started.
  • Remote Postgres must use POSTGRES_SSL=required.
  • Library MCP routes allow MCP_RATE_LIMIT_PER_MINUTE requests per client address per minute (default 300, 0 off) and answer 429 with Retry-After past that. The address follows TRUST_PROXY. See docs/deploy.md.
  • Treat each library's Connect link and Reader key as secrets. Rotate them from the publisher UI if they leak. Prefer X-Library-Token for clients that can set headers, and keep /libraries/*/mcp/* out of proxy logs.
  • With AUTH_MODE=oidc, give library MCP its own audience (AUTH_MCP_AUDIENCE) so web sign-in tokens cannot open MCP.

There aren't any published security advisories