ワンクリックで
sec-approval
// Help prepare a Firefox security approval request by analyzing local commits/changes and drafting answers to the sec-approval questionnaire. Use when setting sec-approval? on a Bugzilla bug.
// Help prepare a Firefox security approval request by analyzing local commits/changes and drafting answers to the sec-approval questionnaire. Use when setting sec-approval? on a Bugzilla bug.
| name | sec-approval |
| description | Help prepare a Firefox security approval request by analyzing local commits/changes and drafting answers to the sec-approval questionnaire. Use when setting sec-approval? on a Bugzilla bug. |
| argument-hint | [bug-id] [path-to-bug-report] |
| allowed-tools | ["Bash(git:*)","Bash(jj:*)","Bash(searchfox-cli:*)","Bash(bmo-to-md:*)","Bash(python3:*)","Read","Grep","Glob","AskUserQuestion","WebFetch","Write"] |
Dependencies and Bugzilla API key setup live in
README.md. Point the user there ifbmo-to-mdorbmo-sec-approval --check-authfails.
This skill has two phases:
Arguments: $0
Parse the arguments: the first token that looks like a number is the bug ID,
and any token that contains a / (path separator) is the bug report path.
Both are optional and may appear in either order.
Security bugs are private and cannot be fetched via the MCP tool
mcp__moz__get_bugzilla_bug — it will always fail for sec-* bugs. Use the
following priority order:
bmo-to-md (look for summary.md
or bug-<id>.md).bmo-to-md to download the report:
bmo-to-md is installed: run bmo-to-md --help. If not
found, ask the user to install it: cargo install bmo-to-md
(see https://github.com/padenot/bmo-to-md).python3 .claude/skills/sec-approval/bmo-sec-approval --check-auth
If it fails, ask the user to store their key in
~/.config/bugzilla/config.toml (see Step 6, item 1 for instructions).bmo-to-md -o /tmp/bug-<id> -a <bug_id>bmo-to-md fails, stop and report to the user.bmo-to-md). If they provide a path, read it. If
they provide a bug ID, go to step 2. If neither, proceed without bug
context (the compliance audit can still run on the patch alone, but the
questionnaire will need the user to supply missing information manually).sec-* keyword (sec-critical, sec-high,
sec-moderate, sec-low) and the status-firefox* flags.Determine which VCS is in use and read the relevant commits:
# Check if using jj or git
jj --version 2>/dev/null && echo "jj" || echo "git"
If jj:
jj log -T builtin_log_detailed -r 'trunk()..@'
jj diff -r 'trunk()..@'
If git:
git log --oneline origin/main..HEAD
git diff origin/main..HEAD
Collect:
Audit the patch against every rule from the Fixing Security Bugs guidelines. Work through each check below. For each one, report PASS or FAIL with specifics. If any check fails, present concrete fixes and ask the user to resolve them before moving to Phase 2.
Commit messages must not contain any of the following:
If a commit message fails: suggest a generic rewrite. Examples:
Fix use-after-free in MediaDecoder::ShutdownImprove lifetime management in MediaDecoderFix heap buffer overflow when parsing VP9Add validation for buffer size in VP9 decoderPrevent XSS in content processStrengthen input sanitization in content processOmitting a detailed commit message entirely is acceptable — details should go in the private bug comment instead.
Inline comments in the diff must not:
// See H265.cpp:651)// Without this check, an attacker could trigger X by doing Y)If comments fail: suggest removing them or rewriting them as generic correctness/robustness comments. Security context belongs in the private bug, not in the source.
New or renamed variables, functions, classes, or constants in the diff must not reveal the vulnerability class or attack vector:
fixUAFBuffer, preventOverflow, sanitizeXSSInputbuffer, validateSize, sanitizeInputkMaxAllocBeforeOOB, gNullDerefGuardkMaxAlloc, gGuardIf identifiers fail: suggest neutral renames that describe the correctness purpose, not the security purpose. The vulnerability context belongs in the private bug.
Tests included in the patch must not:
test_uaf_in_foo.html,
test_overflow_parser.js)Additionally, verify the test-landing policy:
in-testsuite flag to ?.If tests fail: suggest renaming, sanitizing test content, or splitting tests into a deferred follow-up.
Check whether the user has pushed (or plans to push) to Try:
Ask the user about their Try push status.
Review whether the fix can be plausibly framed as a non-security change (performance improvement, correctness fix, code cleanup). The goal is to reduce the identifiability of the security fix:
This is advisory — report observations but do not block on it.
Present a summary table:
| Check | Status | Details |
|---|---|---|
| Commit messages | PASS/FAIL | ... |
| Code comments | PASS/FAIL | ... |
| Identifiers | PASS/FAIL | ... |
| Test cases | PASS/FAIL | ... |
| Try server | PASS/FAIL/N/A | ... |
| Patch obfuscation | Advisory | ... |
Then present the checklist for the user to confirm:
If any check is FAIL: present the specific violations with suggested fixes. Ask the user if they want help fixing them now. Re-audit after fixes.
This is a hard gate. Ask the user to confirm all checklist items pass before proceeding. Do not proceed to Phase 2 until Checks 1–5 all pass and the user gives explicit approval to continue.
Before drafting the questionnaire, check if the patch qualifies for automatic
approval (i.e., no explicit sec-approval needed):
unaffected, and the vulnerability only shipped in Nightly buildsIf either condition is met, inform the user they may be able to land without explicit approval. Ask if they still want to prepare the questionnaire (useful for sec-high/sec-critical, or when in doubt).
Work through all questions systematically by examining the diff and commit messages gathered in the Preliminary step.
Question: "How easily could an exploit be constructed based on the patch?"
Analyze:
Rate as one of:
Always open the answer with one of "Easy.", "Moderate.", or "Difficult.", followed by 2-3 sentences of justification. Base the answer on the patch itself — what the fix reveals about the vulnerable code path — and on whether an attacker could recreate the conditions using only publicly available web APIs.
Question: "Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?"
By this point, Phase 1 should have already caught and resolved any bulls-eyes. Confirm that:
Report the current state — ideally "No, the patch has been reviewed for information leaks."
Question: "Which branches (beta, release, and/or ESR) are affected by this flaw, and do the release status flags reflect this affected/unaffected state correctly?"
Fetch the current release calendar to determine which versions are on each channel:
WebFetch: https://whattrainisitnow.com/calendar/
Extract the current Nightly, Beta, Release, and ESR version numbers.
Check the current Firefox version from the local tree:
cat config/milestone.txt
Check status-firefox* flags from the bug (if fetched). If not available,
inspect the code history to find when the vulnerable code was introduced:
If git:
git log --oneline --follow -S "<key_symbol>" -- <affected-file> | head -10
If jj:
jj log -r 'ancestors(trunk())' -T builtin_log_oneline -p -s -- <affected-file> | head -50
Cross-reference with the status-firefoxNN: affected/unaffected/fixed flags
on the bug if available.
Verify reachability on each branch. The vulnerable code may exist on a branch but be unreachable if it is gated behind a preference or feature flag that is disabled on that branch. For each affected ESR and release branch:
Check the pref/flag value on the branch itself — do not assume the current trunk value applies to older branches:
# Example: check a pref on each ESR branch
git show upstream/esr115:<path-to-pref-file> | grep -A10 '<pref-name>'
git show upstream/esr128:<path-to-pref-file> | grep -A10 '<pref-name>'
git show upstream/esr140:<path-to-pref-file> | grep -A10 '<pref-name>'
Check that the vulnerable code exists on the branch — it may have been added after the branch point:
git show upstream/esr115:<affected-file> 2>&1 | head -3
Determine when the feature was enabled — find the commit that changed the pref from disabled to enabled, and check which branches contain it:
git log --all --oneline --grep='<enable-bug>' -- <pref-file>
git branch --all --contains <enable-commit>
A branch is not affected if the pref is false or @IS_NIGHTLY_BUILD@
on release builds, even if the vulnerable code exists. Clearly state in the
answer which branches are affected and which are not, with the reason (e.g.,
"ESR 128: not affected — WebCodecs disabled by default, value: @IS_NIGHTLY_BUILD@").
If no regression range is identified and no pref gate exists, assume the worst — all supported branches are affected.
Use this answer format: "Introduced in Firefox 118 (Bug XXXXXXX). Affects Nightly (150), Beta (149), Release (148), and ESR 140. ESR 128 and ESR 115 are not affected: the feature is disabled by default on those branches."
Question: "If not all supported branches, which bug introduced the flaw?"
Only needed if Q3 shows some branches are unaffected. Find the introducing commit:
If git:
git log --oneline -S "<key_symbol>" -- <affected-file> | head -10
git blame -L <line>,<line> <affected-file>
If jj:
jj log -r 'ancestors(trunk())' -T builtin_log_oneline -s -- <affected-file> | head -30
jj annotate <affected-file>
Report the bug number or commit that introduced the flaw. If the vulnerable code was introduced in one bug but only became reachable due to a later bug (e.g., a feature flag being enabled), report both:
This distinction matters for determining which branches actually need a fix versus which are technically vulnerable but unexploitable.
Questions (two separate bullets in the output):
Ask the user:
Note: backports to ESR require separate approval — mention this if ESR is affected.
Question: "How likely is this patch to cause regressions; how much testing does it need?"
Assess:
Rate as:
Question: "Is the patch ready to land after security approval is given?"
Answer Yes or No. Consider whether:
Question: "Is Android affected?"
Answer Yes, No, or Unknown. Check whether:
gfx/, dom/media/, or other shared directories, it is
likely Android-affectedGenerate the complete text using the same format that Bugzilla auto-generates
for sec-approval requests. The comment will be posted with is_markdown: true
so Markdown is rendered on Bugzilla. Use this exact format:
### Security Approval Request
* **How easily could an exploit be constructed based on the patch?**: <answer>
* **Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?**: <answer>
* **Which branches (beta, release, and/or ESR) are affected by this flaw, and do the release status flags reflect this affected/unaffected state correctly?**: <answer>
* **If not all supported branches, which bug introduced the flaw?**: <answer — or "N/A">
* **Do you have backports for the affected branches?**: <answer>
* **If not, how different, hard to create, and risky will they be?**: <answer>
* **How likely is this patch to cause regressions; how much testing does it need?**: <answer>
* **Is the patch ready to land after security approval is given?**: <Yes/No>
* **Is Android affected?**: <Yes/No/Unknown>
*Drafted with the assistance of Claude Code — reviewed and approved by the patch author.*
Keep answers factual, specific, and concise. Each answer follows the **:
on the same line as a single flowing sentence or paragraph. Do not reveal
more about the vulnerability than necessary.
Present to the user:
Ask the user if they want to revise any answer before finalizing.
After the user confirms they are satisfied with the questionnaire answers,
generate a markdown file at the repository root named
sec-approval-bug-<bug_id>.md (e.g., sec-approval-bug-1234567.md).
If no bug ID is available, use sec-approval.md.
The file must use the exact same markdown format as the questionnaire drafted in Step 3 (the Bugzilla auto-generated format):
### Security Approval Request
* **How easily could an exploit be constructed based on the patch?**: <answer>
* **Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?**: <answer>
* **Which branches (beta, release, and/or ESR) are affected by this flaw, and do the release status flags reflect this affected/unaffected state correctly?**: <answer>
* **If not all supported branches, which bug introduced the flaw?**: <answer>
* **Do you have backports for the affected branches?**: <answer>
* **If not, how different, hard to create, and risky will they be?**: <answer>
* **How likely is this patch to cause regressions; how much testing does it need?**: <answer>
* **Is the patch ready to land after security approval is given?**: <answer>
* **Is Android affected?**: <answer>
*Drafted with the assistance of Claude Code — reviewed and approved by the patch author.*
Use the Write tool to create this file, then inform the user of the file path.
This step only applies when sec-approval is required. Do NOT offer to post if the bug qualifies for automatic approval (see Step 1):
unaffected: no sec-approval needed.For these cases, inform the user the questionnaire file is available for their records but does not need to be posted. Skip the rest of this step.
For sec-high, sec-critical, or unrated bugs (assume worst-case):
ask the user whether they want to post the questionnaire directly to Bugzilla
and request sec-approval? on the attachment.
If the user agrees:
Check API key: run the auth check — never read or print the key itself:
python3 .claude/skills/sec-approval/bmo-sec-approval --check-auth
If it fails, offer the user two options and stop:
mkdir -p ~/.config/bugzilla && cat > ~/.config/bugzilla/config.toml << 'EOF'
api_key = "YOUR_KEY"
EOF
chmod 600 ~/.config/bugzilla/config.toml
export BMO_API_KEY="YOUR_KEY"
Tell the user to replace YOUR_KEY with their Bugzilla API key from
https://bugzilla.mozilla.org/userprefs.cgi?tab=apikey. If they already
have bmo-to-md configured, the key in ~/.config/bmo-to-md/config.toml
is also picked up automatically.
Identify the attachment: the sec-approval flag must be set on the Phabricator attachment (the patch revision), not on the bug itself.
First, extract Phabricator revision IDs from the local commits gathered in the Preliminary step:
If git:
git log origin/main..HEAD --format=%B | grep -oP 'Differential Revision:.*/(D\d+)' | sed 's|.*Differential Revision:.*/||'
If jj:
jj log -r 'trunk()..@' -T description | grep -oP 'Differential Revision:.*/(D\d+)' | sed 's|.*Differential Revision:.*/||'
Then fetch all active Phabricator attachments from Bugzilla:
python3 .claude/skills/sec-approval/bmo-sec-approval <bug_id> --list
This prints each attachment with its attachment ID, Phabricator revision ID, summary, and existing flags.
Cross-reference the revisions found in the commits with the attachments from Bugzilla. Present a table like:
| Revision | Attachment ID | Summary | Flags | In local commits? |
|---|---|---|---|---|
| D290715 | 9560245 | Bug 2022604 - ... | Yes | |
| D290800 | 9560300 | Bug 2022604 - ... | No |
Dry-run first: always run with --dry-run so the user can verify before
posting:
python3 .claude/skills/sec-approval/bmo-sec-approval \
<bug_id> sec-approval-bug-<bug_id>.md --attachment <id> --dry-run
Show the dry-run output to the user and ask for confirmation.
Post: after the user confirms, run without --dry-run:
python3 .claude/skills/sec-approval/bmo-sec-approval \
<bug_id> sec-approval-bug-<bug_id>.md --attachment <id>
Report: show the user the Bugzilla URL from the script output.
sec-critical, sec-high, sec-moderate,
sec-low, sec-other, sec-wantsec-high and sec-critical
bugs that land before a public releaseHelp prepare a Firefox uplift approval request (Beta, Release, and/or ESR) by checking whether patches are already on the bug, auditing sanitization once for sec-* bugs, and drafting the approval comment per https://wiki.mozilla.org/Release_Management/Uplift_rules. Use after a fix is ready and needs to ride into a stabilization branch. May or may not follow sec-approval (sec-moderate typically skips sec-approval but may still need uplift).
Firefox bug triage assistant for media, web conferencing, and graphics related issues.
Generate technical documentation for a specified technology domain with optional customization.
Generate or modify Firefox mozconfig build configuration files. Use when the user asks to create a mozconfig, configure a build, set up ASan/TSan/debug builds, or match try server configurations.
Firefox bug triage assistant for determining if a bug severity rating of S1 or S2 is warranted, and to gather information for triaging and prioritization.
Launch a local web server and open a browser page listing all bug triage reports in ./reports, with live JS text filtering.