Skip to content

Security: MSK-Scripts/mskanban

SECURITY.md

Security Policy

MSKanban is a zero-knowledge end-to-end encrypted Kanban board. The threat model and our defence-in-depth posture are described in docs/threat-model.md. This file covers how to report security issues and how to verify the artefacts we ship.

πŸ“¬ Reporting a Vulnerability

Please do not open a public GitHub issue for security problems.

Report privately, in this order of preference:

  1. GitHub Private Vulnerability Reporting β€” github.com/MSK-Scripts/mskanban β†’ Security β†’ Report a vulnerability.
  2. E-mail β€” security@msk-scripts.de. Please encrypt sensitive details with our PGP key (fingerprint in .well-known/security.txt; the same key is published at https://msk-scripts.de/.well-known/security.txt).

Include, where possible:

  • Affected version / commit SHA.
  • A minimal reproduction (preferably as a self-contained Docker invocation against the dev compose stack).
  • Your assessment of impact (auth bypass? plaintext exposure? DoS?).
  • Whether the issue is already public (e.g. an upstream CVE we ship).

What to expect

Time after report What we'll do
48 h Acknowledge receipt, assign a tracking issue (private).
7 days First triage: severity, affected versions, planned timeline.
30 days Targeted fix in a private branch.
≀ 90 days Coordinated disclosure: patched release + GHSA advisory.

We may need longer for complex cryptographic findings or for issues that require coordinated upstream fixes (e.g. libsodium, Next.js). We'll keep you posted weekly when that happens.

Out of scope

  • Attacks requiring a malicious server-side admin to decrypt user content. Per ADR 0003 (Zero-Knowledge E2EE), this is by design impossible without a separate key-compromise primitive.
  • Issues that require physical access to a user's unlocked device.
  • Vulnerabilities in third-party hosted instances. Report those to the operator first.
  • Self-XSS that requires the user to paste attacker-controlled content into devtools.

Safe-harbour

We won't pursue legal action against good-faith research that:

  • Stays within the scope above.
  • Uses your own data (and your own self-hosted instance for destructive tests).
  • Avoids exfiltrating other users' data and gives us a reasonable window to fix before public disclosure.

πŸ” Verifying Released Artefacts

Every tagged release ships three independently verifiable artefacts.

1. Container image signature (Sigstore / Cosign, keyless)

We sign every pushed image with cosign sign --yes under GitHub's OIDC issuer β€” there is no long-lived signing key to compromise. To verify:

cosign verify ghcr.io/msk-scripts/mskanban:<tag> \
  --certificate-identity-regexp \
    'https://github.com/MSK-Scripts/mskanban/\.github/workflows/release\.yml@refs/tags/.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

A valid signature means the image was built by this repository's release.yml workflow from a v*.*.* tag.

2. SLSA build provenance

Generated automatically via actions/attest-build-provenance. View on the release page's Sigstore tab, or:

gh attestation verify oci://ghcr.io/msk-scripts/mskanban:<tag> \
  --owner MSK-Scripts

3. Software Bill of Materials (CycloneDX + SPDX)

Each release includes two SBOM files generated from pnpm-lock.yaml by Syft (via anchore/sbom-action):

  • sbom.cdx.json β€” CycloneDX 1.x JSON. Feed into Dependency-Track, Trivy, Grype, etc.
  • sbom.spdx.json β€” SPDX 2.3 JSON. Required by some compliance workflows (LF, FedRAMP).
gh release download <tag> -p 'sbom.*.json'

# Match against known CVEs:
grype sbom:./sbom.cdx.json

πŸ”‘ Cryptographic Hygiene

We treat the following as inviolable:

  • Master Keys never leave the user's device, never hit the network, and are never serialised to durable storage. The session envelope in sessionStorage uses an in-memory wrap key β€” see src/lib/crypto/mk-session.ts and ADR 0009.
  • Argon2id is the only password KDF. No bcrypt, no pbkdf2, no unsalted SHA-* for credentials. Memory and time parameters live in one place; bumping them is a single-PR change.
  • XChaCha20-Poly1305 is the only application-level AEAD. Nonces are sourced exclusively from crypto.getRandomValues. The lint config forbids Math.random() for any code under src/lib/crypto.
  • Crypto code has 100 % line coverage, enforced in CI by pnpm test:crypto -- --coverage.

If a contribution touches anything under src/lib/crypto, please mention ⚠️ Crypto-relevant β€” needs review in the PR description so two maintainers look at it.

πŸ“œ Past Advisories

See the Security tab for the chronological list of patched issues.

β€” Maintainer: Moritz Kohm (@musiker15).

There aren't any published security advisories