Secure development lifecycle
Last reviewed 2026-05-18
Stages
1. Requirements / planning
- Feature briefs use the GitHub feature-request template or an equivalent change note with a data section enumerating any new data collected, its classification (per the data classification), retention, and the processors involved.
- Feature briefs use the GitHub feature-request template or an equivalent change note with an AI section if any AI provider is invoked; enumerate vendor, model, inputs, retention, and consent-flow implications.
2. Threat modeling
- For any change touching authentication, authorization, payment, file upload, external integration, cron, or AI: include a STRIDE threat-model section in the PR description or change record.
- Trivial UI/copy changes are exempt.
- Template held internally; the GitHub PR template prompts for this section.
3. Design review
- PRs adding new API routes, Firestore collections, or cron jobs include a one-paragraph design note referencing: data classification, who can access, what validation, what rate limits, and what logs. The GitHub PR template prompts for these fields.
- Material UI changes should identify accessibility considerations during planning or review, including keyboard flow, focus management, accessible names, semantic landmarks, contrast, reflow, reduced motion, and status announcements where applicable.
4. Implementation
Secure-coding requirements:
- Input validation: new and changed API route handlers use a shared schema-validation utility, enforced by local compliance checks and the scheduled/manual security workflow.
- Output encoding: user-provided HTML is routed through a shared sanitization helper where rich text is rendered. User-submitted content elsewhere flows through React JSX auto-escape.
- Authorization: new and changed handlers re-check authorization in the handler or shared route guard; no implicit trust in middleware. Firestore writes are scoped by owner/tenant where Firestore rules and server code have been updated.
- Outbound HTTP: external fetches use a shared SSRF-blocking helper that rejects private CIDRs and cloud-metadata endpoints.
- Logging: no PII or secrets in logs. Sentry's pre-send hooks strip known PII fields.
- Audit: security-relevant actions write to the append-only audit log; see the logging & retention.
- AI calls: AI calls routed through our internal AI audit handler write a metadata-only row to the AI call audit and support optional input safety checks. Per-request retention-minimization flags are set on covered provider requests (for example,
store: falseon OpenAI Chat Completions and Responses requests) and verified by local compliance checks and the scheduled/manual security workflow. We do not have Zero Data Retention (ZDR) amendments with any provider; standard provider retention applies. See the AI use disclosure. - Secrets: only via environment variables managed by the hosting platform; never committed; never logged.
5. Testing
- Unit: Jest; coverage for new business logic.
- Integration: Jest + Firebase emulator for Firestore-rules-sensitive changes.
- E2E: Playwright for golden-path user flows.
- Security: the weekly/manual security workflow is configured to run npm audit, Semgrep (
p/owasp-top-ten,p/nextjs,p/r2c-security-audit,p/nodejsscan), CodeQL, SBOM, patch verification, compliance audits, unauthenticated OWASP ZAP baseline DAST, and an optional read-only authenticated DAST smoke run. The authenticated run uses a scanner-safe authenticated session to check selected logged-in routes and read-only APIs for access-control regressions, expected security headers, and obvious secret exposure. Local pre-push checks run compliance deltas. - Accessibility: jsx-a11y lint, jest-axe, and Playwright axe are available for UI changes through local checks and release verification. Role-specific accessibility responsibilities are covered in the accessibility training module, and accessibility verification evidence is retained for each verification cycle.
6. Code review
- Current code-review control combines Security Officer review/approval, CODEOWNERS routing when PRs are used, local pre-push checks, and the security workflow.
- CODEOWNERS routes sensitive paths to the Security Officer when the GitHub PR workflow is used. Sensitive paths covered include Firestore Security Rules and Firebase configuration, authentication, administrator, and payment API handlers, top-level request middleware, audit, authorization, and security helpers, the compliance documentation tree, and the security workflow configuration.
7. Deploy
- Vercel preview deployments are available when PRs are used; staging smoke tests are run manually or through the manual CI workflow.
- Production releases are promoted from
masterthrough the Vercel deployment workflow. - Material releases require an archived authenticated DAST smoke report, with critical/high findings remediated or covered by a documented time-bound exception before release.
- Progressive rollout for major changes via feature flags.
8. Post-deploy monitoring
- For material releases, the deployment owner checks Sentry issue activity for 15 min post-deploy.
- For security-sensitive releases, selected audit-log events are spot-checked for unexpected patterns.
Dependency review
- Dependabot weekly PRs; patches triaged within 7 business days.
- High/critical CVEs remediated within target SLA (see the patch management) or covered by a documented, time-bound exception. The current release audit reports no unresolved high or critical npm audit findings.
- Licensing: GPL, AGPL, SSPL, or similar strong-copyleft dependencies require an Engineering Lead license exception or replacement. An advisory license check runs in local checks and the manual security workflow; exception records are kept internally. Enforcement is available for strong-copyleft packages without a recorded exception.
Secure defaults (implemented)
- Firestore rules: default-deny
- Next.js middleware and auth routes: production asserts secure base URLs; NextAuth provides CSRF protection for auth flows; selected mutating endpoints enforce trusted-origin checks
- Cookies:
__Secure-/__Host-prefixes,HttpOnly,SameSite - Global security headers (HSTS, XFO, XCTO, Referrer-Policy, Permissions-Policy, COOP, CORP) applied to every response
- Rate limiting on selected high-risk auth and account endpoints
- Content Security Policy applied in request middleware with a per-request nonce; nonce-only enforcement is progressively expanded as legacy inline content is migrated
Training
All engineers complete OWASP Top 10 training annually; see the security awareness training program. Personnel assigned accessibility or user-interface delivery responsibilities complete the accessibility training module before taking those responsibilities and annually while assigned.
Exceptions
Changes may request an exception with written justification; the Security Officer approves time-bound exceptions. Track the exception in the change record or PR description when a PR exists.