Encryption in Transit¶
Statement¶
ClaimGuard's encryption-in-transit story is TLS end-to-end on every documented external path. There are two parallel public HTTPS ingresses today, both terminating TLS with managed certificates:
- User-facing UI (canonical today):
https://claim-guard.dtectvision.ai, served by nginx on the application VM with a Let's Encrypt certificate (Certbot-managed, auto-renewing). Nginx serves the built Vitedist/for the static UI and proxies/api/to the Node backend on loopback (loopback only). HTTP (:80) on the same hostname 301-redirects to HTTPS. - API-only ingress (parallel):
https://app.dtectvision.ai, served by a GCP global external HTTPS Load Balancer with a Google-managed certificate (ACTIVE since 2026-05-03). HTTP (:80) on the same LB IP<LB_IP>301-redirects to HTTPS (added 2026-05-04). The LB applies an attached Cloud Armor security policy (per-IP rate limit + Adaptive Protection L7-DDoS defense). The LB hits the same Node backend;GET /returns 404 because the LB does not serve the SPA — it is intentionally the API path. - Outbound from the application: every outbound flow — to GCP control-plane services, to GCS, to the internal analysis services, 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.
- Future canonical:
app.claim-guard.aiis the intended user-facing URL once theclaim-guard.aidomain is acquired. Until then,claim-guard.dtectvision.aiis the URL prospects and customers should use.
The status below is partial only because the MODERN (TLS 1.2+)
SSL policy has not yet been attached to the LB target HTTPS proxy
— the LB defaults to the GCP COMPATIBLE profile which still
permits TLS 1.0/1.1 ciphers.
Implementation¶
What's TLS today¶
| Flow | Direction | TLS posture |
|---|---|---|
User browser → claim-guard.dtectvision.ai |
Inbound to nginx on VM | Let's Encrypt cert, HTTP→HTTPS 301 redirect, HSTS one-year. |
Caller → app.dtectvision.ai (API ingress) |
Inbound to GCP HTTPS LB | Google-managed cert, HTTP→HTTPS 301 redirect, Cloud Armor (rate limit + Adaptive DDoS), HSTS one-year. |
| LB → backend VM (LB-internal hop) | Google internal network | Plain HTTP between LB and NEG; runs inside Google's network, not the public internet. |
| nginx → Node backend (loopback only) | Loopback on the VM | Not TLS — same-host, never leaves the VM. |
| GCP control plane (Secret Manager, Cloud Logging, Compute, GCS) | Outbound from VM | TLS, Google-issued certificates, validated against system trust store. |
| internal analysis service (the configured analysis model) | Outbound from VM (an internal analysis service) | TLS, system trust store. See AI transparency. |
Operator webhooks (SUPPORT_WEBHOOK_URL) |
Outbound from Node backend | Wrapped by the outbound-HTTP wrapper. Enforces TLS for https:// URLs, blocks private/link-local/CGNAT ranges, refuses redirects by default. See SAST. |
| the image-analysis service → an internal peer VM | Outbound to a separate VM | Plain HTTP today (not TLS). The peer is the a peer VM (FastAPI image-analysis services). Cross-VM trust boundary; tracked as a follow-up to migrate behind an internal HTTPS endpoint or VPC-private network. |
| Internal: Node ↔ Python tools (an internal analysis service, content-provenance service, metadata-extraction service, 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¶
- internal tool ports on the VM IP are still reachable
unauthenticated over plain TCP from
0.0.0.0/0via the the internal-tool firewall rule. These are FastAPI internal tool ports (internal analysis service,the image-analysis service) that the application calls over loopback only; nothing legitimate connects to them externally. Tightening this rule is the residual the firewall-narrowing step follow-up. - No other plain-HTTP ingress. The the dev-server firewall rule firewall rule (the dev-server port world-open) was deleted 2026-05-04. The the application backend port was removed from the internal-tool firewall rule 2026-05-04, so the backend is no longer reachable directly via plain TCP on the VM IP.
Front-door hardening — what's in place 2026-05-04¶
For https://claim-guard.dtectvision.ai (nginx + Let's Encrypt):
- HTTPS via Let's Encrypt cert (auto-renewed by Certbot).
- HTTP (
:80) → HTTPS (:443) 301 redirect at the nginx layer. - Static UI served from the built
dist/;/api/reverse-proxied to the Node backend on loopback loopback only. - Application-set headers (helmet): HSTS one-year +
includeSubDomains, CSP
default-src 'none'; frame-ancestors 'none', referrer-policyno-referrer, X-Content-Type-Options nosniff, COOPsame-origin.
For https://app.dtectvision.ai (GCP HTTPS LB + Google-managed cert):
- Google-managed certificate ACTIVE.
- HTTP (
:80) → HTTPS (:443) 301 redirect at the LB (<REDIRECT_URLMAP>+<HTTP_PROXY>, added 2026-05-04). - Backend zonal NEG points at the VM on an internal application port. Health check
on
/health. Firewall ruleallow-lb-healthrestricts that port to GCP's LB source ranges (130.211.0.0/22,35.191.0.0/16). - Cloud Armor security policy the Cloud Armor policy attached to the backend service:
- Per-IP rate limit: 200 req/min, 5-minute ban on breach.
- Adaptive Protection (Layer-7 DDoS defense, ML-scored) enabled.
- Default rule:
allow. - Same application-set headers (helmet) reach the browser through the LB hop.
the firewall-narrowing step — substantially closed; residue tracked¶
The world-open dev/internal port surface that the firewall-narrowing step was scoped to address has been narrowed substantially:
- the dev-server firewall rule (the dev-server port): deleted 2026-05-04.
- the internal-tool firewall rule: direct backend port removed 2026-05-04; rule now only allows the narrowed internal-tool ports.
- an internal-tools firewall rule (an internal tool port, 9998, 8737, 5678): still in place, deferred pending operator confirmation that no external client uses these ports directly.
- The two FastAPI tool ports (9996/9997) on the VM IP are the
remaining
0.0.0.0/0ingress that the firewall-narrowing step still has to address.
TLS versions and ciphers¶
- Let's Encrypt cert on nginx uses the default Certbot configuration; cipher set follows Mozilla "intermediate".
- GCP-managed cert on the LB uses the custom
the MODERN-profile SSL policy SSL policy (
MODERNprofile,min_tls_version=TLS_1_2), attached to the LB HTTPS proxy 2026-05-06. TLS 1.0 and 1.1 are refused at the LB. - System-trust-store outbound uses Node.js / Python defaults, which require TLS 1.2+ and reject weak ciphers.
Certificate management¶
claim-guard.dtectvision.ai: Let's Encrypt via Certbot, auto-renewing on the VM. Certificate path:/etc/letsencrypt/live/claim-guard.dtectvision.ai/.app.dtectvision.ai: 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¶
implemented — verified 2026-05-06.
What's in place:
- Two parallel public HTTPS ingresses, both with HTTP→HTTPS 301 redirect, both with HSTS one-year + includeSubDomains:
claim-guard.dtectvision.ai(nginx + Let's Encrypt) — canonical user URL today.app.dtectvision.ai(HTTPS LB + Google-managed cert) — API ingress, with Cloud Armor (rate limit + Adaptive L7-DDoS protection) attached to the backend service and the MODERN-profile SSL policy SSL policy (MODERNprofile, TLS 1.2 floor) attached to the target HTTPS proxy 2026-05-06.- TLS for every outbound flow (GCP, the analysis service, operator webhooks).
- the outbound-HTTP wrapper 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¶
- internal tool ports on the VM IP are still world-open via the internal-tool firewall rule. These are FastAPI tool ports nothing external should reach. Roadmap.
the image-analysis service→ a peer VM at an internal peer VM is plain HTTP across VMs (cross-VM trust boundary). Roadmap.- No
/.well-known/security.txtat the application root yet (cross-listed on Vulnerability disclosure).
Roadmap¶
- Narrow the internal-tool firewall rule further (or move the FastAPI tool
services to bind on
127.0.0.1and delete the rule entirely). - Migrate
the image-analysis service↔ a peer VM to TLS or to a VPC-private network hop. /.well-known/security.txtat the application root.- Future: cut over to the new domain once
app.claim-guard.aiis provisioned (DNS + cert).