Triage
1
Acknowledge receipt
Reports arrive through GitHub private vulnerability reporting and appear under repo → Security → Advisories. Reply in the advisory thread on intake confirming the report was received, with a confidentiality reminder.
Do this first, before reproduction and scoring, so the response is never delayed by triage depth.
Do this first, before reproduction and scoring, so the response is never delayed by triage depth.
2
Reproduce
Reproduce locally before scoring. If it doesn’t reproduce, ask the reporter for clarification.
3
Check scope
Compare against the Out of scope list in SECURITY.md. If out of scope, reply with the reason and close.
4
Score with CVSS 4.0
Use the FIRST calculator. Record the score and vector.
Buckets: 0.1–3.9 low, 4.0–6.9 medium, 7.0–8.9 high, 9.0–10 critical.
Buckets: 0.1–3.9 low, 4.0–6.9 medium, 7.0–8.9 high, 9.0–10 critical.
5
Send evaluation within 7 business days
Reply to the reporter with the severity and expected resolution date. Clock starts at the report timestamp.
Private fix
1
Work from the advisory
A report submitted through private vulnerability reporting already appears as a draft advisory under repo → Security → Advisories; open it.
For an internally discovered issue with no external reporter, create one with New draft security advisory.
Set affected versions, severity, and a neutral summary.
Keep it as a draft. You’ll fill the rest of the metadata in Draft advisory later.
For an internally discovered issue with no external reporter, create one with New draft security advisory.
Set affected versions, severity, and a neutral summary.
Keep it as a draft. You’ll fill the rest of the metadata in Draft advisory later.
2
Use a temporary private fork
From the draft advisory, click Start a temporary private fork.
Fix on a
Fix on a
security/<ghsa-id> branch inside it.3
Add a regression test, then merge
Run
Add a regression test. Merge the PR inside the private fork.
npm run lint-dev, npm run test-unit, npm run test-api. Add a regression test. Merge the PR inside the private fork.
Draft advisory
1
Request CVE ID (optional)
In the draft advisory: CVE ID → Request CVE. GitHub assigns one within ~1 business day.
2
Fill the metadata
Fields must match the in-app
SecurityAdvisory shape: summary, description, severity, cvssScore, vulnerableVersionRange (e.g. < 0.71.1), patchedVersion. Use the advisory body template for the description.3
Set the embargo
Default 60 days. Hold publication until the patch is on cloud production and customers have been notified.
Publish sooner if actively exploited or the reporter has set an earlier date.
Patch release
1
Cut a hotfix branch
Follow the cloud-hotfix flow in Releases:
deploy/cloud/YYYY-MM-DD branch, then trigger continuous-delivery-cloud.yml with cloud-hotfix.2
Bump versions
Patch-bump root package.json. Bump
packages/core/shared if touched. If the fix has a migration, set release = '<patched-version>' per Database Migrations.3
Verify on canary
Wait for canary to confirm before promoting to production.
4
Draft the changelog entry
Draft (don’t post yet) for docs/about/changelog.mdx:
Customer disclosure
7-day lead time before public publication. Patched version must already be on cloud production before sending.Public publication
1
Publish the advisory
In the draft advisory, click Publish advisory. This makes the CVE public.
2
Confirm the advisory reaches admins
Confirm the new advisory appears on the platform health page (
/platform/infrastructure/health). Source feeds cache for 15 minutes, so allow that delay before troubleshooting.Pending the security advisories panel reaching production. Until then, skip this step.
3
Post the changelog
Commit the changelog entry drafted in Patch release.
Postmortem
Required for high/critical, optional for medium, skip for low. Createdocs/handbook/engineering/postmortems/YYYY-MM-DD-<slug>.mdx using the existing structure (see 2026-03-19 Redis and delay overload).