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 fdcc68a feat(security-issue-sync): conservative affected-versions
range when uncertain (#401)
fdcc68a is described below
commit fdcc68a1b180fa6aaee9cab2102a727c80d796e8
Author: Jarek Potiuk <[email protected]>
AuthorDate: Sat May 30 21:52:28 2026 +0200
feat(security-issue-sync): conservative affected-versions range when
uncertain (#401)
Per Arnout Engelen's 2026-05-29 review on CVE-2026-33264 — "If you
haven't checked if versions before 2.10.5 are affected, the
conservative choice is to mark them affected. That's what you should
do unless that version line is EOL."
Adds the rule in two places:
1. New Step 1d signal row that fires when the Affected versions field
carries a lower-bounded range (`>= X.Y.Z, < A.B.C`) AND the
rollup / body / linked PR text does not contain explicit evidence
that earlier versions were verified non-vulnerable (an
"introduced in <version>" marker, a "regression from <version>"
note, or a "<X-line> is EOL" tag per release-trains.md). Proposes
widening the range by dropping the lower bound: `< A.B.C`. The
proposal surfaces both current and widened shape so the operator
can override by replying with introducing-version evidence
(next sync pass picks it up from the rollup) instead of just
accepting the widening.
2. New seventh pre-push hygiene gate in Step 5b 1b that refuses any
push whose JSON carries a lower-bounded affected[].versions[]
entry without that evidence. Catches the case where the body
update was missed at proposal time and the JSON would otherwise
ship with the narrow range.
The "introduced in <version>" / "EOL" markers are the load-bearing
signals: when they are present, the narrow range is intentional and
the gate passes. When they are absent, the default-narrow shape is
the failure mode the gate is here to catch.
Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
---
.claude/skills/security-issue-sync/SKILL.md | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/.claude/skills/security-issue-sync/SKILL.md
b/.claude/skills/security-issue-sync/SKILL.md
index 9ae896b..5fba16e 100644
--- a/.claude/skills/security-issue-sync/SKILL.md
+++ b/.claude/skills/security-issue-sync/SKILL.md
@@ -843,6 +843,7 @@ update, label change, or next-step recommendation in Step 2:
| The *"Affected versions"* body field is missing, holds a pre-convention
shape, or carries the project's pre-release sentinel, and the tracker is
**not** at `fix released` yet | Propose populating / refining *"Affected
versions"* per the project's convention. The per-scope shape, the pre-release
sentinel (if any), and the lifecycle live in
[`<project-config>/scope-labels.md` — *Affected versions convention by
scope*](../../../<project-config>/scope-labels.md#affected-versions-convention
[...]
| The *"Affected versions"* body field has a value but it is **not
backtick-wrapped** (the raw value, as returned by `gh issue view --json body`,
starts with a `>` character or contains a bare `>=` / `<=` / `<` / `>` token
outside a `` ` `` … `` ` `` span) | Propose wrapping the value in backticks
(e.g. `` `>= 3.0.0, < 3.2.2` ``, `` `< 3.2.2` ``, `` `<= 3.2.1` ``). **Why:**
the leading `>` is the markdown blockquote marker — without backticks, GitHub
renders the rendered field as a quote [...]
| A tracker is transitioning to `fix released` (per the row below) and
*"Affected versions"* still carries the project's pre-release sentinel |
Propose replacing the sentinel with the concrete released version per the
project's convention; see [`<project-config>/scope-labels.md` — *Affected
versions convention by
scope*](../../../<project-config>/scope-labels.md#affected-versions-convention-by-scope)
for the recipe. After the body update, regenerate the CVE JSON attachment so
`versions[] [...]
+| The *"Affected versions"* body field carries a **lower-bounded range** (e.g.
`` `>= X.Y.Z, < A.B.C` ``) **and** the rollup / body / commits do not show
explicit evidence that the operator verified earlier versions are NOT affected
(e.g. *"vulnerability introduced in X.Y.Z by PR/commit ABCDEF"*, or *"versions
< X.Y.Z are EOL per release-trains.md"*). Detector heuristic: the field matches
`^\s*\`?\s*>=?\s*\d+\.\d+(\.\d+)?\s*,\s*<\s*\d+\.\d+(\.\d+)?\s*\`?\s*$` AND the
rollup / body / link [...]
| The *"Short public summary for publish"* body field is populated but does
**not** name a concrete upgrade-target version — the rendered text mentions
*"upgrade"* / *"upgrading"* but no `<package> <X.Y.Z>` pattern, or ends with a
generic phrase like *"the version that contains the fix"* / *"a later version"*
/ *"the next release"* | Propose tightening the summary to name the
upgrade-target version verbatim. Resolve the version from the fix PR's
milestone (the canonical signal — set at m [...]
| The *"Short public summary for publish"* body field is populated but does
**not** state the triggering conditions — the rendered text describes the bug
mechanism without identifying (a) the attacker role / capability, (b) the
deployment configuration that has to be active, OR (c) the action the attacker
takes against which surface. Detector heuristic: scan the summary for any of
these phrases — *"an authenticated [\\w ]+ user"*, *"a Dag author"*, *"an
attacker with"*, *"a user able to" [...]
| The tracker is an **incomplete-fix follow-up to another CVE** — detected by
any of: the rollup or body mentions *"incomplete fix for `CVE-YYYY-NNNNN`"* /
*"follow-up to `CVE-YYYY-NNNNN`"* / *"sibling tracker"*; the title contains a
*"(incomplete fix for `CVE-YYYY-NNNNN`)"* parenthetical; the `affected[]` array
names a different `packageName` than the referenced prior CVE; OR the tracker
was opened as a split from a closed-`announced` tracker whose CVE is already
PUBLISHED — **AND** the [...]
@@ -2993,7 +2994,7 @@ Step 6 below describes how to verify the state advance
landed
CVE worthy). There is no record to push to.
1b. **Pre-push hygiene-gate scan.** Before any push call, re-scan
- the JSON about to be pushed for the six pre-push gates that
+ the JSON about to be pushed for the seven pre-push gates that
make the published CVE record user-facing:
- **Title strip cascade** — `containers.cna.title` must have
@@ -3050,6 +3051,22 @@ Step 6 below describes how to verify the state advance
landed
on `security@` with their real name). Rationale, examples,
and the full opt-in / opt-out matrix live in
[`<project-config>/scanner-products.md`](../../../<project-config>/scanner-products.md).
+ - **Conservative affected-versions range** — when the
+ JSON's `affected[].versions[]` array describes a
+ lower-bounded range (typically emitted from the body's
+ `>= X.Y.Z, < A.B.C` shape: `version: "X.Y.Z"`,
+ `versionType: "semver"`, `lessThan: "A.B.C"`), the body
+ field must show explicit evidence that the operator
+ verified earlier versions are NOT affected — an
+ "introduced in `<version>`", "regression from `<version>`",
+ or "`<X-line>` is EOL" marker for the lower-bound version
+ in the rollup, body, or linked PR text. Without that
+ evidence the gate refuses the push and surfaces the
+ widened-range proposal (`version: "0"` lower bound)
+ described in the matching Step 1d row. Per ASF Security
+ policy (Arnout Engelen's 2026-05-29 review on
+ CVE-2026-33264), the default is all-versions-affected
+ unless we have positive evidence to the contrary.
When any gate fails the JSON the regen just produced, the
right recovery is **not** to push — fix the underlying body