security: pk_/sk_ key rotation, origin-validation hardening, and CSP guidance for embedded widget - #50
Merged
aguilar1x merged 12 commits intoJul 20, 2026
Conversation
…tion-origin-csp # Conflicts: # services/connect-gateway/prisma/schema.prisma # services/connect-gateway/src/routes/admin.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #36
Summary
Implements #36 — key rotation with a grace period, hardened origin validation, and copy-paste CSP guidance for the embedded widget. Builds on the
pk_/sk_key model (#11) and the origin validation shipped in the first campaign.Key rotation with grace period (
services/connect-gateway)rotateApiKeynow issues a newpk_/sk_pair as a successorApiKey(linked viarotatedFromId) instead of overwriting the secret in place. The old key staysactivewith agraceExpiresAtwindow (default 24h, configurable viaKEY_ROTATION_GRACE_MS), so in-flight sessions using the old key keep working during cutover.cutoverApiKey+POST /admin/keys/:id/cutoverrevoke the predecessor on demand; keys also expire lazily once the grace window passes (no cron). Double-rotation is guarded.Origin-validation hardening
normalizeOrigin(rejects non-http(s) schemes, embedded credentials, path/query/fragment, and unparseable values) andmatchOrigin(single-label wildcardhttps://*.example.com; apex, multi-level, and bare*are rejected case-insensitively; protocol and port must match).RefererwhenOriginis absent and returns explicit error codes:key_required,key_invalid,origin_required,invalid_origin,origin_not_allowed.allowedOriginsare validated at key-creation time too.CSP + iframe-sandbox guidance (
apps/docs,packages/connect-elements)security.mdxwith mode-aware, copy-paste CSP snippets (in-pagemount()vs isolatedmountFrame()) and iframe-sandbox guidance.FRAME_SANDBOXis exported as the single source of truth for the sandbox tokens;csp.test.tsasserts the built widget bundle contains noeval()/new Function()/inline<script>and that the documented sandbox string matches the constant.Acceptance criteria
Testing
npm run type-check(8/8) andnpm run check(biome) clean.Follow-ups (non-blocking)
KEY_ROTATION_GRACE_MSusesNumber.parseInt, which is lenient about trailing garbage ("24abc"→ 24).