Skip to content

Encryption in Transit

Statement

ClaimGuard's encryption-in-transit story is strong on the back-of-house and weak on the front door, and is documented honestly on this page so prospects and auditors can read both halves:

  • Strong: every outbound flow from the application — to GCP control-plane services, to GCS, to the Gemini API, to operator- configured webhooks — uses TLS with system-trust-store certificate validation. Internal traffic between the Node backend and the Python tools never leaves the VM.
  • Weak: public user-facing traffic to the application's API currently terminates on a non-TLS port (3001) on the VM's public IP. Closing that gap is plan step A1.3 (HTTPS Load Balancer + Google-managed certificate). Until A1.3 lands, this control is partial and the gap is the reason.

Implementation

What's TLS today

Flow Direction TLS posture
GCP control plane (Secret Manager, Cloud Logging, Compute, GCS) Outbound from VM TLS, Google-issued certificates, validated against system trust store
Google Gemini API (gemini-2.5-pro) Outbound from VM (master_tool) TLS, system trust store. See AI transparency.
Operator webhooks (SUPPORT_WEBHOOK_URL) Outbound from Node backend Wrapped by safeFetch (server/src/lib/safeFetch.js). Enforces TLS for https:// URLs, blocks private/link-local/CGNAT ranges, refuses redirects by default. See SAST.
Internal: Node ↔ Python tools (master_tool, c2pa, layover, etc.) Loopback (127.0.0.1) on the VM Not TLS — same-host, never leaves the VM. Documented as a deliberate design choice in docs/security/PROTOCOL.md §4.
Internal: Node ↔ Postgres Loopback on the VM Same as above — same-host. Postgres listens on local socket; no external network exposure.

What's not TLS today

  • Public user-facing application traffic. Browsers connect to the API at http://<public-ip>:3001/... without TLS. The HTTP-only gap is in scope for plan step A1.3 (HTTPS LB + Google-managed cert). Mitigated only by the fact that the product is not yet in customer hands.

This is the single open gap on this page.

How A1.3 closes the gap

The plan-A1.3 shape:

  • A GCP global external Application Load Balancer in front of the VM with a static IP and a hostname (likely app.dtectvision.ai).
  • A Google-managed TLS certificate attached to the LB; renewal is Google-operated.
  • A backend zonal NEG that points at the VM on the application's port. Health check on /health.
  • A firewall rule (allow-lb-health) restricted to GCP's LB source ranges (130.211.0.0/22, 35.191.0.0/16).
  • After cutover, plan step A1.2 closes the world-open application port directly (tcp:3001); only the LB-internal hop reaches it.

When A1.3 lands, this page flips to implemented and the Cryptography page's "Public user-facing TLS — planned" line is removed.

TLS versions and ciphers

  • GCP-managed certificates on the eventual LB will use Google's default modern TLS profile (TLS 1.2+, modern cipher set, perfect forward secrecy).
  • System-trust-store outbound uses Node.js / Python defaults, which require TLS 1.2+ and reject weak ciphers.

Certificate management

  • Inbound (planned): Google-managed certificate on the LB, auto-renewed; no certificate handling in our codebase or operator procedures.
  • Outbound: the system trust store on the VM is the source of truth; we do not pin a certificate or maintain a custom root list.

Status

partial — verified 2026-04-29.

What's in place:

  • TLS for every outbound flow (GCP, Gemini, operator webhooks).
  • safeFetch enforces TLS for outbound https:// URLs.
  • Internal traffic stays on loopback — no plaintext network hop between the Node backend, the Python tools, and Postgres.

Known gaps

  • Public user-facing TLS — not yet in place. Plan step A1.3. Single most-cross-listed gap on the trust portal — referenced from Cryptography and Network architecture as well.

Roadmap

  • A1.3 — HTTPS Load Balancer + Google-managed certificate. Single closing step.
  • HTTP → HTTPS redirect at the LB once the cert is ACTIVE.
  • HSTS header on the application response post-cutover.
  • /.well-known/security.txt at the application root once the LB is the front door (cross-listed on Vulnerability disclosure).