Security overview
Last reviewed 2026-05-07
This page describes the security controls actually in place today. Items we have committed to but not yet implemented are listed separately at the bottom under “Commitments and roadmap” — we don’t mix the two.
Hosting
- Hosted on Google Cloud Platform (Firebase) and Vercel — both SOC 2 Type II attested. Google additionally holds ISO 27001/17/18/701, Payment Card Industry Data Security Standard (PCI DSS) Level 1, HIPAA, and FedRAMP High. We rely on these inherited controls for at-rest encryption (AES-256 by the platform) and physical security.
- Primary region: United States.
Network and headers
- Cloudflare is active for public DNS and reverse-proxying of
hiringcoach.ai; Vercel inherited platform protection and automatic DDoS mitigation also apply. - HTTPS is required for browser traffic, with HSTS preload. Cloudflare edge minimum TLS is set to TLS 1.2, and TLS 1.3 remains enabled.
- HSTS with 2-year max-age and preload (
next.config.mjs). - Content Security Policy applied to every response, with a per-request nonce emitted on the
x-nonceheader. Nonce-based enforcement (replacing'unsafe-inline'with'nonce-…' 'strict-dynamic') is gated by theSTRICT_CSP_NONCESenv var; the production rollout is on the roadmap. X-Frame-Options DENY; X-Content-Type-Options nosniff (middleware.js,next.config.mjs). - Server-side outbound HTTP wrapped with an SSRF guard that blocks private CIDRs, link-local, and cloud metadata IPs (
lib/net/safeFetch.js; CI grep-gate viascripts/audit-unsafe-fetch.js).
Identity and access
- Passwordless magic-link signin and OAuth (Google, LinkedIn, Facebook).
- Application-level multi-factor authentication (TOTP) is available as an opt-in setting on the user’s Security tab. Compatible with standard authenticator apps (Google Authenticator, 1Password, Authy). Ten one-time backup codes are issued at enrollment for device-loss recovery. TOTP secrets are encrypted at rest with AES-256-GCM and anti-replay is enforced server-side. Administrators additionally use Google Account sign-in protected by Google Account MFA; vendor consoles also require MFA.
- Role-based access control with distinct admin/user roles.
- CSRF protection on auth endpoints (NextAuth).
Data store
- Firestore Security Rules with user-scoped reads and writes; documents not explicitly allowed are denied. Rule changes go through PR review.
- Backups: Google Cloud provides platform durability and encryption. Live GCP review confirmed Firestore PITR, managed daily Firestore backups with 98-day retention, and a US multi-region backup/export bucket with versioning, 90-day soft delete, and an unlocked 90-day retention policy. Immutable Bucket Lock retention is not currently configured.
Audit log
- Selected account, session, app-level MFA, AI feedback, cookie-consent, admin-status, and NextAuth sign-in/sign-out events write to an append-only
auditLogcollection vialib/audit/log.js. - Coverage is not universal across the API surface; expanding coverage is a roadmap item below.
Application security
- Output sanitization for rendered user-provided HTML (
lib/security/sanitizeRichText.js,utils/sanitizeHtml.js). - Rate limiting on selected high-risk endpoints (signup, writer/generate, writer/revise, AI feedback) via
utils/rateLimiter.js. Coverage is not universal across the API surface. - Implemented API endpoints increasingly enter a standardized request-validation wrapper, with route-specific required-field, file, and semantic checks continuing inside handlers while more constraints are promoted into central schemas. We do not claim universal schema validation across the legacy API surface.
- Field-level AES-256-GCM encryption (
lib/crypto/fieldEncrypt.js) for LinkedIn OAuth session cookies (utils/server-utils/linkedinCookieCrypto.js) and customer app-level MFA TOTP secrets. Broader field-level encryption coverage for other Restricted-class fields is under internal evaluation.
Dependency and code security (CI)
- Dependabot for dependency updates (
.github/dependabot.yml). - Semgrep SAST, CodeQL, npm audit, SBOM generation, and optional ZAP are available through the manual security workflow. Local pre-push checks run typecheck, changed-file lint, and compliance deltas.
- CycloneDX SBOM generation is available through the manual security workflow and is published when the workflow is run from
master. - Custom audit scripts:
scripts/audit-unsafe-fetch.js,scripts/verify-ai-zdr.js,scripts/audit-dpa-register.js,scripts/audit-compliance-claims.js.
Error monitoring
- Sentry for application errors and performance.
- Sentry default PII collection is disabled (
sendDefaultPii: false), andbeforeSendstrips request cookies, authorization headers, query strings, and sensitive extra/context keys.
AI safety
- Per-request controls minimize provider storage or transcript exposure where supported (
store: falseon OpenAI,redact=trueon Deepgram). We have not signed Zero Data Retention amendments; standard provider retention applies (for OpenAI, up to 30 days for abuse monitoring). - We rely on each AI provider’s standard API terms for the no-training default.
- Output moderation is not currently applied to AI outputs. Adding OpenAI Moderation in
lib/ai/callWithAudit.jsis a planned control. - Prompt-injection / jailbreak detection in
lib/ai/safetyGuard.js. - AI activity logging records operational metadata (model, endpoint, token counts where available, timing, and outcome) — never prompt or completion content.
- See AI disclosure for the full picture, including which features may auto-trigger AI calls in the background.
Compliance posture
- HIPAA: N/A — PHI is prohibited by our Terms.
- Payment Card Industry Data Security Standard (PCI DSS): Self-Assessment Questionnaire A (SAQ-A) scope; Stripe handles all card capture.
- GDPR / UK GDPR: 2021 EU SCCs and the UK IDTA where required; relies on sub-processor agreements (see Sub-processors).
- CCPA / CPRA: service-provider posture.
Commitments and roadmap
The following are documented as program commitments. Where evidence of execution does not yet exist in the repository, we describe them as such rather than asserting them as ongoing practice.
- Quarterly access reviews — documented in
docs/compliance/internal-audit.md; first review pending. - Annual full + semi-annual partial restore drills — documented in
docs/compliance/BCP.md; first drill pending. - AI bias-evaluation baseline across demographic name variations, with a larger annual evaluation planned.
- 72-hour regulator notification SLA for qualifying breaches — documented in
docs/compliance/breach-notification.md. - Universal audit-log coverage on mutating API routes — currently partial (~8/367 routes).
- Continue promoting route-specific schemas and constraints into the standardized API validation wrapper; universal schema validation remains partial.
- Broader field-level encryption coverage (currently used for LinkedIn OAuth cookies and customer app-level MFA TOTP secrets; extend to other Restricted-class fields per
docs/compliance/data-classification.md). - Continue expanding AI audit metadata review coverage as new AI providers and realtime features are added, including wrapping remaining direct OpenAI call sites in
lib/ai/callWithAudit.js.