This is an automated email from the ASF dual-hosted git repository. lukaszlenart pushed a commit to branch docs/cve-advisory-mails-from-cve-tool in repository https://gitbox.apache.org/repos/asf/struts.git
commit af5ac9a846110ea9a9b28bec7ed325905ecee8f8 Author: Lukasz Lenart <[email protected]> AuthorDate: Sat Aug 15 06:47:40 2026 +0200 docs(skills): send CVE advisory mails from the ASF CVE tool Advisory mails for S2-070..S2-074 were composed and sent by hand from Gmail. The bodies were already the CVE tool's generated text, but every send failed at least once: one bounced for a [email protected] sender, four bounced for carrying a text/html part, and the re-sends went out with a hand-added [ANN] prefix. sebb and raboof both pointed out on the S2-073 thread that these should go through the 'Send these Emails' button on the record's OSS/ASF Emails tab at cveprocess.apache.org, and that ASF CVE reports do not carry an [ANN] prefix. Mail sent through the tool is moderated automatically; the same text from a personal account waits for a human moderator. The skill already recommended the tool's text but then documented a full Gmail recipe underneath, so the fallback is what got used. Replace the recommendation with an ordered recipe ending in the send button, and demote Gmail to a conditional keyed to the button actually failing. The reason hand-sending looked necessary was a misconfigured field: CNA_private.userslist on the Struts records reads [email protected], so the generated ASF mail addressed announce@ and dev@ and missed [email protected]. Setting that one field is now step 1 of the send and a pre-publication checklist item. Also guard the release [ANN] mail explicitly: that prefix stays on release announcements, and only advisory subjects drop it. Co-Authored-By: Claude Opus 5 <[email protected]> --- .../skills/creating-security-bulletins/SKILL.md | 90 +++++++++++++++------- .../bulletin-template.md | 2 + .claude/skills/releasing-struts/SKILL.md | 3 +- .claude/skills/releasing-struts/release-runbook.md | 15 +++- 4 files changed, 79 insertions(+), 31 deletions(-) diff --git a/.claude/skills/creating-security-bulletins/SKILL.md b/.claude/skills/creating-security-bulletins/SKILL.md index 864908c1c..3d83e99b4 100644 --- a/.claude/skills/creating-security-bulletins/SKILL.md +++ b/.claude/skills/creating-security-bulletins/SKILL.md @@ -163,34 +163,66 @@ Publication is clearing them **completely** — read *and* update, both empty, m already-published bulletin. Verify with an unauthenticated fetch of the public URL, not with the API's response: the tool reporting success is not the page being readable. -## Announcing it: the mail is text/plain, or it does not arrive +## Announcing it: press the button on the CVE record -Once the page is public the advisory goes to the lists. **The mail carries one `text/plain` -part and nothing else.** A `text/html` part is a delivery failure — `[email protected]` -rejects it permanently: +Once the page is public the advisory goes out **from the CVE record**, not from a mailbox. +Every record on `cveprocess.apache.org` carries an *OSS/ASF Emails* tab — +`https://cveprocess.apache.org/cve5/CVE-YYYY-NNNNN#email` — holding two finished mails, one +for `oss-security` and one for the ASF lists, generated from the record's own affected +ranges, description, credit and references. A single **`Send these Emails`** button sits at +the foot of the tab, and both mails point at it — *"Use the button below to send these +mails, or copy, paste, and send the email yourself."* -``` -ezmlm-reject: fatal: Sorry, a message part has an unacceptable MIME Content-Type: 'text/html' (#5.2.3) -``` +The send is four steps, in order: -**Do not rely on a bounce to catch it.** On the S2-070 run, 2026-08-14, one send was rejected -by `[email protected]` and *accepted* by `[email protected]`. The HTML advisory reached -the user list. A partial failure looks like success in the Sent folder. +1. **Set `userslist` to `[email protected]`** — the field is in the *Editor* tab, or as + `CNA_private.userslist` on the *Source* tab, which accepts the record as raw JSON. It is + labelled *"This is your project list such as users@ where you also want security + announcement emails go to"*, and it is what puts the Struts user list on the ASF mail. +2. **`SAVE`.** The mails are regenerated from the saved record, not from the form. +3. **Re-read both mails on the *OSS/ASF Emails* tab.** They are the deliverable — read them + as closely as you read the bulletin. +4. **Press `Send these Emails`.** + +**Take the subject the tool generates, unedited** — `CVE-YYYY-NNNNN: Apache Struts: <title>`. +No `[ANN]` prefix: that prefix belongs to *release* announcements, and ASF CVE reports do not +carry it. No `- S2-XXX` suffix either; the bulletin reaches readers as a `References:` line. + +**Why the button rather than a mailbox.** Mail sent through the tool is moderated +automatically, while the same text from a personal account waits for a human moderator. It +also cannot get the `text/plain` contract or the sender identity wrong — which is the entire +class of failure below. + +Both points are sebb's, on the S2-073 announcement thread, 2026-08-14. -Two unrelated defects bounced that morning, each from a different list: +**Expect a delay either way, and do not read it as a failed send.** The tab warns that +*"ASF announcement mailing lists are moderated. It may take some hours/days before your +email will be published."* Silence on the archives an hour later is moderation, not a +bounce. -| Defect | What the list says | +### The failure this replaces + +On 2026-08-14 all five advisories were sent by hand from Gmail. Every one failed at least +once: + +| Send | Outcome | |---|---| -| A `text/html` part | `unacceptable MIME Content-Type: 'text/html' (#5.2.3)` | -| Wrong sender identity | `Must be sent from an @apache.org address.` | +| S2-070, from the personal Gmail identity | Bounced — `Must be sent from an @apache.org address.` | +| S2-071…074, to `user@` with `announce@` in Cc/Bcc | Bounced — `unacceptable MIME Content-Type: 'text/html' (#5.2.3)` | +| The re-sends, to `announce@` alone | Delivered, subjects hand-prefixed `[ANN] ` | + +The *bodies* were already the tool's generated text. Only the **sending** was hand-rolled, +and every one of those failures came from the sending. `CNA_private.emailed` on those +records is still `null`. -**The CVE tool generates both mails — use them.** Each record on `cveprocess.apache.org` has an -*OSS/ASF Emails* tab holding a finished `oss-security` mail and a finished ASF-lists mail, built -from the record's own affected ranges, description, credit and references, with send buttons -that go through ASF infrastructure rather than a personal mailbox. Copying that text is how the -mail stays consistent with the CVE record; composing a fresh one is how the two drift. +**A bounce is not a reliable alarm.** That morning one HTML send was rejected by +`[email protected]` and *accepted* by `[email protected]`. The HTML advisory reached +the user list. A partial failure looks like success in the Sent folder. + +### If the button is genuinely unavailable -If you draft in Gmail instead, the deliverable is three things and is incomplete without any: +Only when the button itself fails — it errors, or the record will not save. Moderation delay +is not unavailability. Then the mail is three things and is incomplete without any: 1. A draft with To, Bcc, Subject and `body`. **Never `htmlBody`** — and passing `body` alone does not make the mail plain text; Gmail generates the HTML part itself on send. @@ -198,12 +230,9 @@ If you draft in Gmail instead, the deliverable is three things and is incomplete 3. The sending instruction in your handover: **plain-text mode on** (⋮ → *Plain text mode*), paste the file over the body, send from the `@apache.org` identity. -The `oss-security` copy is a separate mail with no Cc and no Bcc — not the ASF mail with an -extra recipient. - -**Recipients are not interchangeable.** The tool's ASF mail addresses `[email protected]` and -`dev@`; Struts practice adds `[email protected]`, which is the list operators actually -read. `[email protected]` takes only `@apache.org` senders. +Copy the recipients and subject off the tool's tab rather than composing them. The +`oss-security` copy is a separate mail with **no Cc and no Bcc** — not the ASF mail with an +extra recipient — and `[email protected]` accepts only `@apache.org` senders. ## Start from the template, never from a previous bulletin @@ -237,7 +266,9 @@ Read the whole page and rewrite it; do not patch the fields you happen to notice - Publishing without re-checking restrictions - Treating an API success as proof the page is publicly readable - `htmlBody` passed to the draft tool, for any reason -- An announcement composed from scratch when the CVE record's *OSS/ASF Emails* tab holds one +- An advisory sent from a mailbox while the record's `Send these Emails` button is available +- `Send these Emails` pressed before `userslist` is set to `[email protected]` and saved +- `[ANN]`, an S2-XXX suffix, or any other hand-edit to the subject the tool generated - A draft handed over without the plain-text-mode instruction and the body file - A severity rating chosen by feel, or by reachability alone, without checking it against the published scale - Rating something Low because the feature is opt-in — opt-in is the definition of Moderate @@ -263,4 +294,7 @@ Read the whole page and rewrite it; do not patch the fields you happen to notice | "I read the page a few minutes ago" | Someone else may have written to it since. Re-fetch, then write. There is no conflict warning. | | "I passed `body`, not `htmlBody`, so it's plain text" | Gmail generates the HTML part itself on send. The format is decided in the compose window. | | "It reached the lists, so the format was fine" | One list accepted the same message another rejected. Check every recipient, not the Sent folder. | -| "Writing the mail myself is quicker than opening the CVE tool" | The tool's text is generated from the record. Hand-written text is how the mail and the CVE drift apart. | +| "I copied the tool's text, so the mail is fine" | The text was never what failed. Sending by hand is. Press the button. | +| "The tool doesn't mail `user@`, so I'll send it myself" | It does once `userslist` says so. One field on the record, not a parallel process. | +| "`[ANN]` marks it as an announcement" | ASF CVE reports don't carry it. The tool's subject *is* the subject. | +| "Sending it myself is quicker than pressing the button" | It is slower end to end: a personal-account mail waits for a human moderator, the tool's does not. | diff --git a/.claude/skills/creating-security-bulletins/bulletin-template.md b/.claude/skills/creating-security-bulletins/bulletin-template.md index abb1efde5..d50524dea 100644 --- a/.claude/skills/creating-security-bulletins/bulletin-template.md +++ b/.claude/skills/creating-security-bulletins/bulletin-template.md @@ -117,6 +117,8 @@ but make it deliberately and record which way you went. now, not at drafting time. - [ ] The fixed release is out and accepted. - [ ] Restrictions are lifted only at the coordinated publication moment. +- [ ] The CVE record's `CNA_private.userslist` reads `[email protected]` and is saved, + so `Send these Emails` on the *OSS/ASF Emails* tab reaches the Struts user list. ## Storage-format skeleton diff --git a/.claude/skills/releasing-struts/SKILL.md b/.claude/skills/releasing-struts/SKILL.md index b94beedd5..052aedeaa 100644 --- a/.claude/skills/releasing-struts/SKILL.md +++ b/.claude/skills/releasing-struts/SKILL.md @@ -27,7 +27,7 @@ the judgement. | 4 | Vote | 72 h elapsed, three binding `+1`, result mail sent | | 5 | Promote | Nexus repo released, `dist/dev` → `dist/release`, 24 h rsync waited | | 6 | Publish | Site PR merged, GitHub release un-flagged, `[ANN]` mail delivered | -| 7 | Advisories | Bulletins public, CVE records filled, advisory mails delivered | +| 7 | Advisories | Bulletins public, CVE records filled, advisory mails sent from the CVE tool | Phase 7 only exists when the release carries a security fix, and *publishing* the advisory is **strictly after** phase 6 — see *Security work is a separate clock* below. Writing the bulletin @@ -144,5 +144,6 @@ the site. | "The vote passed, so it's released" | Nexus release, dist move and the mirror wait all come after. | | "I'll announce now and fix the site after" | The announcement links the site. Merge the site PR first. | | "The 6.x fix is the same change, so one announcement covers both" | Two artifacts, two downloads, two sets of affected users. | +| "The advisory is an announcement, so it gets `[ANN]` too" | `[ANN]` is for releases. CVE reports take the CVE tool's subject unedited. | | "The pom says 7.3.1-SNAPSHOT, so this is 7.3.1" | The placeholder is not a decision. Semver impact decides. | | "The cwiki page is the official process" | It is the 2017 process. Where they disagree, this skill is current. | diff --git a/.claude/skills/releasing-struts/release-runbook.md b/.claude/skills/releasing-struts/release-runbook.md index 1985ed611..bd0c1151b 100644 --- a/.claude/skills/releasing-struts/release-runbook.md +++ b/.claude/skills/releasing-struts/release-runbook.md @@ -242,6 +242,9 @@ Publishing is the merge. There is no separate deploy step and no svn. ### The `[ANN]` mail +This is the **release** announcement, and it keeps its `[ANN]` prefix. Advisory mails are a +different mail with a different subject convention — see phase 7. + ✔ Recipients, from the 7.3.0 and 6.11.0 announcements: ``` @@ -274,8 +277,16 @@ bulletin itself was almost certainly written when the report was triaged, long b release existed. **`creating-security-bulletins`** owns all of it: unrestricting the bulletin, the CVE record on -<https://cveprocess.apache.org>, and the advisory mails from that record's *OSS/ASF Emails* tab. -Follow that skill from here; it is not a step in this runbook. +<https://cveprocess.apache.org>, and the advisory mails. Follow that skill from here; it is not +a step in this runbook. + +✔ **The advisory mails are sent by the `Send these Emails` button** on the record's +*OSS/ASF Emails* tab (`.../cve5/CVE-YYYY-NNNNN#email`), after `CNA_private.userslist` is set to +`[email protected]` and saved. Not from a mailbox: the tool's mail is auto-moderated and +cannot get the sender identity or the `text/plain` contract wrong. + +✔ **Advisory subjects carry no `[ANN]`** — take the tool's `CVE-YYYY-NNNNN: Apache Struts: …` +unedited. The prefix belongs to the release mail above, not to CVE reports. The order that matters here: the CVE record goes `RESERVED → DRAFT → READY`, and **READY is the last state a PMC sets**. ASF Security submits it to the CVE Program and sets `PUBLIC`, so
