Files
klarbild-oss/SECURITY.md
T
tillandClaude Opus 5 e2481139a1
CI / check (push) Has been cancelled
Klarbild 1.0.0 — first public release
A self-hosted print studio: images at exact physical sizes, sheet layout with
crop marks, tiling, 1:1 PDF. Everything else — image generation, delivery,
share links, mail, Telegram — is an optional module that is off by default.

This is the neutral public twin of a private tool. Compared to that original:

- optional modules behind KLARBILD_MODULES; the default install is print-only
- English interface with German as a full second language (1,038 strings);
  the English sentence is the translation key
- no built-in accounts — first boot creates one admin from ADMIN_USERNAME /
  ADMIN_PASSWORD, or generates a password and logs it once
- delivery and backup targets are generic SFTP/FTPS endpoints, off by default
- English routes, English identifiers, English comments throughout
- two compose files: print-only by default, everything in the full one
- AGPL-3.0, CI (build, tests, type check, secret scan), CONTRIBUTING, SECURITY

124 tests green, type check clean, verified end to end against a live instance.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nh4A79bbqT9dcd2inzYUdg
2026-09-15 14:52:41 +00:00

2.0 KiB

Security

Reporting a vulnerability

Please do not open a public issue. Mail security@heidrich-digital.de with what you found and how to reproduce it. You will get an acknowledgement within a few days. There is no bounty programme — this is a one-person project — but credit in the release notes is yours if you want it.

What Klarbild already does

  • Passwords are hashed with argon2. Stored credentials (SMTP, delivery targets, API keys) are encrypted with AES-256-GCM using ENCRYPTION_KEY, never written in plain text.
  • Sessions are a signed cookie plus a server-side check. Changing a password or a role invalidates every open session; the role comes from the database, not from the cookie.
  • Content-Security-Policy with per-script hashes rather than 'unsafe-inline', set at build time. style-src keeps 'unsafe-inline' because React writes styles as element attributes, which cannot be hashed — a narrower class of problem than script injection, which stays closed.
  • Remote paths are validated immediately before writing, not somewhere upstream: posixpath.join('/customers/acme', '../../../etc/cron.d') is /etc/cron.d, and the upload would have created the directory first. See safeSegment in src/lib/remotetarget.ts and its tests.
  • Share links: expiry, revocation, optional argon2 passphrase with a rate limit, noindex, and access bound to the link rather than to the image. Visit logging hashes the IP with a server secret and the link id, keeps one row per visitor per hour, and deletes after 90 days.
  • A module that is switched off returns 404, not 403.

What it does not do

  • There is no multi-tenant isolation. Every account on an instance is on the same instance; roles are user and admin and that is the whole model.
  • Klarbild expects to run behind a reverse proxy that terminates TLS. It does not do TLS itself.
  • ENCRYPTION_KEY has no rotation path yet. Losing it means re-entering the stored credentials.

Supported versions

The latest release. There is no long-term support branch.