Skip to content

Security: gautamkrishnar/TabPilot

.github/SECURITY.md

Security Policy

Supported Versions

Tab Pilot is currently in its initial release (v1). Only the latest published version receives security fixes. We do not backport security patches to older versions.

Version Supported
v1.x (latest) Yes
< v1.0 No

Reporting a Vulnerability

Please do not report security vulnerabilities through public GitHub Issues.

If you discover a security vulnerability in Tab Pilot, please disclose it responsibly using one of the following methods:

  1. GitHub Private Security Advisory (preferred): Navigate to the Security tab of this repository and click "Report a vulnerability". This keeps the disclosure private until a fix is available.

  2. Email: Send a description of the vulnerability to the repository owner. Check the GitHub profile of @gautamkrishnar for contact information.

Please include the following in your report:

  • A clear description of the vulnerability and its potential impact
  • Step-by-step instructions to reproduce the issue
  • Any proof-of-concept code, screenshots, or network captures
  • The version or commit SHA you tested against
  • Your suggested severity level (Low / Medium / High / Critical)

We will acknowledge receipt of your report within 3 business days and provide a more detailed response — including an estimated timeline for a fix — within 7 business days.

Response Timeline

Stage Target
Acknowledgement of report 3 business days
Vulnerability confirmed / dismissed 7 business days
Fix developed and reviewed Depends on complexity
Patch released and advisory published Coordinated with reporter

We will credit reporters who responsibly disclose valid vulnerabilities in the release notes and security advisory, unless they prefer to remain anonymous.

Security Considerations

Understanding Tab Pilot's security model will help identify what is and is not in scope.

Host key authentication

The host key is a cryptographically random token generated by nanoid at session creation time. It is returned to the client exactly once over HTTPS and stored in the browser's localStorage. The server stores only a SHA-256 hash of the key (hostKeyHash) — the plaintext is never persisted.

Implications:

  • There is no account system; anyone who possesses the host key can control the session.
  • If localStorage is cleared, the host loses control of their session — there is no account-based recovery mechanism.
  • The host key is transmitted as a WebSocket message payload. Ensure Tab Pilot is deployed behind HTTPS/WSS in production.

Co-host authentication

Co-hosts are invited via a separate invite key (hostInviteKey), also hashed with SHA-256 before storage. When a co-host joins, they receive their own unique host key (also SHA-256 hashed). Both the primary host key and all co-host keys are validated on every privileged WebSocket event.

Session locking

Hosts can lock a session to prevent new participants from joining. The isLocked flag is persisted in the database and enforced on the POST /api/sessions/:id/join endpoint.

URL handling and sanitization

The API validates that all URLs in the session queue — and any URL pushed via host_open_url — use the http: or https: protocol. javascript:, data:, and other protocol schemes are rejected. However, Tab Pilot does not validate the content of the URLs. The host is trusted to paste legitimate ticket URLs.

Implications:

  • A malicious host could push any HTTP/HTTPS URL to participants' browsers (including phishing pages).
  • Participants should only join sessions from hosts they trust.
  • Browser popup blockers may prevent automatic tab opening — this is a known limitation, not a vulnerability.

Session expiry

Sessions expire after a configurable period (1–30 days). Expired sessions are automatically purged from MongoDB via a TTL index on the expiresAt field.

Rate limiting

The API does not currently implement request rate limiting on session creation or joining endpoints. Running Tab Pilot on the public internet without a reverse proxy (nginx, Caddy, Traefik) that enforces rate limits is not recommended for production deployments.

WebSocket CORS

The WebSocket gateway in development uses cors: { origin: '*' }. In production, the CORS origin should be restricted to the FRONTEND_URL environment variable. Ensure FRONTEND_URL is set correctly in production deployments.

Container security

The production container runs as UID 1001 (non-root) on a RHEL UBI9 minimal base image. No package manager, curl, or wget is present in the runner stage. The container health check uses a Node.js one-liner rather than external tools. If deploying on Kubernetes, set readOnlyRootFilesystem: true in the security context where possible.

Known Limitations

The following are known design limitations in v1, not security vulnerabilities:

  • localStorage-only host authentication: There is no server-side account system. Host keys cannot be rotated or recovered without ending the session.
  • Vote storage: Votes and revealed indices are persisted to the session document in MongoDB. Saved story point averages are stored as a map keyed by URL hash. In-memory voting state (current round) is lost on server restart, but saved/revealed votes survive.
  • No transport encryption at the application layer: Tab Pilot relies on HTTPS/WSS at the transport layer. Deploy behind a TLS-terminating reverse proxy in production.
  • Popup blocker interference: Browsers may block automatically opened tabs. Participants may need to allow popups for the Tab Pilot origin.

There aren't any published security advisories