40 lines
8.3 KiB
Markdown
40 lines
8.3 KiB
Markdown
# Security and privacy
|
|
|
|
This is a local Linux stdio MCP for selected Nextcloud calendars. Its scope is reading events, creating non-recurring events and conditionally editing supported fields. It does not implement deletion, scheduling, invitations, arbitrary HTTP requests, raw ICS submission or remote credential enrollment.
|
|
|
|
## Protected storage
|
|
|
|
Password-protected storage is the recommended enrollment path. The existing default collection in the selected Secret Service provider should be encrypted with a nonempty password. Trusted local setup recognizes selected GNOME Keyring file headers where the running provider, collection identifier and owned regular file can be mapped unambiguously. Only a bounded header is read. Known textual storage is reported as unprotected. Encrypted KWallet format is recognized as evidence of encryption but cannot establish that its password is nonempty. Unknown formats, paths and providers remain unverified; no master-password test or decryption is attempted. Header recognition is not an attestation against compromised services, filesystem contents or concurrent backend changes, and does not establish password strength.
|
|
|
|
Where automatic verification is unavailable, setup offers concrete steps in the native wallet manager and a plain acknowledgement that the user set a password. This is not cryptographic verification. It also permits an explicit, default-off override for unavailable verification or known unprotected storage. These cases have different labels and are repeated on the final review. **An unprotected backend can save the secret payload in plaintext.** This is an explicitly accepted backend risk; it does not introduce an application credential fallback to files, YAML, arguments or environment variables. The internal enrollment API separately requires explicit consent to bypass its verified-storage requirement. MCP tools cannot enroll credentials or select an override. Use a known maintained keyring backend and its native manager. The application refuses unencrypted Secret Service IPC sessions, missing profiles, locked collections and unavailable services. It has no file, environment or command-line credential fallback.
|
|
|
|
The read-only wallet inventory reads D-Bus service availability and checks only default-collection metadata and encrypted IPC. It does not retrieve items/secrets, create collections, unlock wallets or start inactive providers. Desktop environment hints only choose a recommendation, never the runtime credential destination. The user explicitly chooses among multiple detected providers. Named GNOME/KDE providers use their own service aliases; older KDE aliases remain supported when they provide the Secret Service API. Each operation resolves the selected service once and binds to that unique D-Bus owner, preventing an in-flight generic-provider change from splitting one operation across wallets. An otherwise unnamed provider is checked against its executable identity before secret access. These checks prevent accidental provider changes; they do not establish integrity against a compromised same-user process.
|
|
|
|
A restricted per-profile preference file contains only a provider identifier and optional executable identity. It never contains Nextcloud connection data, credentials or calendar data. Generated Hermes configuration explicitly carries the same nonsecret selection. Unavailable selected providers and commands relying on corrupt preferences fail; there is no fallback to another wallet. Explicit configuration can recover a known selection independently of the preference file. Existing configurations created before selection existed retain the previous generic provider behavior. Enrollment does not itself change desktop-wide keyring configuration or migrate/delete secrets in other wallets. The trusted wizard can open the native manager after the human chooses help; the human configures/unlocks the wallet there. Runtime never starts or unlocks a wallet.
|
|
|
|
Only a generic application identifier and nonsecret profile name appear in keyring attributes. URL, username, app password, calendar paths/names/permissions, timezone and optional CA path are within the secret payload. Profiles are reloaded at each tool operation, not retained globally. Password entry must be hidden; visible-input fallback fails. Existing profiles are replaced only after successful discovery and final human confirmation. Cancellation before saving leaves the existing profile unchanged. Nextcloud account/sharing/2FA instructions are local help, not automated server administration. Automatic Hermes registration uses its preserving configuration writer for one credential-free entry, refuses conflicts, and verifies tool discovery without calendar calls. Partial outcomes are reported without raw backend or CLI output.
|
|
|
|
Plaintext necessarily exists in process memory while using credentials. Python cannot ensure zeroization. An unlocked keyring is accessible to other same-user programs, including host-agent tools. Privileged inspection, swap, core dumps, a compromised keyring/OS/interpreter/dependency or a malicious administrator remain outside the application boundary. Consider a separate OS account and managed service if same-user isolation is required.
|
|
|
|
## Network and write boundaries
|
|
|
|
Authenticated requests use verified HTTPS and configured certificates, never an insecure TLS switch. Redirects and ambient proxy configuration are disabled. Destinations are restricted to the enrolled origin, calendar collections and direct resources; setup discovery is limited to the configured calendar home. URL userinfo, query/fragment, traversal and ambiguous encodings are refused before authentication. Only PROPFIND, REPORT, GET and conditional PUT are available. Calendar attachments/links are never fetched. There is no listening network port.
|
|
|
|
Byte, occurrence and date-window limits protect the client. XML rejects DTDs/entities/external references. Compressed calendar response bodies are refused to avoid unbounded decompression; unused write acknowledgement bodies are not consumed. HTTP and DAV property statuses are checked explicitly. Expected failures return fixed redacted errors; no raw provider responses, headers, profiles or tracebacks are forwarded. Runtime file logging is unavailable.
|
|
|
|
Creates use generated UIDs and `If-None-Match: *`. Edits use full original resources and `If-Match` with a strong revision, retaining unrelated properties/components. Invitation-managed resources and unsupported recurrence changes fail safely. Writes are never automatically repeated. A timeout/cancellation after a write starts can leave an unknown outcome: read before attempting another write.
|
|
|
|
Use a dedicated Nextcloud account with only the selected shared calendars, plus a dedicated revocable app password. A primary-account app password is not calendar scoped. Nextcloud write permission includes deletion authority even though this MCP omits deletion. Local allowlisting limits this application, not the account's underlying rights.
|
|
|
|
## Calendar data and the host
|
|
|
|
No event bodies, local indexes, sync state or caches are persisted by this application. Calendar text is untrusted data. It is never executed or used to change configuration. Listing returns minimal summaries; detailed reads disclose descriptions and locations to the calling session. The MCP cannot prevent a host language model from being influenced by returned text.
|
|
|
|
Returned data may enter Hermes history, memory, logs and its model provider. Those systems' retention and access controls are outside this project. The setup guide requires reviewing host privacy settings before activation. This application does not silently change them.
|
|
|
|
## Verification and reporting
|
|
|
|
Offline tests use synthetic profiles/calendar fixtures and mocked HTTPS responses, including actual SDK stdio and legacy protocol negotiation. They cannot prove a particular deployment's encryption at rest, permissions, reverse-proxy behavior or live Nextcloud compatibility. Perform the disposable-calendar checks in [the setup guide](docs/setup.md) privately.
|
|
|
|
Do not post credentials, private URLs/usernames, calendar exports or logs containing personal information in public issues. Use a private vulnerability reporting channel if the repository maintainer provides one. Otherwise, avoid posting exploitable details publicly until a private reporting channel is established. Revoke any exposed app password promptly; deleting a local profile does not revoke it.
|