Security/Firefox/Security Bug Life Cycle/Security Advisories: Difference between revisions
m (Fixing the formatting for "advisory.txt" examples) |
(Note that csectype- keywords need fixing) |
||
| (13 intermediate revisions by 2 users not shown) | |||
| Line 6: | Line 6: | ||
== Process == | == Process == | ||
==== Summary ==== | |||
===== Monday (the week before the release) ===== | |||
# Clone or update https://github.com/MozillaSecurity/security-advisories-scripts | |||
# Clone or update https://github.com/mozilla/foundation-security-advisories-private (next to the other working dir for the following examples) | |||
# Make sure the private repository matches the public repository https://github.com/mozilla/foundation-security-advisories. The public repository should be the source of truth! | |||
# In the working directory, run <code>./gen_queries.py $VERSIONNUMBER</code> to find bugs which could get advisories | |||
# For each bug, determine if it should get an advisory and assign the appropriate whiteboard tag on Bugzilla [[#Determine_what_bugs_will_get_advisories]]. While you're at it make sure the csectype- keywords are set correctly because that is what determines the advisory text. They are described at https://wiki.mozilla.org/Security_Severity_Ratings/Client#csectype-_Keywords. | |||
# Next run <code>./gen_yml.py $VERSIONNUMBER --all --output-path ../foundation-security-advisories/announce/2025</code> (you need to set a Bugzilla API key) | |||
# Fix any errors you encounter - the idea is that we fix e.g. missing categories when we encounter them instead of trying to find them up front. | |||
# If you had to fix something, run it again but add <code>--id $ID</code> to ensure you overwrite the files instead of creating even more | |||
# If you find any odd names you may want to email people and ask them to update their Bugzilla realname to whatever they want in the advisory. | |||
# Ask the Thunderbird folks if they will need advisories. If they do ask them to request a review from you on GH when their PR is ready. | |||
===== Thursday ===== | |||
# Repeat the steps above to get the most recent changes | |||
# Create a PR against the private repo and get a review from the reviewer in the rotation | |||
===== Friday ===== | |||
# Send a mail with the YAML files to the security group (security-group@), to get further review | |||
===== Day Before Release (usually Monday) ===== | |||
# Set up CVE and Bugzilla credentials, (maybe try <code>DRY_RUN=1</code>) | |||
# Run <code>assign_cve_ids</code>, this should reserve IDs and set the alias of each bug in Bugzilla to its CVE ID. See [[#Assign_CVEs]] for more. | |||
# Make a release manager accept the PR. | |||
# Review the Thunderbird PR and make sure it gets merged. | |||
===== Release Day (usually Tuesday) ===== | |||
# Make sure there are no last minute uplifts or other changes. If there are repeat the necessary steps. | |||
# When the actual release happens, make sure a release manager also merges it into the public repo at https://github.com/mozilla/foundation-security-advisories. At that point a GHA should populate the CVEs with the actual data from the YAML files. | |||
# Make sure the CVEs show up at https://www.mozilla.org/en-US/security/advisories/ | |||
# Make sure the CVEs show up at cve.org by searching for a sample. | |||
=== Determine what bugs will get advisories === | === Determine what bugs will get advisories === | ||
| Line 22: | Line 52: | ||
==== Tag them ==== | ==== Tag them ==== | ||
# Query for bugs using the status-firefoxXX (with the release number) flag that are marked as “verified” or “fixed” that also do not have the status-firefoxXY flag for the previous release set to “fixed”, “verified”, “unaffected”, or “disabled” in bugzilla. Additionally, we query on whether the bugs have a “sec-” keyword or are in any security group in Bugzilla. [https://github.com/ | # Query for bugs using the status-firefoxXX (with the release number) flag that are marked as “verified” or “fixed” that also do not have the status-firefoxXY flag for the previous release set to “fixed”, “verified”, “unaffected”, or “disabled” in bugzilla. Additionally, we query on whether the bugs have a “sec-” keyword or are in any security group in Bugzilla. [https://github.com/MozillaSecurity/security-advisories-scripts/blob/main/gen_queries.py I use a script that generates the bugzilla query for a given version.] For example <tt>./gen_queries.py 71</tt> or <tt>./gen_queries.py 71 -v</tt> | ||
# For each bug, decide on an advisory, marking it with a whiteboard tag. A missing whiteboard tag helps us notice when new fixes land late in the release cycle, and in the future the whiteboard tag is useful for tracking when a vulnerability received an advisory. | # For each bug, decide on an advisory, marking it with a whiteboard tag. A missing whiteboard tag helps us notice when new fixes land late in the release cycle, and in the future the whiteboard tag is useful for tracking when a vulnerability received an advisory. | ||
## The whiteboard of the bug is tagged with [adv-mainXX+], [adv-mainXX-], [adv-ESRXX.X+], or [adv-ESRXX.X-] to mark whether an advisory is being created (a ‘+’) or explicitly not being created (a ‘-’) for a given Firefox or Firefox ESR release. | ## The whiteboard of the bug is tagged with [adv-mainXX+], [adv-mainXX-], [adv-ESRXX.X+], or [adv-ESRXX.X-] to mark whether an advisory is being created (a ‘+’) or explicitly not being created (a ‘-’) for a given Firefox or Firefox ESR release. | ||
| Line 29: | Line 59: | ||
=== Write the advisories === | === Write the advisories === | ||
On each bug | We generally do not write individual advisories anymore. If one is necessary, here is the process: On each bug needing an advisory add an attachment with a description of 'advisory.txt'. The file structure is: | ||
Title | Title | ||
| Line 43: | Line 73: | ||
When receiving a foobar message, an attacker could specify in incorrect number of gordons. This can lead to a use-after-free causing a potentially exploitable crash. | When receiving a foobar message, an attacker could specify in incorrect number of gordons. This can lead to a use-after-free causing a potentially exploitable crash. | ||
It's possible to put a - into one of the fields and the scripts will populate it with the auto-generated values. | |||
Advisories are written in the past tense. Typically they're somewhat vague, but they don't have to be. | * Advisories are written in the past tense. Typically they're somewhat vague, but they don't have to be. Note, anyone is allowed to write an advisory for a bug. | ||
* The titles of bugs do *not* use Title Case, they use Sentence Case. | * The titles of bugs do *not* use Title Case, they use Sentence Case. | ||
* The title should be a full sentence. | * The title should be a full sentence. | ||
| Line 63: | Line 84: | ||
* JavaScript not javascript | * JavaScript not javascript | ||
* use-after-free not 'use after free'. | * use-after-free not 'use after free'. | ||
=== Assign CVEs === | === Assign CVEs === | ||
| Line 98: | Line 91: | ||
That script will automatically reserve new CVEs, insert them into the yml file, and set the CVE IDs as aliases on Bugzilla. You can use it by running <tt>pip i && assign_cve_ids</tt> in the root of the repository. You can provide the required credentials through the '''CVE_USER''', '''CVE_ORG''', '''CVE_API_KEY''', '''CVE_ENV''', and '''BUGZILLA_API_KEY''' environment variables. Before running the script, make sure to set the names of the advisories that should get a CVE ID to '''MFSA-RESERVE-{YEAR}-{BUG_ID}''', where '''{YEAR}''' is the year that should be associated with the CVE, and '''{BUG_ID}''' is the id of a Bugzilla bug that should get the CVE ID as an alias. If you do not want to have a alias set for the advisory, use a small unique number instead. If you have used the [[#Generate_and_edit_the_YML_File|'''gen_yml.py''' script from the previous step]] to generate your yml file, the advisories should already have this format. | That script will automatically reserve new CVEs, insert them into the yml file, and set the CVE IDs as aliases on Bugzilla. You can use it by running <tt>pip i && assign_cve_ids</tt> in the root of the repository. You can provide the required credentials through the '''CVE_USER''', '''CVE_ORG''', '''CVE_API_KEY''', '''CVE_ENV''', and '''BUGZILLA_API_KEY''' environment variables. Before running the script, make sure to set the names of the advisories that should get a CVE ID to '''MFSA-RESERVE-{YEAR}-{BUG_ID}''', where '''{YEAR}''' is the year that should be associated with the CVE, and '''{BUG_ID}''' is the id of a Bugzilla bug that should get the CVE ID as an alias. If you do not want to have a alias set for the advisory, use a small unique number instead. If you have used the [[#Generate_and_edit_the_YML_File|'''gen_yml.py''' script from the previous step]] to generate your yml file, the advisories should already have this format. | ||
A noteworthy item is that '''issues that already have had a CVE assigned''' - for example because it's an upstream bug - should | A noteworthy item is that '''issues that already have had a CVE assigned''' - for example because it's an upstream bug - should instead have their identifier set to that CVE. If the issue should have a CVE from another org but we don't have it yet, then it should be set to '''MFSA-TMP-2025-XXXX''' where XXXX is an incrementing number. We strive not to re-ruse these. It is common (usually once or twice a year) for us to request Google to assign a CVE for an issue in an upstream library. The Googler to contact for this is James Zern, and Tom Ritter (among others) can put you in touch. | ||
The CVE ID is unique per bug except for the internal roll-up advisories, which use one CVE ID for a list of bugs. (The CVE assignment process can be complicated because Mitre imposes many rules on CVE assignment and requires communication back in specified data formats when CVEs are assigned. Failure to follow this process can result in Mitre refusing to hand out additional CVE IDs for use.) | The CVE ID is unique per bug except for the internal roll-up advisories, which use one CVE ID for a list of bugs. (The CVE assignment process can be complicated because Mitre imposes many rules on CVE assignment and requires communication back in specified data formats when CVEs are assigned. Failure to follow this process can result in Mitre refusing to hand out additional CVE IDs for use.) | ||
Latest revision as of 12:09, 9 December 2025
Background
This page documents the process to create security advisories for Firefox. If you're looking for what the advisories actually are; you want to go to https://www.mozilla.org/en-US/security/advisories/
The goal is that with this document, and the scripts, anyone with the appropriate access can produce advisories.
Process
Summary
Monday (the week before the release)
- Clone or update https://github.com/MozillaSecurity/security-advisories-scripts
- Clone or update https://github.com/mozilla/foundation-security-advisories-private (next to the other working dir for the following examples)
- Make sure the private repository matches the public repository https://github.com/mozilla/foundation-security-advisories. The public repository should be the source of truth!
- In the working directory, run
./gen_queries.py $VERSIONNUMBERto find bugs which could get advisories - For each bug, determine if it should get an advisory and assign the appropriate whiteboard tag on Bugzilla #Determine_what_bugs_will_get_advisories. While you're at it make sure the csectype- keywords are set correctly because that is what determines the advisory text. They are described at https://wiki.mozilla.org/Security_Severity_Ratings/Client#csectype-_Keywords.
- Next run
./gen_yml.py $VERSIONNUMBER --all --output-path ../foundation-security-advisories/announce/2025(you need to set a Bugzilla API key) - Fix any errors you encounter - the idea is that we fix e.g. missing categories when we encounter them instead of trying to find them up front.
- If you had to fix something, run it again but add
--id $IDto ensure you overwrite the files instead of creating even more - If you find any odd names you may want to email people and ask them to update their Bugzilla realname to whatever they want in the advisory.
- Ask the Thunderbird folks if they will need advisories. If they do ask them to request a review from you on GH when their PR is ready.
Thursday
- Repeat the steps above to get the most recent changes
- Create a PR against the private repo and get a review from the reviewer in the rotation
Friday
- Send a mail with the YAML files to the security group (security-group@), to get further review
Day Before Release (usually Monday)
- Set up CVE and Bugzilla credentials, (maybe try
DRY_RUN=1) - Run
assign_cve_ids, this should reserve IDs and set the alias of each bug in Bugzilla to its CVE ID. See #Assign_CVEs for more. - Make a release manager accept the PR.
- Review the Thunderbird PR and make sure it gets merged.
Release Day (usually Tuesday)
- Make sure there are no last minute uplifts or other changes. If there are repeat the necessary steps.
- When the actual release happens, make sure a release manager also merges it into the public repo at https://github.com/mozilla/foundation-security-advisories. At that point a GHA should populate the CVEs with the actual data from the YAML files.
- Make sure the CVEs show up at https://www.mozilla.org/en-US/security/advisories/
- Make sure the CVEs show up at cve.org by searching for a sample.
Determine what bugs will get advisories
Criteria
- All client bugs that ship in Firefox reported in Bugzilla with a sec-critical, sec-high, sec-moderate, or sec-low rating are normally included in an advisory.
- Exceptions are occasionally made for sec-low rated issues, especially internal reports, deemed too minor for advisory inclusion.
- Internally found memory corruption issues, usually found by developers or members of the fuzzing team, are included in a “roll-up” advisory that is a list of internally found and fixed issues affecting the previous release that were reported by employees or longtime community members. This roll up does not get a detailed advisory but is simply a list of internally found issues.
- Externally reported security bugs with security ratings always receive an advisory outside of the above parameters if they affected a shipped Firefox release.
- ASAN Nightly bugs go into the roll-up advisory.
- Sometimes we know a large library update will fix vulnerabilities, but we don't know _which_ vulnerabilities it fixes (often upstream does not assign CVEs, and we aren't allowed to assign CVEs for them) or if there are vulnerabilities at all (but we suspect there are.) We try to avoid this, but in these cases, it's acceptable to issue a CVE with details like e.g. 'Angle graphics library out of date' - 'An out of date graphics library (Angle) [likely] contained vulnerabilities that could potentially be exploited.'
- Internally-found vulnerabilities that are not simple memory corruption usually get a separate advisory and don't go in the roll-up
- Vulnerabilities that only existed in Nightly or Beta versions do not need an advisory.
Tag them
- Query for bugs using the status-firefoxXX (with the release number) flag that are marked as “verified” or “fixed” that also do not have the status-firefoxXY flag for the previous release set to “fixed”, “verified”, “unaffected”, or “disabled” in bugzilla. Additionally, we query on whether the bugs have a “sec-” keyword or are in any security group in Bugzilla. I use a script that generates the bugzilla query for a given version. For example ./gen_queries.py 71 or ./gen_queries.py 71 -v
- For each bug, decide on an advisory, marking it with a whiteboard tag. A missing whiteboard tag helps us notice when new fixes land late in the release cycle, and in the future the whiteboard tag is useful for tracking when a vulnerability received an advisory.
- The whiteboard of the bug is tagged with [adv-mainXX+], [adv-mainXX-], [adv-ESRXX.X+], or [adv-ESRXX.X-] to mark whether an advisory is being created (a ‘+’) or explicitly not being created (a ‘-’) for a given Firefox or Firefox ESR release.
- [adv-mainXX+r] (and [adv-esrXX+r]) is used to mark bugs that will go into the roll-up advisory.
Write the advisories
We generally do not write individual advisories anymore. If one is necessary, here is the process: On each bug needing an advisory add an attachment with a description of 'advisory.txt'. The file structure is:
Title Reporter Description
for example:
Memory corruption when processing WebRTC messages John Doe When receiving a foobar message, an attacker could specify in incorrect number of gordons. This can lead to a use-after-free causing a potentially exploitable crash.
It's possible to put a - into one of the fields and the scripts will populate it with the auto-generated values.
- Advisories are written in the past tense. Typically they're somewhat vague, but they don't have to be. Note, anyone is allowed to write an advisory for a bug.
- The titles of bugs do *not* use Title Case, they use Sentence Case.
- The title should be a full sentence.
- Function names and objects in the advisory description should be enclosed with <code> tags.
- Description of the bug should not credit/mention the bug reporter again.
- Check the ESR version number for decimal errors (e.g., 78.6000001).
- Do not include IRC nicks in the reporter field.
- JavaScript not javascript
- use-after-free not 'use after free'.
Assign CVEs
Typically done a day or two before the release, assign CVEs to the bugs in bugzilla and in the yml file. This needs to be done by a person with CVE Services credentials and Bugzilla security access, and can be automated with the assign_cve_ids script in the foundation-security-advisories repository.
That script will automatically reserve new CVEs, insert them into the yml file, and set the CVE IDs as aliases on Bugzilla. You can use it by running pip i && assign_cve_ids in the root of the repository. You can provide the required credentials through the CVE_USER, CVE_ORG, CVE_API_KEY, CVE_ENV, and BUGZILLA_API_KEY environment variables. Before running the script, make sure to set the names of the advisories that should get a CVE ID to MFSA-RESERVE-{YEAR}-{BUG_ID}, where {YEAR} is the year that should be associated with the CVE, and {BUG_ID} is the id of a Bugzilla bug that should get the CVE ID as an alias. If you do not want to have a alias set for the advisory, use a small unique number instead. If you have used the gen_yml.py script from the previous step to generate your yml file, the advisories should already have this format.
A noteworthy item is that issues that already have had a CVE assigned - for example because it's an upstream bug - should instead have their identifier set to that CVE. If the issue should have a CVE from another org but we don't have it yet, then it should be set to MFSA-TMP-2025-XXXX where XXXX is an incrementing number. We strive not to re-ruse these. It is common (usually once or twice a year) for us to request Google to assign a CVE for an issue in an upstream library. The Googler to contact for this is James Zern, and Tom Ritter (among others) can put you in touch.
The CVE ID is unique per bug except for the internal roll-up advisories, which use one CVE ID for a list of bugs. (The CVE assignment process can be complicated because Mitre imposes many rules on CVE assignment and requires communication back in specified data formats when CVEs are assigned. Failure to follow this process can result in Mitre refusing to hand out additional CVE IDs for use.)
Release
Before releasing ensure that no last-days uplift happened that would be ommitted. The yml files are checked into git and staged in the private https://github.com/mozilla/foundation-security-advisories-private/ repo. Release management will pull from this repo and commit it to the public https://github.com/mozilla/foundation-security-advisories/ repo which will make them live on the site in moments, as well as publishing the actual CVE contents to CVE Services.