Skip to content

Security: sonak11/heart

Security

docs/SECURITY.md

HER Platform — Security

Authentication

  • Cognito User Pool with strong password policy (12+ chars, upper, lower, number, symbol)
  • JWT authorizer on all sensitive API routes
  • In-app sign-in/sign-up (no Cognito Hosted UI redirect)

Authorization

All interview management endpoints require JWT:

  • Create, edit, delete interviews
  • Transcript editing, finalization
  • Coding review, privacy review
  • Participant management

Public Endpoints (No Auth)

Endpoint Risk Justification
GET /analytics/stats MEDIUM Returns aggregate data + Bedrock-redacted quotes. Intentionally public for dashboard consumption. Quotes are PII-redacted.
POST /copilot MEDIUM AI assistant. Token consumption risk. Rate limiting recommended.
GET /analytics/themes LOW Aggregate thematic data only
GET /config/framework LOW Static coding framework definition

S3 Security

  • Both buckets have PublicAccessBlock enabled (all 4 flags true)
  • Server-side encryption: AES-256 (SSE-S3)
  • Bucket policies: only CDK auto-delete role + Transcribe service principal (scoped)
  • No public objects

IAM / Lambda Permissions

  • Each Lambda has its own least-privilege role
  • Comprehend Lambda: comprehend:DetectPiiEntities, comprehend:DetectEntities, comprehend:DetectKeyPhrases on Resource *
    • Justification: Synchronous Comprehend Detect* APIs do not support resource-level ARN restrictions. The wildcard is required by the AWS IAM model for these actions. Only the ComprehendProcess Lambda role has this policy.
  • Lambda invoke permissions are scoped to specific function ARNs

Data Separation

  • Raw transcripts: private to uploading user
  • Finalized transcripts: accessible to authenticated reviewers
  • Analysis (redacted) transcripts: used for analytics
  • Exported quotes: Bedrock-redacted before storage in analytics path
  • Legacy data quarantined at legacy/ prefix

State Bypass Protection

All state transitions are enforced server-side:

  • submit-review.js: Rejects approval if codingState is DRAFT or STALE
  • edit-codes.js: Rejects edits on DRAFT/STALE coding
  • edit-transcript.js: Rejects edits after finalization
  • export-analytics.js: Uses isAnalyticsEligible() dual gate (5 conditions)
  • privacy-review.js: Rejects review if privacy processing incomplete

Logging

  • No Lambda logs full transcript content or raw PII
  • Logs contain: action type, interview IDs, counts, status, error messages (truncated)

CORS

  • Allowed origins: https://heart.dqwgm9x6cucpa.amplifyapp.com, http://localhost:5173
  • Production note: Remove localhost origin before stakeholder release

Recommendations

  1. Add rate limiting to public endpoints (API Gateway throttling)
  2. Remove localhost from CORS for production
  3. Consider adding JWT auth to /analytics/stats if quote exposure is a concern
  4. Enable CloudTrail for DynamoDB/S3 audit logging

There aren't any published security advisories