Exactly what happens to your code and credentials

Riftmap asks for a read-only access token to scan your organisation. This page explains precisely what we do with that access — no ambiguity, no hand-waving.

three guarantees
  • Source code is never stored. Only dependency metadata (names, versions, line numbers) persists. Code is cloned to a temporary directory, parsed, and deleted.
  • Tokens are encrypted at rest. AES-128-CBC via Fernet symmetric encryption. The encryption key lives in an environment variable, physically separate from the database.
  • Zero per-repo configuration. Read-only access only. No agents installed, no webhooks registered, no code changes in your repositories. Disconnect anytime.

What happens during a scan

Every scan follows this exact sequence. Each step is auditable in the codebase.

  1. 01

    Enumerate

    Platform API lists repository names and metadata. No code is accessed at this stage.

  2. 02

    Clone

    Shallow clone (depth=1, latest commit only, no history) to a temporary worker directory. No commit history is downloaded.

  3. 03

    Restrict

    Clone directory set to 0700 (owner-only) before git writes any content. No other OS process can read the files.

  4. 04

    Parse

    Only dependency manifest files are read (go.mod, package.json, Dockerfile, Terraform, CI configs, etc.) to extract dependency references.

  5. 05

    Store

    Only the dependency graph is written to the database: names, version constraints, line numbers. No source code.

  6. 06

    Delete

    Clone directory deleted via shutil.rmtree() in a try/finally block — runs even on parser exception or timeout. A Celery Beat task sweeps for orphaned clones every 15 minutes.

Hung clones are killed after 120 seconds. The cleanup is guaranteed by a try/finally block — it runs whether parsing succeeded, failed, or timed out.

What we store vs. what we don't

What persists in the database
  • Repository names and platform IDs
  • Dependency names and version constraints
  • Source file paths and line numbers where dependencies are declared
  • Scan timestamps, status, and per-repo lifecycle events
  • Artifact names (e.g. Docker image tags, npm package names)
What is never stored
  • Source code content of any kind
  • File contents beyond manifest metadata
  • Commit history (shallow clone — no history downloaded)
  • Secrets, environment variables, or .env files
  • Binary files or build artifacts

How we handle your access tokens

Encrypted at rest

Fernet symmetric encryption (AES-128-CBC + HMAC-SHA256). The encryption key is an environment variable, physically separate from the database. A database leak without the key yields only ciphertext.

Never in process arguments

Tokens are passed to git clone via the GIT_ASKPASS mechanism — a helper script that reads from an environment variable. The token never appears in /proc/*/cmdline or ps aux output.

Validated at ingestion

PATs are validated against known platform prefixes (ghp_, github_pat_, glpat-) and rejected if they don't match. Catches accidental submission of wrong credentials before they reach storage.

Zero-downtime key rotation

Dual-key mechanism: set the old key as ENCRYPTION_KEY_PREVIOUS, deploy with the new key, run the migration CLI to re-encrypt all tokens. No downtime, no user interruption.

Startup validation

The API server refuses to start if the encryption key is missing. There is no silent fallback to plaintext — failure is loud and blocks deployment.

Minimum OAuth scopes

GitHub OAuth login uses only read:user, user:email, and read:org — no repository access; scanning uses a separate PAT you provide. GitLab OAuth uses the OIDC scopes openid email profile read_user together with the read-only scanning scopes read_api read_repository — granted in the same consent flow, so no separate PAT is needed.

Verified-email gate

An OAuth identity is only accepted when the provider has proven the email is verified — GitHub via /user/emails (primary + verified), GitLab via the OIDC email_verified claim. OAuth can only attach to an existing local account when that local email is itself already verified.

Redirect-URL allow-list

OAuth return URLs are validated against an explicit allow-list before redirect. Protocol-relative payloads (//evil.com) and backslash-smuggling tricks (/\evil.com) are rejected — no open-redirect surface for phishing kits.

Workspace API keys

Stored hashed at rest — the plaintext is shown once at creation and never again. In the browser, API keys live only in sessionStorage; any legacy localStorage copy is purged on app bootstrap.

Safe clone invocation

Repository URLs are passed to git clone as a single argv argument — no shell, no interpolation. A repo name cannot smuggle flags, command separators, or filesystem paths into the cloner.

Session and password security

Passwords are hashed with Argon2id — 64 MB memory cost, time_cost=3, parallelism=4. Password policy enforces a 12-character minimum, rejects the top 10,000 most common passwords, and checks against the Have I Been Pwned breach database using k-anonymity (only a SHA-1 prefix is sent; the full hash is checked locally). HIBP unavailability never blocks registration.

Sessions use JWT access tokens with a 15-minute lifetime, stored in httpOnly cookies (JavaScript cannot access them). Refresh tokens rotate on every use under a database row lock (SELECT … FOR UPDATE) so two concurrent refresh requests cannot both succeed. If a previously spent refresh token is ever replayed — the signature a token thief would leave — the entire session chain is revoked immediately, forcing re-login on the legitimate client and instantly invalidating the attacker's copy. All cookies are SameSite=Lax and Secure in production; the SameSite value is compared case-insensitively, so a provider returning "lax" is still recognised as safe.

Brute-force protection: 5 login attempts per 15 minutes per IP, plus a per-email counter that locks after 10 failed attempts. The per-email counter uses a SHA-256 hash as the key — it reveals nothing about which email addresses are registered. Per-user rate limits key off a verified JWT (never a client-supplied header), so one user cannot exhaust another user's quota. Request-ID values are restricted to a strict character allow-list before logging, closing a log-injection vector.

Workspace invitations sent to a specific email address can only be accepted by an authenticated user whose own verified email matches the invited address (case-insensitive). An intercepted invite link cannot be redeemed under a different account.

Production hardening

HTTPS enforced in production — startup check rejects all http:// URLs for backend, frontend, and CORS origins.
HSTS 2-year max-age with includeSubDomains and preload. Forces HTTPS at the browser level.
CSP default-src 'none'; frame-ancestors 'none' on all API responses. Prevents XSS and clickjacking.
X-Frame-Options DENY. X-Content-Type-Options: nosniff. Referrer-Policy: strict-origin-when-cross-origin.
Swagger UI disabled in production — /docs, /redoc, and /openapi.json are unavailable. Prevents endpoint enumeration.
Sentry error tracking and 5% performance tracing. Authorization, X-API-Key, and Cookie headers are stripped; send_default_pii=False; session replay is disabled.
Axiom structured JSON log aggregation (request IDs, method, path, status, scan and workspace identifiers). ~30 day retention. No source code, passwords, or tokens in logs.
Redis password required in production — startup validation rejects default credentials.
Docker all service ports bound to 127.0.0.1 — not exposed to the network.
/health/detailed admin-key gated in production. ADMIN_API_KEY is validated at startup — the server refuses to boot without it, so there is no accidental path to a public infrastructure-report endpoint.
Stripe webhooks signature-verified, IP-filtered against Stripe's official allow-list, and dropped unless the event type is on our explicit handler list. When adopting a Stripe customer into a workspace, the customer's email must match the workspace owner's before billing events are honoured — a replayed or spoofed event cannot re-target another tenant's subscription.

Your data is your data

All data is scoped to a Workspace via foreign keys enforced at the database level. Every API query filters by the authenticated workspace — there is no global view.

Cross-workspace access attempts return 404 Not Found (not 403 Forbidden). This prevents an attacker from even discovering whether another workspace's resources exist.

Workspace API keys are scoped to a single workspace and cannot access any other. We run a parametrised cross-workspace isolation test suite in CI that hits every endpoint with a foreign workspace ID and asserts 404 on all of them.

Offboarding and data portability

Disconnect an organisation

The encrypted token is deleted from the database. All associated repositories, scans, dependency data, and artifacts are cascade-deleted. You should revoke the token manually at your provider (GitHub Settings / GitLab Settings).

Delete your account

30-day grace period (GDPR soft-delete). All sessions are immediately revoked. You can cancel by re-authenticating within the grace period. After 30 days, all workspace data, scans, and personal data are permanently hard-deleted.

Export your data

GET /workspaces/{id}/export returns all workspace data as JSON. Members, connected orgs, repos, scans, dependencies, artifacts, and audit events. Encrypted tokens are redacted. Rate-limited to one export per workspace per hour.

Common security questions

01 Do you store my source code?

No. Source code is cloned to a temporary directory, parsed for dependency metadata, and deleted immediately — guaranteed by a try/finally block. A background task sweeps for orphaned clones every 15 minutes as a safety net. Only dependency names, version constraints, and line numbers persist.

02 What access does Riftmap need?

For GitHub: OAuth login uses only read:user, user:email, and read:org (no repository access); scanning uses a separate PAT you provide — a fine-grained PAT with "Contents: Read-only" and "Metadata: Read-only" is the recommended choice. For GitLab: OAuth login grants login plus read-only scanning in the same consent flow (openid email profile read_user read_api read_repository) so no separate PAT is required; you may still provide a PAT with read_repository scope if you prefer. We also verify that the email on your OAuth identity is proven verified at the provider before linking an account — GitHub's primary+verified email or GitLab's OIDC email_verified claim.

03 Can other workspaces see my data?

No. All data is scoped to your workspace via foreign keys enforced at the database level. Cross-workspace access attempts return 404 (not 403) to prevent even leaking the existence of other workspaces. We run a parametrised cross-workspace isolation test suite in CI that hits every endpoint with a foreign workspace ID.

04 What happens if I disconnect an organisation?

The encrypted token is deleted from the database, and all associated repositories, scans, dependency data, and artifacts are cascade-deleted. Riftmap does not automatically revoke your token at the provider — you should do this manually via your GitHub or GitLab settings. If you only need to replace the token (rotation, rather than full offboarding), you can do it in place without losing data — see the next question.

05 What if my access token is compromised or expires?

You can rotate a connected org's access token in place from Settings → Connections → Edit → Rotate access token. The new token is validated (prefix + GitHub scope check), then encrypted and swapped for the old one. Your repositories, scans, and dependency graph are preserved. In-flight scans finish using the old token; subsequent scans use the new one. Rotation does not automatically revoke the old token at the provider — revoke it manually once the new one is in place.

06 How do I export my data?

GET /workspaces/{id}/export returns all workspace data as JSON — members, connected orgs, repos, scans, dependency declarations, resolved edges, artifacts, and audit events. Encrypted tokens are redacted. Rate-limited to one export per workspace per hour.

07 What telemetry do you collect?

We send error reports and a small fraction (~5%) of performance traces to Sentry, and ship structured JSON request logs to Axiom. Telemetry includes stack traces, URL paths, HTTP status codes, request IDs, and your authenticated user ID and email (so we can correlate reports you send us). Authorization, API-key, and cookie headers are stripped before leaving the backend. Session replay is disabled — we do not record video of user interactions or capture keystrokes. Passwords, access tokens, and source-code content are never in telemetry. When self-hosting becomes available, it will disable all external telemetry.

08 Is Riftmap SOC 2 certified?

Not yet. SOC 2 Type II certification is on our roadmap. In the meantime, every security claim on this page is verifiable against our codebase. We publish our security documentation openly and welcome review.

09 Can I self-host Riftmap?

Self-hosting is on our roadmap and not yet generally available. When it ships, your data will never leave your infrastructure and the same security controls (encryption, workspace isolation, clone cleanup) will apply. Self-hosting will support GitLab self-managed CE/EE and GitHub Enterprise Server, including air-gapped deployments. Contact us at [email protected] if you need on-premises deployment — we're prioritising based on inbound demand.

You'll talk to the person who built it

Riftmap is built and operated by Daniel Westgaard — a software and DevOps engineer based in Norway, operating under Westgaard Technologies. The architecture and the security defaults on this page reflect the kind of regulated environments Riftmap was designed for from day one — Norwegian government, finance, defence — not bolted on later.

If you have a security question that isn't covered above, the email below reaches me directly. No support queue, no tier-one deflection, no "we'll pass this to the team."

Start mapping your dependencies

Connect a GitHub or GitLab organisation with a read-only token. Riftmap scans your repos, builds the dependency graph, and deletes the code. You can disconnect anytime.

Every security claim on this page is verifiable against our codebase.