Skip to content

Security Contract

Assertions

SEC-001 - Joplin credentials never enter public output or workspace state

Contract: The Joplin token MUST be accepted only from JOPLIN_TOKEN or a token file, except that the local process mcp stdio MAY also accept the compatibility argument --token TOKEN, whose value is visible to other local processes and IDE configuration readers. Every Joplin, MCP, and Actions token file MUST be a bounded single-line regular file opened without following symlinks. On POSIX it MUST be owned by the current user with no group or other access. On Windows it MUST be owned by the current user, SYSTEM, or Administrators, and no effective allow entry of its ACL MAY give another account read, write, or permission-change rights. Rejections MUST NOT echo the file content. Every accepted form MUST be redacted from stdout, stderr, log files, and logged tracebacks and MUST NOT be stored in workspace files. Stdio stdout MUST contain only protocol messages, and stdio mode MUST NOT open HTTP interfaces or accept their bearer credentials. Authentication failure MUST not echo remote response content containing the credential.

Evidence:

SEC-002 - Remote network exposure always requires explicit authorization

Contract: Joplin API addresses outside loopback MUST require --allow-remote-api. MCP listeners outside loopback MUST require both --allow-remote-mcp and protected MCP bearer authentication. Browser-origin requests MUST pass the configured Origin policy.

Evidence:

SEC-003 - Bearer sources are strong, protected, and rotatable

Contract: MCP and Actions bearer sources MUST be token files protected as defined by SEC-001 on POSIX and Windows, not symlinks or directories, and contain one bounded URL-safe Base64 value encoding at least 256 bits. Files MUST be re-read per request and comparisons MUST fail closed for non-ASCII, malformed, oversized, or duplicate authorization.

Evidence:

SEC-004 - Filesystem inputs cannot escape or redirect traversal

Contract: Remote titles and local relative paths MUST be sanitized and checked against the workspace root. Workspace scanning and bearer-file loading MUST reject symlinks. Local replacements MUST be atomic, and destructive sync operations MUST retain backup or quarantine evidence.

Evidence:

SEC-005 - Untrusted note content is data, never executable input

Contract: Runtime modules MUST NOT invoke a shell, subprocess, dynamic eval, or dynamic exec. Note bodies, titles, tags, tool arguments, and tool results MUST be treated as data and MUST not become filesystem paths or command arguments outside their validated domain adapters.

Evidence:

SEC-006 - Public Actions logs and contracts disclose no note content

Contract: Actions audit logs MAY contain request IDs, timing, sizes, effect, status, and result class but MUST NOT contain authorization, arguments, results, note content, or backend credentials. Generated OpenAPI MUST be token-free and MUST expose only explicitly approved registry operations.

Evidence:

SEC-007 - Destructive boundaries match Joplin recovery capabilities

Contract: Sync and direct note/notebook operations MUST use Joplin trash and support restore. Tag and resource deletion MAY be permanent because Joplin has no trash API for them and MUST be marked destructive in registry metadata. Actions and MCP MUST report the actual deletion class.

Evidence: