Mursil Documentation

Security

Mursil carries identity mail, invitations, payment notices, and other messages that affect account access. Treat that as an account-security surface, not as a marketing tool that happens to send HTML.

Controls that are in the product

  • Portal authentication is OIDC. There is no local user database to dump.
  • Roles are least privilege. Viewer can read health. Template editing, provider changes, and delivery actions are separate policies.
  • Tenant and application scope are part of authorization and of queries. A new endpoint has to opt in.
  • Provider credentials are references (env: or secret:). Raw secrets do not belong in portal fields, logs, or suppression import.
  • Status and integration events redact the recipient. Attachment bytes stay in the database. Accepted events do not carry the file.
  • Idempotency stops a retry storm from sending a second security mail.
  • Provider callbacks are signed (X-Mursil-Provider-Signature, X-Mursil-Provider-Timestamp).
  • Preference and tracking links are HMAC-signed. Security mail is excluded from the public preference center.
  • High-risk template keys go through review before publish. Published versions are immutable, so a sent message can be explained later.
  • Operator actions are audited.
  • Integration events use a transactional outbox. Mursil does not hand the payload to an outside broker inside the request.

Mursil:Edition can cap applications, failover, and extra providers. Unset means those gates are open. There is no usage billing in this repository.

Controls that are not done

Chapter 39 names work that needs people and environments this repository does not contain:

  • A formal third-party security assessment.
  • Browser smoke of the portal against a real OIDC authority.
  • Production-scale load.

Staging and production host design is out of scope. Do not read the local demo issuer, the demo password, or Mailpit as a production control.

Data handling for operators

DataHandling
Recipient address on sendAccepted, then omitted from status and from integration events.
Rendered bodyNot returned by the status API.
Provider secretEnvironment or secret store. The portal stores the reference.
Suppression rowrecipientHash, scope, and reason.
AttachmentBytes in MessageAttachments. Metadata only on the event.
AuditWho did the operator action. Not a copy of the mail.

SQL stays parameterized through EF Core. Do not build SQL by concatenating strings. Do not log tokens, passwords, or raw recipient addresses.