> ## Documentation Index
> Fetch the complete documentation index at: https://docs.riftmap.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Security

> Riftmap security: how to report a vulnerability, how scanned source code and tokens are handled, plus our auth design, GDPR data export, and audit history.

## Reporting a vulnerability

If you've found a security issue in Riftmap, please **disclose it privately** rather than posting it publicly.

Email **[hello@riftmap.dev](mailto:hello@riftmap.dev)** with reproduction steps and any relevant version, request, or environment info. We aim to acknowledge within two business days.

<Card title="Email security disclosures" icon="envelope" href="mailto:hello@riftmap.dev">
  Goes straight to maintainers. Please use this channel rather than opening a public issue anywhere.
</Card>

### What's in scope

* The hosted product at `app.riftmap.dev`, its API at `api.riftmap.dev`, and the marketing site at `riftmap.dev`
* The static schema and docs at `docs.riftmap.dev` and `app.riftmap.dev/openapi.json`

### What's out of scope

* Reports based purely on automated scanner output without a working proof‑of‑concept
* Volumetric DoS / brute-force findings against the hosted product (we have rate limits; please don't try to find their thresholds)
* Issues that require a privileged position the attacker shouldn't have (e.g. "if I steal an owner's API key, I can act as that owner")
* Social engineering of staff or customers

### What we'll do

1. Acknowledge the report.
2. Triage and confirm the issue, or push back with reasoning.
3. Develop and ship a fix; coordinate disclosure timing with you.
4. Credit you in release notes if you'd like (and if the fix is shipped).

We don't currently run a paid bug-bounty program, but we do appreciate the work and will say so publicly when a fix lands.

## What Riftmap does with your data

Short version:

* **Source code is never stored.** Repos are shallow-cloned (depth=1) into a per-scan temporary directory at `0700` permissions, parsed for dependency manifests, and `rmtree`'d in a `try/finally`. Only the dependency graph metadata persists in the database.
* **Scanned repos are treated as hostile input.** Clones run with symlinks disabled (`core.symlinks=false`) and the file walks skip symlinks and never read outside the clone tree — a malicious repo can't point the scanner at `/etc/passwd` or the worker's environment. Working trees above a total size cap are rejected before parsing.
* **The scan worker can't be aimed at internal networks.** Every organisation URL and clone URL must be public `https://` — hosts resolving to private, loopback, link-local, or cloud-metadata addresses are rejected at registration (422) and re-checked at connect time. Upstream error bodies are never echoed into scan results.
* **Contributor data is opt-in.** The ownership / bus-factor signal is off by default. When a workspace enables it, Riftmap extracts contributor names and emails from git **author metadata only** (no commit messages, diffs, or file blobs) to compute a per-repo bus factor. This personal data is workspace-scoped and cascade-deleted on workspace deletion and the 30-day GDPR purge; the API ever returns contributor **names only**, never emails.
* **Tokens are encrypted at rest** with Fernet. The encryption key lives in env (`ENCRYPTION_KEY`) and is required at startup outside dev mode.
* **Cross-workspace isolation** is enforced at every endpoint: workspace API keys can't reach another workspace's data, and foreign-workspace requests return 404 (not 403, to avoid leaking existence).
* **GDPR data export** is available at `GET /workspaces/{id}/export` (owner/admin only). Account deletion is at `POST /auth/account/delete` with a 30-day grace period.

## Auth design (one-pager)

| Surface          | Auth                                                    | Notes                                       |
| ---------------- | ------------------------------------------------------- | ------------------------------------------- |
| Browser sessions | JWT cookies (15-min access, 30-day refresh, `HttpOnly`) | Set by `/auth/login` and OAuth callback.    |
| API integrations | Workspace API keys (`rfm_live_…`)                       | SHA-256 hashed at rest; raw key shown once. |

Mutations are rate-limited per identity. Cross-workspace access returns 404. Configuration mutations — registering a connected org, triggering a scan, creating or rotating API keys — require the **Owner or Admin** role for session users (workspace API keys are owner-equivalent by design). Password-reset links are single-use, and login timing is constant for unknown emails. See [Authentication](/authentication) for the header conventions and limit specifics.

## Responsible exposure decisions

We deliberately:

* **Disable live `/openapi.json` and `/docs` in production** — agents read the static schema published from CI at [`app.riftmap.dev/openapi.json`](https://app.riftmap.dev/openapi.json), which is reviewed and exported deliberately rather than auto-introspected from a running prod server.
* **Return 404, not 403, for cross-workspace requests** — so attackers can't enumerate which workspace IDs are real.
* **Return rate-limit errors with a precise `Retry-After`** rather than silently dropping requests — predictable behaviour beats opaque failure.

If you find a place where these defaults haven't been applied, that's exactly the kind of report we want.

## Audit history

Riftmap goes through recurring full-codebase security audits — most recently **April 2026** and **July 2026** — covering the backend, the scanner pipeline (untrusted repository content), the frontend, dependencies, and infrastructure. Every finding is remediated with an accompanying regression test, and the complete remediation records are public:

* [July 2026 audit & remediation record](https://github.com/DanielWestgaard/Riftmap/blob/main/docs/audits/SECURITY_AUDIT_2026-07-04.md) — no critical findings; all findings fixed before publication.
* [Verified controls table](https://github.com/DanielWestgaard/Riftmap/blob/main/docs/security.md) — every documented control cross-checked against the code, including what we deliberately risk-accept. This is also where the user-facing security summary on the marketing site is sourced from.
