Table of Contents generated with DocToc
Forwarder-routing policy
When a security tracker has no direct way to reach the original
reporter — there is no individual reporter email, GitHub Private
Reporting access is read-only, or the report arrived through a
forwarding service — the skills route reporter-facing communication
through whoever delivered the report to us instead (the forwarder
— typically the Apache Security team relaying via
security@apache.org, or an internal security-team member who
opened the tracker on someone else’s behalf).
In that “via-forwarder” mode, only important milestones are relayed. Regular workflow chatter and credit-confirmation questions are not sent to the forwarder — they would burn the forwarder’s goodwill with low-signal updates the forwarder has no useful reply to.
This file is the single source of truth for when the via-forwarder mode applies and what gets relayed.
When does via-forwarder mode apply?
The mode applies to a tracker when any of the following is true:
-
ASF-security relay. The inbound report came from
security@apache.orgwith the ASF forwarding preamble; the original reporter is not addressable directly on the relayed thread. The personal@apache.orgaddress of the forwarding security-team member is the forwarder contact. (Seetools/gmail/asf-relay.mdfor the detection mechanics.) -
GitHub Private Reporting we cannot reply on. A GHSA-style private report we have read access to but can’t post comments on as a security team. Whoever made us aware of the GHSA (typically the same Apache Security team member, or an internal escalation thread) is the forwarder.
-
security-issue-import-from-md-imported tracker. The tracker came from a markdown file (AI scan / third-party scan output) with no inbound reporter at all. There is no reporter to relay to; treat the security-team member who ran the import as the forwarder for any “additional information” questions. -
Explicit no-direct-contact marker. A security-team member sets the marker comment
<!-- apache-steward: routing-mode via-forwarder -->on the tracker (one line in the body, or as the first line of a pinned comment) and names the forwarder contact in the comment body. This is the fall-through escape hatch for cases the automatic detection above misses — an internal escalation, a chat-only report, a printed letter, anything else where the normal reporter address simply does not exist.
The trackers opened by
security-issue-import-from-pr
are a separate case with its own no outreach to the PR
author rule (see that skill’s Reporter credit policy for public-PR imports section). The forwarder-routing policy does
not apply there — the PR author is not someone we are
deliberately relaying through, just someone whose public PR we
imported. No reporter-facing drafts of any kind are proposed.
Milestones — DO relay
Only these events warrant a draft to the forwarder. They map 1:1 to the lifecycle decisions a reporter (or the team that relayed on their behalf) would actually want to hear about:
| Milestone | Where it fires | Draft body summary |
|---|---|---|
| Report accepted as valid | After Step 5 lands a valid consensus + scope label applied | ”We received the report you forwarded; the team has confirmed it as valid. A CVE will be allocated next; we will write again when the advisory is sent. If you can pass this update back to the original reporter, please do; if you can also ask them to reply with their preferred credit form, that would help — otherwise we’ll proceed with the credit line in the original report.” |
| Report assessed as invalid | security-issue-invalidate — closing reply | ”The team has assessed the report you forwarded and concluded it is not a security vulnerability. Reasoning: <one-paragraph summary>. If you (or the original reporter) want to challenge the assessment, please reply with the additional context; otherwise this is our final disposition.” |
| Advisory sent | security-issue-sync Step 14 close-out — after the advisory archive URL is captured | ”The advisory for CVE-YYYY-NNNNN has been sent and is archived publicly at <URL>. This completes the lifecycle for the report you forwarded; thank you for the relay.” |
| Additional information requested | Any skill that needs a specific clarification from the reporter (re-reproduction steps, attack-vector clarification, affected-version range) | “We need additional information to assess the report you forwarded: <specific question(s)>. If you can relay this to the original reporter and pass back a reply, that would help us land a decision.” |
The drafts go to the forwarder contact, not to the relay list
address — same rule as the existing ASF-relay flow in
tools/gmail/asf-relay.md. The
body is short, references the external identifier (GHSA ID,
HackerOne URL, internal ticket number) when one exists, and never
re-states the technical detail of the report.
Events handled outside this policy
Some lifecycle events generate reporter-facing notifications outside this policy’s milestone / negative-space rules. They fire the same way in both direct-reporter and via-forwarder modes — no recipient swap, no body-shape swap, no suppression.
- CVE allocated
(
security-cve-allocateStep 4 #5). Vulnogram typically emits its own allocation notification when the CVE record is created, and even when it doesn’t, the team owes the reporter (or their forwarder) a single short notification at this point regardless of routing mode. The notification lands on whatever thread the tracker’s Security mailing list thread field resolves to; in via-forwarder mode that is the relay thread, so the same draft reaches the forwarder without any policy-specific re-routing. The credit-preference question is still suppressed in via-forwarder mode (per the Negative space section below) but the rest of the CVE-allocated notification still fires.
Future events that follow the same shape (independent of routing mode, not subject to milestone-only suppression) belong here. Add a bullet and a one-paragraph explanation; do not hide the event by silently omitting it from the milestone list.
Negative space — DO NOT relay
These events would generate a draft in direct-reporter mode but are suppressed in via-forwarder mode:
-
Regular workflow status —
pr created/pr merged/fix releasedlabel transitions. The forwarder has no actionable reason to learn about these intermediate states; the next forwarder-bound message is at advisory-sent (the Advisory sent milestone above). -
Credit-acceptance confirmations — i.e. messages asking the reporter to confirm receipt and acceptance of the credit line the team plans to use. The standalone bot/AI credit-clarification draft belongs to this class (it asks “is this AI/bot handle the intended credit, or should we credit someone else?” — a confirmation prompt on a proposed credit). So do the follow-up chase-ups “please confirm we will credit you as X” that direct-reporter sync passes would otherwise generate when the reporter has gone silent. The forwarder cannot meaningfully accept a credit on behalf of the original reporter, so the prompt bounces back and burns goodwill.
The credit question itself is not suppressed. Folding a single short “if the reporter has a preferred credit form, please pass it back” line into a milestone draft (the Step 7 receipt-of-confirmation, the Report accepted as valid milestone, or the CVE allocated notification per the Events handled outside this policy section) is fine — the forwarder might know, or might be able to relay the question through the original channel. The distinction is:
- Question (allowed): a one-line ask included in a milestone message the team is already sending. Cheap; the forwarder either knows or can relay or drops it.
- Confirmation (suppressed): a message whose entire purpose is to get the reporter to accept a credit line the team has chosen. Demands a reply the forwarder can’t supply, so it becomes a chase-up loop.
The bot-credit detection still runs in via-forwarder mode and still filters the auto-extracted credit before it lands in the body field; it just does not generate its own confirmation message.
-
Reviewer-comment relays. CVE reviewer feedback that lands on
<security-list>is handled by the security team internally; the forwarder is not on that loop and does not need to be. -
Sync-rollup notifications. The internal rollup comments
security-issue-syncposts on the tracker stay on the tracker — they are for the security team, not for the forwarder.
Implementation in the skills
Each skill that composes a reporter-facing draft checks the tracker’s routing mode (using the detection rules in this doc) and applies one of three behaviours:
- Direct-reporter mode (the common case) — proceed exactly as the skill’s existing draft logic prescribes.
- Via-forwarder mode + the event is on the milestone list — compose the draft to the forwarder contact instead of the reporter, using the short milestone-body shape above. Reference the external identifier rather than the technical detail.
- Via-forwarder mode + the event is NOT on the milestone list
— suppress the draft entirely. Record in the proposal recap
“skipped draft:
<event>not on the via-forwarder milestone list” so the user can see why no message was proposed.
The detection runs once per skill invocation; subsequent dispatch through the skill is consistent for that run.
Worked examples
ASF-relayed GHSA report, advisory sent. A report arrives via
security@apache.org carrying a GHSA reference; the import skill
classifies it as ASF-security relay, drafts the Step 7 receipt to
the forwarder (Arnout / the Apache Security team member who
relayed it). Weeks later the fix ships and the advisory is
archived on the users-list; security-issue-sync Step 14
captures the URL and proposes an Advisory sent milestone draft
to the same forwarder contact: “The advisory for
CVE-2026-12345 has been sent and is archived publicly at
<URL>. This completes the lifecycle for the report you
forwarded; thank you for the relay.” No technical detail is
restated. (The intermediate CVE allocated notification landed
on the same thread per the
Events handled outside this policy
rule, so the forwarder already saw it.)
Bot-credit candidate in via-forwarder mode. The relayed report
names the discoverer as Automated Scanner v3. The bot-credit
policy detects the match and would normally propose a
clarification draft to the reporter. In via-forwarder mode the
clarification draft is suppressed; the credit field stays at
_No response_ until the next milestone draft, where a single
line “if the original reporter has a preferred credit form,
please pass it back” is folded in.
Internal-escalation tracker. An ASF PMC member forwards a
private internal report to the security team verbally; the
security team opens the tracker by hand and writes the
<!-- apache-steward: routing-mode via-forwarder --> marker
comment naming the PMC member as the forwarder contact. From that
point on, every sync skill that would draft to a reporter routes
to the named PMC member instead, and milestone-only suppression
applies as if the tracker had come in via ASF-relay.