Skip to content

Security: pickbitsai/pickbits-booking

SECURITY.md

Security policy

Report vulnerabilities privately through GitHub private vulnerability reporting on this repository. Include the affected version, Node/OS versions, expected behavior and a minimal synthetic reproduction. Never attach real customer data, private calendar URLs, SMTP credentials or signed appointment links. Version 0.1.0 and the latest default-branch code are the supported versions.

Trust boundaries

Customer input, SMTP responses and calendar content are untrusted. Text is escaped for HTML, email and iCalendar; fields, bodies and headers are bounded. No customer input is run as code, interpreted as a filesystem path, or passed to a shell. Nodemailer is the only runtime dependency; its file/URL attachment access is disabled. TLS is required for real SMTP.

Configuration, environment variables, the local data directory and the machine account running Node are trusted owner inputs. Private calendar URLs authorize outbound HTTPS requests and are not customer-editable. This is not an SSRF sandbox for untrusted administrators. Only demo mode accepts local calendar files. Redirects are disabled, request duration/response size are bounded, and unsupported calendar recurrence closes availability.

The HTTP listener binds only to loopback port 4207. Terminate HTTPS at a reverse proxy and set the public origin correctly. POSTs require an exact matching Origin; only requests with no Origin and Sec-Fetch-Site: same-origin use the fallback. Empty, null and mismatched Origins are rejected even with same-origin Fetch Metadata. Form encoding, a body under 16 KiB, and per-IP limits are also required. No forwarding headers are trusted by default. If enabling trustProxy, the loopback proxy must replace X-Forwarded-For with one verified client IP. Avoid exposing the raw listener. The application has no telemetry or runtime external assets.

Authentication and private records

Owner passwords use salted scrypt with N=32768, r=8 and p=1. Signed owner sessions have a twelve-hour expiry, HttpOnly/SameSite=Strict cookies and Secure on HTTPS. Password or HMAC rotation invalidates sessions after restart. Logout clears the current browser cookie; stateless signed sessions cannot revoke a stolen cookie individually.

Customer management links use random identifiers, expiring HMAC signatures and a separate token scope. They reveal appointment details to anyone holding them. The private owner feed uses an independent random environment token, checked with timing-safe comparison. Rotating it invalidates old subscriptions after restart. Do not place any of these links in public logs or analytics. Responses are no-store and use Referrer-Policy: same-origin, allowing browser forms to preserve their Origin while withholding referrers from other origins. Frame protections and a CSP exclude framing and inline scripts.

Booking records contain customer contact details, notes, question answers and consent timestamps. Keep data/config/env outside public web roots; the server serves only its two allowlisted assets. File permissions are restrictive where the OS supports them; configure Windows ACLs and host access controls yourself. Keep private backups and choose a retention policy appropriate for your business. No data-retention automation is supplied.

Persistence and notifications

One queue serializes every mutation and rechecks conflicts. A lock excludes a second serving process; local storage and one replica are required. JSON replacement is atomic after flushing its temporary file. Do not delete a live process's lock. After a crash, verify it ended before removing server.lock. Do not edit JSON during operation.

External calendars are cached; external edits can race with booking and are not reserved by this application. Expired or unsupported feeds fail closed. Email failures never discard appointments. The journal records sending, successful SMTP acceptance, failures and reminder claims. No automatic send retries occur. Persisting a reminder claim before delivery prevents restart duplicates but can lose a send if the process fails at that point. Inspect admin delivery records for failures or interrupted attempts.

Public repository hygiene

Only synthetic data belongs in this repository. .gitignore excludes local configuration, secrets files, booking/demo data, outboxes, dependencies, caches and build output. Leakscan checks every text file outside generated/private directories for private identities, paths, credential shapes, non-synthetic phones and non-example email domains. Tests construct negative fixtures from fragments so those fixtures do not publish forbidden literal data.

Run npm run preflight before release. Unit tests prohibit networking and port binding. The clean-consumer gate installs from the local npm cache offline and does not serve HTTP. Keep Node and Nodemailer patched.

There aren't any published security advisories