This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow-steward.git
The following commit(s) were added to refs/heads/main by this push:
new e0ade0a feat(security-issue-invalidate): notification audit-trail +
GHSA-write-access split (#379)
e0ade0a is described below
commit e0ade0af1a78dcae9943c37e989f781072227d31
Author: Jarek Potiuk <[email protected]>
AuthorDate: Sat May 30 15:54:42 2026 +0200
feat(security-issue-invalidate): notification audit-trail +
GHSA-write-access split (#379)
Three refinements to the reporter-notification rule for close-as-invalid
trackers, all driven by 2026-05-29/30 ASF-Security (Arnout Engelen)
feedback + a session-wide audit:
1. CVE-ID in body for `duplicate` dispositions. Per Arnout's 2026-05-29
message in the Kyuubi SSRF context: when closing as duplicate, the
reply body MUST name the canonical CVE-YYYY-NNNNN so the ASF Security
team's dedup workflow can group the threads. For via-forwarder mode
the CVE-ID goes inside the paste-ready reporter-voice block per the
new asf-relay.md shape.
2. Two named exceptions where no Gmail draft is owed:
- Internal-audit-finding imports (airflow-core-findings.md or
equivalent) — no inbound security@ thread, no reporter to notify.
- GHSA-relay-only reports where the operator HAS GHSA-write access
on <upstream> — the GHSA advisory itself carries the closure.
3. New case: GHSA-relay-only reports where the operator LACKS
GHSA-write access. The GHSA channel is not self-sufficient; the
closure must be relayed via ASF Security so the forwarder can post
the closing comment on the GHSA on our behalf. Draft an ASF-relay
message per asf-relay.md (clickable GHSA URL + paste-ready block in
reporter voice + canonical CVE-ID when duplicate).
The Step 5e rollup terminal entry now requires one of seven explicit
notification states; ambiguous channels surface as a blocker so the
tracker cannot close without an audit-trail line.
Audit context: spot-checked 7 of 11 Jan-Apr 2026 closed-invalid
trackers on airflow-s/airflow-s; every confirmed case had a direct
rejection reply sent. The rule has been followed in practice — this
codifies it so it cannot slip going forward.
Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
---
.claude/skills/security-issue-invalidate/SKILL.md | 81 +++++++++++++++++++++--
1 file changed, 75 insertions(+), 6 deletions(-)
diff --git a/.claude/skills/security-issue-invalidate/SKILL.md
b/.claude/skills/security-issue-invalidate/SKILL.md
index 512136a..76c707a 100644
--- a/.claude/skills/security-issue-invalidate/SKILL.md
+++ b/.claude/skills/security-issue-invalidate/SKILL.md
@@ -516,10 +516,56 @@ informational, not a blocker).
### 5d — Email draft (security@-imported only)
Skip this entire substep when the import path detected in Step 2
-is *PR-imported*.
-
-For `security@`-imported trackers, the invalidation reply is one
-of the five [forwarder-routing-policy
milestones](../../../docs/security/forwarder-routing-policy.md#milestones--do-relay)
+is *PR-imported*. Two additional skip cases — both **must be
+named explicitly** in the Step 5e rollup terminal entry:
+
+- **Internal-audit-finding imports.** The tracker was
+ imported from a project-internal markdown audit
+ (`airflow-core-findings.md` or equivalent) with no inbound
+ `security@` thread. No reporter to notify. The rollup
+ terminal entry MUST state: *"No reporter notification owed
+ — internal audit finding, no inbound `security@` thread."*
+- **GHSA-relay-only reports — operator with GHSA write
+ access.** The only inbound channel is a GHSA advisory and
+ the tracker carries no Gmail thread. The operator running
+ the skill IS a maintainer with write access to the
+ `<upstream>` repo's GHSA (verify via
+ `gh api repos/<upstream>/security-advisories/<GHSA-ID>`
+ returning a non-403). In that case the GHSA advisory
+ itself IS the closure communication: post a closing
+ comment on the GHSA, mark the advisory as withdrawn or
+ closed informational, and record in the rollup terminal
+ entry: *"GHSA-relay-only reporter channel
+ (GHSA-XXXX-XXXX-XXXX) — closure communicated as GHSA
+ comment `<URL>` / advisory state set to
+ `<withdrawn|informational>`; no Gmail reply needed."*
+- **GHSA-relay-only reports — operator without GHSA write
+ access.** Same intake (GHSA-only, no Gmail thread) but the
+ operator cannot comment on / modify the GHSA — the API
+ call above returns 403, or the operator is running from a
+ triager account that does not hold GHSA-write membership.
+ In that case the GHSA channel is **not** self-sufficient;
+ the closure must be relayed via ASF Security so Arnout
+ Engelen (or another `@apache.org` forwarder with the
+ required GHSA-write permissions) can post the closure
+ comment / state-change on our behalf. Draft an
+ ASF-relay-shape message per
+ [`tools/gmail/asf-relay.md`](../../../tools/gmail/asf-relay.md):
+ recipient is `[email protected]` (or the named forwarder
+ who relayed the original GHSA report); body includes the
+ clickable GHSA URL on its own line + a paste-ready block
+ in the reporter's voice with the invalid-disposition
+ rationale + canonical CVE-ID (when `duplicate`) for the
+ forwarder to post on the GHSA. Record in the rollup
+ terminal entry: *"GHSA-relay-only reporter channel
+ (GHSA-XXXX-XXXX-XXXX); operator lacks GHSA-write access on
+ `<upstream>`. ASF-relay draft `<draftId>` queued to
+ `<[email protected]>` requesting they post the closure
+ comment on the GHSA on our behalf — awaiting user review."*
+
+For every other `security@`-imported tracker, the invalidation
+reply is one of the five
+[forwarder-routing-policy
milestones](../../../docs/security/forwarder-routing-policy.md#milestones--do-relay)
(*Report assessed as invalid*) — so the draft fires in both
direct-reporter and via-forwarder modes; the policy only changes
the **recipient** and the **body shape**.
@@ -561,6 +607,18 @@ the **recipient** and the **body shape**.
private; the reporter has no access; references would
leak. Cite the public Security Model and any public CVEs
instead.
+ - **Canonical CVE-ID for `duplicate` dispositions.** When
+ the close is a `duplicate` of an existing CVE record, the
+ body MUST name the canonical `CVE-YYYY-NNNNN` ID
+ verbatim — e.g. *"This is the same root cause as
+ `CVE-2026-XXXXX` which we already track and ship the fix
+ for in `apache-airflow` X.Y.Z."* This lets the ASF
+ Security team's dedup workflow group the two threads
+ (per Arnout Engelen's 2026-05-29 ASF-Security ask in the
+ Kyuubi SSRF context). For via-forwarder mode this
+ additionally goes inside the *paste-ready block in the
+ reporter's voice* per the
+ [asf-relay.md shape](../../../tools/gmail/asf-relay.md).
- **Polite-but-firm.** Per
[`AGENTS.md`](../../../AGENTS.md#tone-polite-but-firm--no-room-to-wiggle), state
the team's position once, clearly, with reasoning. Do not
@@ -601,11 +659,22 @@ upsert recipe). Shape:
**Canned response selected:** *<canned section name>* in
[`canned-responses.md`](https://github.com/<tracker>/blob/<tracker-default-branch>/<project-config>/canned-responses.md#<anchor>).
-**Reporter notification:** <one of:>
-- **`security@`-imported:** Gmail draft `<draftId>` created on thread
`<threadId>` — awaiting user review.
+**Reporter notification:** <one of — required line, never omit:>
+- **`security@`-imported, direct-reporter mode:** Gmail draft `<draftId>`
created on thread `<threadId>` anchored at message `<messageId>` — awaiting
user review.
+- **`security@`-imported, via-forwarder mode (ASF-relay):** ASF-relay draft
`<draftId>` to `<[email protected]>` on thread `<threadId>` per
[`asf-relay.md`](https://github.com/apache/airflow-steward/blob/main/tools/gmail/asf-relay.md)
shape (clickable URL + paste-ready reporter-voice block) — awaiting user
review.
+- **`security@`-imported, `duplicate` disposition:** *(same as direct or
via-forwarder above; the draft body MUST name the canonical CVE-ID per Step
5d).*
+- **No notification owed — internal audit finding:** Tracker imported from
project-internal markdown audit (`<source-markdown>`), no inbound `security@`
thread, no reporter to notify.
+- **No Gmail draft owed — GHSA-relay-only, operator has GHSA-write access:**
GHSA-relay-only reporter channel (`GHSA-XXXX-XXXX-XXXX`); closure communicated
as GHSA comment `<URL>` / advisory state set to `<withdrawn|informational>`. No
Gmail reply needed.
+- **ASF-relay draft owed — GHSA-relay-only, operator lacks GHSA-write
access:** GHSA-relay-only channel (`GHSA-XXXX-XXXX-XXXX`); operator's account
does not have GHSA-write on `<upstream>`. ASF-relay draft `<draftId>` queued to
`<[email protected]>` requesting they post the closure comment on the GHSA
on our behalf — awaiting user review.
- **PR-imported:** none (no reporter; per [Reporter credit
policy](https://github.com/<tracker>/blob/<tracker-default-branch>/.claude/skills/security-issue-import-from-pr/SKILL.md#reporter-credit-policy-for-public-pr-imports)).
- **Indeterminate import path:** none (flag from Step 2 surfaced; user
explicitly chose silent close).
+**The Reporter-notification line is required on every invalidate
+rollup entry.** Exactly one of the cases above must apply. If
+none does (the channel is genuinely ambiguous), surface as a
+blocker to the user before closing — do NOT post the rollup
+entry without the line.
+
**Project board:** archived (item `<item-id>`).
**Next:** none — terminal disposition.