diff --git a/_static/psrt-coordinator-report.html b/_static/psrt-coordinator-report.html
new file mode 100644
index 000000000..d1e3c9d69
--- /dev/null
+++ b/_static/psrt-coordinator-report.html
@@ -0,0 +1,31 @@
+
+
+
+
+ ┌────────────────────────┐
+ │ Received a report... │
+ └──┬──────────────────┬──┘
+ │ │
+┌────────────▼──────────────┐ ┌─▼──────────┐
+│ ..via security@python.org │ │ ..via GHSA │
+└────────────┬──────────────┘ └─┬──────────┘
+ │ │
+┌────────────▼──────────────┐ │
+│ PSRT admin reviews email │ │
+└───┬───────────────────┬───┘ │
+ │ │ │
+┌───▼────┐ ┌────▼───┐ │
+│ Reject │ │ Accept │ │
+└────────┘ └────┬───┘ │
+ │ │
+┌───────────────────────▼───┐ │
+│ PSRT asks reporter to │ │
+│ open via GHSA │ │
+└────────────┬──────────────┘ │
+ │ │
+ ┌──▼──────────────────▼──┐
+ │ GHSA in state 'Triage' │
+ └────────────────────────┘
+
+
+
diff --git a/_static/psrt-coordinator-triage.html b/_static/psrt-coordinator-triage.html
new file mode 100644
index 000000000..af5936a6c
--- /dev/null
+++ b/_static/psrt-coordinator-triage.html
@@ -0,0 +1,40 @@
+
+
+
+
+ ┌────────────────────────┐
+ │ GHSA in state 'Triage' │
+ └─┬────────────────────┬─┘
+ │ │
+┌──────────────────▼─────────┐ ┌────────▼───────────────────┐
+│ │ │ After 3 days idle, │
+│ PSRT member volunteers │ │ Coordinator is assigned │
+│ as Coordinator │ │ automatically by bot │
+└──────────────────┬─────────┘ └────────┬───────────────────┘
+ │ │
+ ┌─▼────────────────────▼─┐
+ │ GHSA update 'Credit' │
+ │ field to Coordinator │
+ └────────────┬───────────┘
+ │
+ ┌────────────▼───────────┐
+ │ Coordinator determines │
+ ┌───┤ whether report... ┼───┐
+ │ └────────────┬───────────┘ │
+ │ │ │
+┌────────────▼─┐ ┌────────────▼───────────┐ ┌─▼─────────────┐
+│..is a invalid│ │ ..is a bug, but not │ │..is a security│
+│ or non-issue│ │ security relevant │ │ issue │
+└────────────┬─┘ └────────────┬───────────┘ └─┬─────────────┘
+ │ │ │
+ │ ┌────────────▼───────────┐ │
+ │ │ Coordinator opens a │ │
+ │ │ public GitHub issue │ │
+ │ └─┬──────────────────────┘ │
+ │ │ │
+ ┌──────────▼─────▼───────┐ ┌────────────▼───────────┐
+ │ Close the GHSA ticket │ │ GHSA in state 'Draft' │
+ └────────────────────────┘ └────────────────────────┘
+
+
+
diff --git a/developer-workflow/psrt.rst b/developer-workflow/psrt.rst
index dee901726..c2501e44b 100644
--- a/developer-workflow/psrt.rst
+++ b/developer-workflow/psrt.rst
@@ -58,7 +58,7 @@ Below are the responsibilities of PSRT members:
necessary to make a determination whether a report is a vulnerability and
developing a patch. Coordinators are encouraged to involve members of the core
team to make the best decision for each report rather than working in isolation.
-* As a Coordinator, calculating the severity using CVSS and authoring advisories
+* As a Coordinator, calculating the severity using CVSSv4 and authoring advisories
to be shared on `security-announce@python.org`_. These advisories are used for
CVE records by the `PSF CVE Numbering Authority`_.
* Coordinators that can no longer move a report forwards for any reason must
@@ -82,94 +82,188 @@ following additional responsibilities:
* Running nomination elections, including counting final votes and giving
the Steering Council an opportunity to veto nominations via email.
-Vulnerability report triage
----------------------------
+Triaging a vulnerability report
+-------------------------------
+
+PSRT members coordinate reports from when they are first submitted
+to a "finished" state. Finished states include
+marking a report as a "non-issue", opening a public issue on GitHub,
+or a merged patch with an accompanying CVE and advisory to
+``security-announce@python.org``. Reports should reach a finished
+state within 90 days of being received by the PSRT.
-Vulnerability reports are sent to one of two locations,
-the long-standing ``security@python.org`` mailing list
-or using the private vulnerability reporting feature
-of GitHub Security Advisories (GHSA).
+Reports enter the system through ``security@python.org`` or
+on a project GitHub Security Advisory (GHSA) ticketing system.
+For projects that use GHSA, reports to ``security@python.org``
+should have reporters :ref:`re-open their report using GHSA `.
+
+.. raw:: html
+ :file: ../_static/psrt-coordinator-report.html
+
+New report in GitHub Security Advisories (GHSA)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once a report is in GHSA, a "Coordinator" must be assigned
+to be responsible for moving the report through the process.
+The "Coordinator" role is assigned using a "Credit" in a GHSA ticket
+(Select 'Edit' > 'Credit' > Add GitHub username and the role 'Coordinator').
+
+.. warning::
+ Assigning the "Coordinator" role to each GHSA ticket is important,
+ as this metadata records whether a PSRT member is
+ `"active" according to PEP 811`_ to avoid being removed due to inactivity.
+
+.. _"active" according to PEP 811: https://peps.python.org/pep-0811/#psrt-membership-policy
+
+If a GHSA ticket is idle for three days without a coordinator
+assigned a PSRT member who is not a Release Manager
+or Steering Council member will be automatically assigned
+as coordinator by the PSRT bot.
+If a coordinator can't complete the process
+they must find a replacement coordinator in the PSRT
+and re-assign the GHSA ticket.
-For reports sent to ``security@python.org``, a PSRT admin
-will triage the report and if the report seems plausible
-(that is, not spam and for the correct project) will reply with
-instructions on how to report the vulnerability on GitHub.
+.. raw:: html
+ :file: ../_static/psrt-coordinator-triage.html
-If the reporter doesn't want to use GitHub's Security Advisories feature
-then the PSRT admins can create a draft report on behalf of the reporter.
+Determining whether a report is a vulnerability
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The coordinator will make a determination about a report, either
+marking the ticket as a non-issue, as an issue that isn't a security
+vulnerability, or as a security vulnerability. If the Coordinator needs
+help from core team experts in making the determination, the
+experts may be added as 'Collaborators' to the GHSA ticket.
+Accepted security vulnerabilities will be moved to the 'Draft' state in GHSA.
-Coordinating a vulnerability report
------------------------------------
+If the report isn't a vulnerability, coordinators close the GHSA ticket
+after optionally opening a public GitHub issue. Note that reporters often
+will not open a GitHub issue on their own, as there is no longer an incentive
+for them to do so without a CVE being assigned.
+
+Remediating a vulnerability report
+----------------------------------
+
+Once a report has been accepted as a vulnerability, the remediation
+development process begins. Coordinators move the GHSA ticket to a 'Draft'
+state using the green 'Accept as Draft' button. Once in this state,
+the PSRT bot will automatically assign a CVE ID from the Python Software
+Foundation CVE Numbering Authority.
+
+Once a vulnerability has been accepted there are three things
+the Coordinator must prepare before sending an advisory and
+closing the GHSA ticket:
+
+* Severity calculated using CVSSv4.
+* Pull request containing the fix merged with a public GitHub issue.
+* Advisory title and short description of the vulnerability.
+
+Severity scoring
+~~~~~~~~~~~~~~~~
+
+Severity of a vulnerability can be difficult to assess
+objectively due to not knowing how software is used
+in all situations. Severity is calculated from expected
+or known use, not from worst-case hypothetical scenarios.
+
+The PSRT and PSF CNA use `CVSSv4`_ for calculating
+the severity of a vulnerability. GHSA tickets provide a
+CVSSv4 calculator within the ticket UI. Note that GitHub defaults to CVSSv3,
+change the scoring algorithm to CVSSv4 before scoring in the ticket UI.
+As with all aspects of PSRT operations, coordinators are encouraged to ask
+for help in calculating a severity from other PSRT members.
+
+.. _CVSSv4: https://www.first.org/cvss/v4.0/
+
+Developing a patch privately
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Patch development can initially be done privately by selecting the
+'Start a temporary private fork' button within the GHSA ticket. Note that
+due to the size of Git repositories, this fork repository may
+take several minutes to create. Once the fork has been created any PSRT member
+or GHSA collaborator can clone the fork and develop a fix and push a branch:
+
+.. code-block:: shell
+
+ git clone https://github.com/python/cpython-ghsa-abcd-efgh-ijkl.git
+ cd cpython-ghsa-abcd-efgh-ijkl
+ git checkout -b advisory-fix-1
+
+ # (develop a fix)
+
+ git add ...
+ git commit -m "Fix"
+ git push origin advisory-fix-1
+
+From here a pull request can be opened within the GHSA ticket
+to be reviewed privately. The coordinator can add core team experts
+as collaborators as necessary to the GHSA to develop the patch and to review
+the patch if the expertise for patch development or review
+aren't available within PSRT. Coordinators are not necessarily responsible
+for developing patches themselves: only with seeing that a patch is
+developed in a timely fashion by involving experts as necessary.
+
+Once the patch has been approved
+a public GitHub issue and pull request can be opened.
+Generate a blurb in the category ``Security`` for the public pull request.
+Public issues and pull requests for security fixes should use the
+:gh-label:`type-security` label.
+
+To quickly pull a patch file from a GHSA pull request, you
+can append ``.patch`` to the pull request URL, like so:
+
+.. code-block:: shell
+
+ curl https://github.com/python/cpython-ghsa-abcd-efgh-ijkl/pull/1.patch \
+ --output ghsa-abcd-efgh-ijkl.patch
+
+This patch can then be applied and pushed to the public GitHub repository:
+
+.. code-block:: shell
+
+ git remote -v
+ origin ssh://git@github.com/.../cpython (fetch)
+ origin ssh://git@github.com/.../cpython (fetch)
+
+ git checkout -b branch-name
+ git apply ./ghsa-abcd-efgh-ijkl.patch
+ git push origin branch-name
+
+.. warning:: **IMPORTANT:** CPython's backport infrastructure
+ is used for tracking backported patches. Use **one GitHub issue
+ per CVE** to accurately track backports of vulnerability fixes.
+ For new CVEs, even when related to a previous issue, **open a
+ new GitHub issue** to accurately track fixed versions.
-Each report will have a member of the PSRT assigned as the "coordinator".
-The coordinator will be responsible for following the below process and
-will be publicly credited on vulnerability records post-publication.
+.. warning:: **IMPORTANT:** Don't select the green 'Merge pull request'
+ or 'Publish advisory' buttons within GHSA. Advisories are published
+ to the mailing list, and the 'Merge pull request' button within
+ GHSA bypasses all continuous integration and branch protection
+ steps. Use a public pull request instead.
+
+Publishing an advisory
+~~~~~~~~~~~~~~~~~~~~~~
+
+Once the vulnerability fix has been merged into the main branch via a
+public GitHub pull request, an advisory must be published.
+The advisory requires the severity,
+a title, and a short description of the vulnerable module, functions,
+behavior and fix. This short description can optionally include mitigation steps
+if applying the patch isn't the only way to mitigate the vulnerability.
-If a coordinator can't complete the process for any reason (time obligation,
-vacation, etc.) they must find a replacement coordinator in the PSRT
-and reassign the vulnerability report appropriately.
+* Send an email to the ``security-announce@python.org`` mailing list
+ using the `advisory template`_, including title, severity, description.
+* The advisory email will be received by PSF CVE Numbering Authority
+ operators and used to publish a CVE record.
+* Begin the backporting process for all Python branches still receiving
+ security updates. Add the :gh-label:`type-security` and :gh-label:`release-blocker` labels
+ to each backport pull request so that release managers can find them prior
+ to releasing.
-Coordinators are expected to collaborate with other PSRT and core team members
-when needed for guidance on whether the report is an actual vulnerability,
-severity, advisory text, and fixes.
+After an advisory email is sent, the GHSA ticket can be closed.
-**The vulnerability coordination process is:**
-
-* Coordinator will determine whether the report constitutes a vulnerability. If the report isn't a vulnerability,
- the reporter should be notified appropriately. Close the GHSA report, the report can be reopened if
- sufficient evidence is later obtained that the report is a vulnerability.
-
-* After a vulnerability report is accepted, a Common Vulnerabilities and Exposures (CVE) ID must be assigned. If this is not done
- automatically, then a CVE ID can be obtained by the coordinator sending an email to ``cna@python.org``.
- No details about the vulnerability report need to be shared with the PSF CVE Numbering Authority (CNA) for a CVE ID to be reserved.
-
-* If the report is a vulnerability, the coordinator will determine the severity of the vulnerability. Severity is one of:
- **Low**, **Medium**, **High**, and **Critical**. Coordinators can use their knowledge of the code, how the code is likely used,
- or another mechanism like Common Vulnerability Scoring System (CVSS) for determining a severity. Add this information to the GitHub Security Advisory.
-
-* Once a CVE ID is assigned, the coordinator will share the acceptance and CVE ID with the reporter.
- Use this CVE ID for referencing the vulnerability. The coordinator will ask the reporter
- if the reporter would like to be credited publicly for the report and if so, how they would like to be credited.
- Add this information to the GitHub Security Advisory.
-
-* The coordinator authors the vulnerability advisory text. The advisory must include the following information:
-
- * Title should be a brief description of the vulnerability and affected component
- (for example, "Buffer over-read in SSLContext.set_npn_protocols()")
-
- * Short description of the vulnerability, impact, and the conditions where the affected component is vulnerable, if applicable.
-
- * Affected versions. This could be "all versions", but if the vulnerability exists in a new feature
- or removed feature then this could be different. Include versions that are end-of-life in this calculation
- (for example, "Python 3.9 and earlier", "Python 3.10 and later", "all versions of Python").
-
- * Affected components and APIs. The module, function, class, or method must be specified so users can
- search their codebase for usage. For issues affecting the entire project, this can be omitted.
-
- * Mitigations for the vulnerability beyond upgrading to a fixed version, if applicable.
-
- This can all be done within the GitHub Security Advisory UI for easier collaboration between reporter and coordinator.
-
-* The coordinator determines the fix approach and who will provide a fix.
- Some reporters are willing to provide or collaborate to create a fix,
- otherwise relevant core team members can be invited to collaborate by
- the coordinator.
-
- * For **Low** and **Medium** severity vulnerabilities it is acceptable
- to develop a fix in public.
- The pull request must be marked with the ``security`` and ``release-blocker``
- labels so that a release is not created without including the fix.
-
- * For **High** and **Critical** severity vulnerabilities the fix must be
- developed privately using GitHub Security Advisories' "Private Forks" feature.
- Core team members can be added to the GitHub Security Advisory via "collaborators"
- to work on the fix together. Once a fix is approved privately and tested,
- a public issue and pull request can be created with
- the ``security`` and ``release-blocker`` labels.
-
-* Once the pull request is merged the advisory can be published. The coordinator will send the advisory by email
- to ``security-announce@python.org`` using the below template. Backport labels must be added as appropriate.
- After the advisory is published a CVE record can be created.
+.. _advisory template: #advisory-email
Handling code signing certificate reports
-----------------------------------------
@@ -212,7 +306,10 @@ These template responses should be used as guidance for messaging
in various points in the process above. They are not required to be sent as-is,
please feel free to adapt them as needed for the current context.
-**Directing to GitHub Security Advisories:**
+.. _submit-using-ghsa:
+
+Submit using GitHub Security Advisories
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. highlight:: none
@@ -220,16 +317,12 @@ please feel free to adapt them as needed for the current context.
Thanks for submitting this report.
We use GitHub Security Advisories for triaging vulnerability reports,
- are you able to submit your report directly to GitHub?
+ please submit your report here:
https://github.com/python/cpython/security/advisories/new
- If you're unable to submit a report to GitHub (due to not having a GitHub
- account or something else) let me know and I will create a GitHub Security
- Advisory on your behalf, although you won't be able to participate directly
- in discussions.
-
-**Rejecting a vulnerability report:**
+Rejecting a vulnerability report
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
@@ -238,35 +331,18 @@ please feel free to adapt them as needed for the current context.
If you are interested in working on this further, you can optionally open a
public issue on GitHub.
-**Accepting a vulnerability report:**
-
-::
-
- Thanks for your report. We've determined that the report
- is a vulnerability. We've assigned {CVE-YYYY-XXXX} and determined
- a severity of {Low,Medium,High,Critical}. Let us know if you disagree
- with the determined severity.
-
- If you would like to be publicly credited for this vulnerability as the
- reporter, please indicate that, along with how you would like to be
- credited (name or organization).
-
- Please keep this vulnerability report private until we've published
- an advisory to ``security-announce@python.org``.
-
-**Advisory email:**
+Advisory email
+~~~~~~~~~~~~~~
::
Title: [{CVE-YYYY-XXXX}] {title}
- There is a {LOW, MEDIUM, HIGH, CRITICAL} severity vulnerability
- affecting {project}.
+ There is a {LOW, MEDIUM, HIGH, CRITICAL} severity vulnerability affecting {project}.
{description}
- Please see the linked CVE ID for the latest information on
- affected versions:
+ Please see the linked CVE ID for the latest information on affected versions:
* https://www.cve.org/CVERecord?id={CVE-YYYY-XXXX}
* {pull request URL}