@blamejs/blamejs-shop 0.2.12 → 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/lib/asset-manifest.json +3 -3
- package/lib/storefront.js +1 -1
- package/lib/vendor/MANIFEST.json +2 -2
- package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +71 -23
- package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +2 -0
- package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +2 -0
- package/lib/vendor/blamejs/.github/workflows/ci.yml +17 -0
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +18 -10
- package/lib/vendor/blamejs/.github/workflows/release-container.yml +29 -16
- package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +22 -3
- package/lib/vendor/blamejs/.github/zizmor.yml +29 -0
- package/lib/vendor/blamejs/.pinact.yaml +24 -8
- package/lib/vendor/blamejs/CHANGELOG.md +4 -0
- package/lib/vendor/blamejs/api-snapshot.json +2 -2
- package/lib/vendor/blamejs/lib/archive-wrap.js +1 -1
- package/lib/vendor/blamejs/lib/auth/jwt.js +7 -4
- package/lib/vendor/blamejs/lib/auth/saml.js +2 -2
- package/lib/vendor/blamejs/lib/cose.js +1 -1
- package/lib/vendor/blamejs/lib/did.js +1 -1
- package/lib/vendor/blamejs/lib/guard-archive.js +2 -2
- package/lib/vendor/blamejs/lib/guard-auth.js +5 -5
- package/lib/vendor/blamejs/lib/guard-cidr.js +4 -4
- package/lib/vendor/blamejs/lib/guard-csv.js +6 -6
- package/lib/vendor/blamejs/lib/guard-domain.js +4 -4
- package/lib/vendor/blamejs/lib/guard-email.js +6 -5
- package/lib/vendor/blamejs/lib/guard-filename.js +4 -4
- package/lib/vendor/blamejs/lib/guard-graphql.js +5 -5
- package/lib/vendor/blamejs/lib/guard-html.js +2 -2
- package/lib/vendor/blamejs/lib/guard-image.js +1 -1
- package/lib/vendor/blamejs/lib/guard-json.js +5 -5
- package/lib/vendor/blamejs/lib/guard-jsonpath.js +4 -4
- package/lib/vendor/blamejs/lib/guard-jwt.js +5 -5
- package/lib/vendor/blamejs/lib/guard-markdown.js +6 -6
- package/lib/vendor/blamejs/lib/guard-mime.js +6 -6
- package/lib/vendor/blamejs/lib/guard-oauth.js +5 -5
- package/lib/vendor/blamejs/lib/guard-pdf.js +1 -1
- package/lib/vendor/blamejs/lib/guard-regex.js +4 -4
- package/lib/vendor/blamejs/lib/guard-shell.js +4 -4
- package/lib/vendor/blamejs/lib/guard-svg.js +5 -5
- package/lib/vendor/blamejs/lib/guard-template.js +4 -4
- package/lib/vendor/blamejs/lib/guard-time.js +6 -6
- package/lib/vendor/blamejs/lib/guard-uuid.js +6 -6
- package/lib/vendor/blamejs/lib/guard-xml.js +4 -4
- package/lib/vendor/blamejs/lib/guard-yaml.js +5 -5
- package/lib/vendor/blamejs/lib/link-header.js +3 -2
- package/lib/vendor/blamejs/lib/mail-agent.js +4 -2
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +2 -2
- package/lib/vendor/blamejs/lib/tsa.js +2 -1
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.13.23.json +42 -0
- package/lib/vendor/blamejs/release-notes/v0.13.24.json +26 -0
- package/lib/vendor/blamejs/test/smoke.js +25 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,8 @@ upgrading across more than a few patches at a time.
|
|
|
8
8
|
|
|
9
9
|
## v0.2.x
|
|
10
10
|
|
|
11
|
+
- v0.2.13 (2026-05-28) — **Product-grid and product-page visual polish.** Small visual refinements to the catalog grid and product page. Product tiles previously all carried the same fixed corner glow, so a grid of them read as one card stamped repeatedly; the glow position now rotates per tile so the grid looks like a designed set. The product page's buy box gets clearer elevation so it reads as a distinct purchase surface, and the fallback placeholder shown for a product with no image is now legible on the dark theme instead of a near-invisible mark. **Changed:** *Product tiles no longer share one identical glow* — Each product card's media glow now rotates through a set of positions per tile (matching the collection cards) instead of every tile glowing in the exact same corner, so a full grid reads as a designed set rather than a single card repeated. · *Clearer product-page buy box* — The product page's buy box gains a stronger border and a soft shadow so it stands out from the page as the purchase surface. · *Legible image-less placeholder* — The fallback artwork shown when a product has no image was nearly invisible on the dark canvas; its contrast is lifted (grid lines, shield detail, and caption) so it reads as an intentional placeholder. Applied identically on the edge and container render paths.
|
|
12
|
+
|
|
11
13
|
- v0.2.12 (2026-05-28) — **Truthful product availability and real SEO metadata — canonical URLs, structured data, and per-page descriptions.** Two related improvements to the storefront's honesty and discoverability. Product pages now report real availability from inventory (instead of a hardcoded 'In stock') and reflect it in their structured data, and the shipping line is suppressed for digital products. Separately, every page now emits a canonical URL and a populated Open Graph URL (previously empty — which broke social-share unfurls and let sort/currency query parameters fork into duplicate indexed pages), the home page emits the same Organization/Website structured data the edge already did, breadcrumb structured data uses absolute URLs, and the home, category, and search pages get their own meta descriptions instead of one shared default. The footer's account links are regrouped and a shipping-and-returns link was added. **Changed:** *Product availability is truthful* — The product page's stock badge and its `Product`/`AggregateOffer` structured-data `availability` are now driven by real per-SKU inventory (`InStock` / `OutOfStock`) rather than a hardcoded value, so a sold-out item reads as sold out everywhere and structured data no longer mismatches reality. The shipping-time line is suppressed for all-digital products (shown as delivered on purchase). Identical across the edge and container render paths. · *Footer account links regrouped* — The footer's operator-oriented column is now a customer 'Your account' grouping (Account / Orders / Contact), the public Admin link was removed, and a 'Shipping & returns' link was added to the policy area. · *Form fields are legible on the dark theme* — Text inputs, selects, and textareas (checkout, address book, search, sign-in) previously rendered with a 10%-opacity hairline that disappeared against the near-black canvas — fields read as empty voids. They now have a clearly-bounded outline and a lifted fill, stretch to fill their column, and the rule covers `tel`/`url`/`password` inputs it previously missed. **Fixed:** *Canonical + Open Graph URLs on every page* — Every page now includes `<link rel="canonical">` and a populated `og:url` (both were absent/empty before). This fixes social-share previews that unfurled with no link target and prevents tracking/sort/currency query-string variants from being indexed as duplicate pages. Emitted on both render paths, derived from the request's own origin. · *Consistent structured data + unique page descriptions* — The home page now emits the `Organization` and `WebSite` (search-action) structured data that previously only appeared on the edge render, breadcrumb structured-data item URLs are absolute (so the breadcrumb rich result is eligible), and the home, category, and search pages each carry their own meta/OG description instead of sharing one generic string.
|
|
12
14
|
|
|
13
15
|
- v0.2.11 (2026-05-27) — **A clearer checkout — itemised order summary, honest pricing, and recoverable errors.** Reworks the checkout and cart experience. Checkout now uses the same two-column layout as the cart, with a sticky order-summary rail that lists the actual items being bought (thumbnail, title, quantity, line total) rather than a bare number in a lonely column. The summary no longer shows a misleading 'Total' equal to the subtotal — it shows the subtotal plus an honest note that tax and shipping are calculated at the payment step, matching the cart. Adding an item now confirms it and offers to keep shopping, checkout and cart failures render as proper pages you can recover from instead of a blank error string, required fields announce themselves to screen readers, and the header 'Framework' link works from every page. **Changed:** *Checkout shows an itemised, sticky order summary* — The checkout page adopts the cart's two-column layout: the shipping form on the left and a sticky order summary on the right that lists each item (thumbnail, title, quantity, line total) with an 'Edit cart' link back to the cart. Previously the form was a narrow column with a bare subtotal box and no way back. · *Honest checkout pricing* — The order summary no longer renders a 'Total (plus tax + shipping)' line bound to the subtotal value (which read as the final price but wasn't). It now shows the subtotal and the same honest note the cart uses — tax and shipping are calculated at the payment step. · *Add-to-cart confirmation + continue shopping* — Adding an item lands on the cart with a dismissible 'Added to cart' confirmation, and the cart now has a 'Continue shopping' link so multi-item shoppers aren't dead-ended. **Fixed:** *Checkout and cart errors are recoverable, not blank pages* — A declined gift card, an invalid input, or a checkout failure previously dumped an unstyled plain-text error. These now render as styled pages with the reason and a way back — gift-card and loyalty errors re-display the checkout form with the message inline so the shopper can correct it without losing their place. · *Required fields announce to screen readers* — Required form fields kept only a red asterisk (color-only); they now include a visually-hidden '(required)' so assistive technology conveys it. · *Header 'Framework' link works on every page* — It pointed at an on-page anchor that only existed on the home page (a no-op elsewhere); it now resolves from any page.
|
package/lib/asset-manifest.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.2.
|
|
2
|
+
"version": "0.2.13",
|
|
3
3
|
"assets": {
|
|
4
4
|
"css/admin.css": {
|
|
5
5
|
"integrity": "sha384-FgqvXcZygYkJjjOtXAeu9xi6AtYqkchPnJKcS0OeHm8lynhd9r4RfdpoT7P7j7/l",
|
|
6
6
|
"fingerprinted": "css/admin.afd7b964c1f6fe1b.css"
|
|
7
7
|
},
|
|
8
8
|
"css/main.css": {
|
|
9
|
-
"integrity": "sha384-
|
|
10
|
-
"fingerprinted": "css/main.
|
|
9
|
+
"integrity": "sha384-E56XcvNC5nbTWyHJJcepF6sVA1KjRNo/MWFL5F5w2PDN10JNaHdzIAP9a46m2Md8",
|
|
10
|
+
"fingerprinted": "css/main.a76d36ac566703d6.css"
|
|
11
11
|
},
|
|
12
12
|
"js/announcement.js": {
|
|
13
13
|
"integrity": "sha384-z4zcEMn+tScoVnYRE4nEf8N/oyvpxdpaxTNrT4QO/jURChid4+qjAvWkzatCaAPq",
|
package/lib/storefront.js
CHANGED
|
@@ -696,7 +696,7 @@ var PRODUCT_CARD_IMAGE =
|
|
|
696
696
|
var PRODUCT_CARD =
|
|
697
697
|
"<a class=\"product-card\" href=\"/products/{{slug}}\">\n" +
|
|
698
698
|
" <figure class=\"product-card__media product-card__media--placeholder\">\n" +
|
|
699
|
-
" <svg class=\"media-ph__svg\" viewBox=\"0 0 160 120\" aria-hidden=\"true\"><rect width=\"160\" height=\"120\" fill=\"none\"/><g stroke=\"currentColor\" stroke-opacity=\"0.
|
|
699
|
+
" <svg class=\"media-ph__svg\" viewBox=\"0 0 160 120\" aria-hidden=\"true\"><rect width=\"160\" height=\"120\" fill=\"none\"/><g stroke=\"currentColor\" stroke-opacity=\"0.18\" stroke-width=\"1\"><path d=\"M0 30 H160 M0 60 H160 M0 90 H160 M40 0 V120 M80 0 V120 M120 0 V120\"/></g><g fill=\"none\" stroke=\"#AD38DB\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M80 38 L104 50 L104 76 L80 88 L56 76 L56 50 Z\"/><path d=\"M56 50 L80 62 L104 50 M80 62 V88\" stroke=\"#C75BE8\"/><path d=\"M70 47 L74 50 L70 53\" stroke=\"currentColor\" stroke-width=\"2\"/><path d=\"M77 54 H86\" stroke=\"currentColor\" stroke-width=\"2\"/></g><text x=\"80\" y=\"106\" text-anchor=\"middle\" font-family=\"ui-monospace,Menlo,Consolas,monospace\" font-size=\"9\" letter-spacing=\"1.5\" fill=\"#9b9ba7\">no image yet</text></svg>\n" +
|
|
700
700
|
" </figure>\n" +
|
|
701
701
|
" <div class=\"product-card__meta\">\n" +
|
|
702
702
|
" <h3 class=\"product-card__title\">{{title}}</h3>\n" +
|
package/lib/vendor/MANIFEST.json
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"_about": "blamejs.shop vendors a single framework — blamejs — which itself bundles every server-side crypto/identity dependency. The transitive packages blamejs ships are surfaced in its own MANIFEST.json at lib/vendor/blamejs/lib/vendor/MANIFEST.json — Trivy / Grype rely on that nested data for CVE attribution.",
|
|
4
4
|
"packages": {
|
|
5
5
|
"blamejs": {
|
|
6
|
-
"version": "0.13.
|
|
7
|
-
"tag": "v0.13.
|
|
6
|
+
"version": "0.13.24",
|
|
7
|
+
"tag": "v0.13.24",
|
|
8
8
|
"license": "Apache-2.0",
|
|
9
9
|
"author": "blamejs contributors",
|
|
10
10
|
"source": "https://github.com/blamejs/blamejs",
|
|
@@ -50,6 +50,8 @@ jobs:
|
|
|
50
50
|
steps:
|
|
51
51
|
- name: Checkout
|
|
52
52
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
53
|
+
with:
|
|
54
|
+
persist-credentials: false
|
|
53
55
|
|
|
54
56
|
- name: Install pinact (release binary + sha256 verify)
|
|
55
57
|
# Install pinact directly from the upstream release binary
|
|
@@ -106,32 +108,43 @@ jobs:
|
|
|
106
108
|
name: zizmor — workflow security audit
|
|
107
109
|
runs-on: ubuntu-latest
|
|
108
110
|
timeout-minutes: 5
|
|
109
|
-
permissions:
|
|
110
|
-
contents: read
|
|
111
|
-
security-events: write # required for SARIF upload to Code Scanning
|
|
112
111
|
steps:
|
|
113
112
|
- name: Checkout
|
|
114
113
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
114
|
+
with:
|
|
115
|
+
persist-credentials: false
|
|
115
116
|
|
|
116
|
-
- name: Install
|
|
117
|
-
|
|
117
|
+
- name: Install zizmor (release binary + sha256 verify)
|
|
118
|
+
# Direct release-binary install instead of astral-sh/setup-uv + uvx.
|
|
119
|
+
# setup-uv (a third-party action) startup_failures the whole
|
|
120
|
+
# workflow on the current runner — the same class of failure as the
|
|
121
|
+
# raven-actions/actionlint composite that took down the actionlint
|
|
122
|
+
# job (no jobs, no logs). A run: step cannot startup_failure.
|
|
123
|
+
# zizmor publishes no checksums file, so the expected sha256 is
|
|
124
|
+
# pinned inline; a mismatch fails closed.
|
|
125
|
+
env:
|
|
126
|
+
ZIZMOR_VERSION: v1.18.0
|
|
127
|
+
ZIZMOR_SHA256: 8e7901319ab7b71c38d6d388a48e02ff65791e5971b2ee6577c9b5c3ab44c65f
|
|
128
|
+
run: |
|
|
129
|
+
set -euo pipefail
|
|
130
|
+
curl -fsSLo /tmp/zizmor.tar.gz "https://github.com/zizmorcore/zizmor/releases/download/${ZIZMOR_VERSION}/zizmor-x86_64-unknown-linux-gnu.tar.gz"
|
|
131
|
+
ACTUAL=$(sha256sum /tmp/zizmor.tar.gz | awk '{print $1}')
|
|
132
|
+
if [ "$ACTUAL" != "$ZIZMOR_SHA256" ]; then
|
|
133
|
+
echo "::error::zizmor tarball sha256 ${ACTUAL} does not match pinned ${ZIZMOR_SHA256}"
|
|
134
|
+
exit 1
|
|
135
|
+
fi
|
|
136
|
+
mkdir -p /tmp/zizmor-bin
|
|
137
|
+
tar -xzf /tmp/zizmor.tar.gz -C /tmp/zizmor-bin ./zizmor
|
|
138
|
+
sudo install -m 0755 /tmp/zizmor-bin/zizmor /usr/local/bin/zizmor
|
|
139
|
+
zizmor --version
|
|
118
140
|
|
|
119
141
|
- name: Run zizmor (fail on level=low across every rule class)
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
#
|
|
142
|
+
# Pure run-gate: zizmor exits non-zero on any finding, failing the
|
|
143
|
+
# job. Inline `# zizmor: ignore[<rule>] — <reason>` is the
|
|
144
|
+
# suppression mechanism for reviewed exceptions.
|
|
123
145
|
run: |
|
|
124
146
|
set -euo pipefail
|
|
125
|
-
|
|
126
|
-
uvx zizmor@1.18.0 --min-severity low . || true # human-readable output for the step log
|
|
127
|
-
if [ "${EXIT:-0}" != "0" ]; then exit "$EXIT"; fi
|
|
128
|
-
|
|
129
|
-
- name: Upload SARIF to Code Scanning
|
|
130
|
-
if: always()
|
|
131
|
-
uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
|
|
132
|
-
with:
|
|
133
|
-
sarif_file: zizmor.sarif
|
|
134
|
-
category: zizmor
|
|
147
|
+
zizmor --min-severity low --no-progress .github/workflows/
|
|
135
148
|
|
|
136
149
|
actionlint:
|
|
137
150
|
name: actionlint — YAML + expression + shellcheck on `run:` blocks
|
|
@@ -140,9 +153,44 @@ jobs:
|
|
|
140
153
|
steps:
|
|
141
154
|
- name: Checkout
|
|
142
155
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
143
|
-
|
|
144
|
-
- name: Run actionlint
|
|
145
|
-
uses: raven-actions/actionlint@205b530c5d9fa8f44ae9ed59f341a0db994aa6f8 # v2.1.2
|
|
146
156
|
with:
|
|
147
|
-
|
|
148
|
-
|
|
157
|
+
persist-credentials: false
|
|
158
|
+
|
|
159
|
+
- name: Install actionlint (release binary + sha256 verify)
|
|
160
|
+
# Direct release-binary install instead of the
|
|
161
|
+
# raven-actions/actionlint composite action. That composite (v2.1.2,
|
|
162
|
+
# the latest release) startup_failures on the current runner, taking
|
|
163
|
+
# the whole workflow down before any job runs — which is why this
|
|
164
|
+
# gate never ran from v0.11.21 onward. The binary path also drops the
|
|
165
|
+
# composite's transitive github-script / cache action surface, which
|
|
166
|
+
# fits the gate whose entire purpose is pinning discipline. Mirrors
|
|
167
|
+
# the pinact install step above.
|
|
168
|
+
env:
|
|
169
|
+
ACTIONLINT_VERSION: v1.7.12
|
|
170
|
+
run: |
|
|
171
|
+
set -euo pipefail
|
|
172
|
+
V="${ACTIONLINT_VERSION#v}"
|
|
173
|
+
curl -fsSLo /tmp/actionlint.tar.gz "https://github.com/rhysd/actionlint/releases/download/${ACTIONLINT_VERSION}/actionlint_${V}_linux_amd64.tar.gz"
|
|
174
|
+
curl -fsSLo /tmp/actionlint-checksums.txt "https://github.com/rhysd/actionlint/releases/download/${ACTIONLINT_VERSION}/actionlint_${V}_checksums.txt"
|
|
175
|
+
ACTUAL=$(sha256sum /tmp/actionlint.tar.gz | awk '{print $1}')
|
|
176
|
+
EXPECTED=$(grep "actionlint_${V}_linux_amd64.tar.gz\$" /tmp/actionlint-checksums.txt | awk '{print $1}')
|
|
177
|
+
if [ -z "$EXPECTED" ]; then
|
|
178
|
+
echo "::error::could not find actionlint_${V}_linux_amd64.tar.gz line in upstream checksums"
|
|
179
|
+
exit 1
|
|
180
|
+
fi
|
|
181
|
+
if [ "$ACTUAL" != "$EXPECTED" ]; then
|
|
182
|
+
echo "::error::actionlint tarball sha256 ${ACTUAL} does not match upstream-published ${EXPECTED}"
|
|
183
|
+
exit 1
|
|
184
|
+
fi
|
|
185
|
+
mkdir -p /tmp/actionlint-bin
|
|
186
|
+
tar -xzf /tmp/actionlint.tar.gz -C /tmp/actionlint-bin actionlint
|
|
187
|
+
sudo install -m 0755 /tmp/actionlint-bin/actionlint /usr/local/bin/actionlint
|
|
188
|
+
actionlint --version
|
|
189
|
+
|
|
190
|
+
- name: Run actionlint (+ shellcheck on every run block)
|
|
191
|
+
# shellcheck ships preinstalled on ubuntu-latest; actionlint invokes
|
|
192
|
+
# it automatically on each `run:` block. Non-zero exit on any finding
|
|
193
|
+
# keeps this a hard gate (the raven composite's fail_on_error: true).
|
|
194
|
+
run: |
|
|
195
|
+
set -euo pipefail
|
|
196
|
+
actionlint -color
|
|
@@ -52,6 +52,8 @@ jobs:
|
|
|
52
52
|
steps:
|
|
53
53
|
- name: Checkout
|
|
54
54
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
55
|
+
with:
|
|
56
|
+
persist-credentials: false
|
|
55
57
|
|
|
56
58
|
- name: Set up Node 24.14.1 LTS
|
|
57
59
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
@@ -106,6 +108,8 @@ jobs:
|
|
|
106
108
|
steps:
|
|
107
109
|
- name: Checkout
|
|
108
110
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
111
|
+
with:
|
|
112
|
+
persist-credentials: false
|
|
109
113
|
|
|
110
114
|
- name: Set up Node 24.14.1 LTS
|
|
111
115
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
@@ -126,6 +130,8 @@ jobs:
|
|
|
126
130
|
steps:
|
|
127
131
|
- name: Checkout
|
|
128
132
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
133
|
+
with:
|
|
134
|
+
persist-credentials: false
|
|
129
135
|
|
|
130
136
|
- name: Set up Node 24.14.1 LTS
|
|
131
137
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
@@ -149,6 +155,8 @@ jobs:
|
|
|
149
155
|
steps:
|
|
150
156
|
- name: Checkout
|
|
151
157
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
158
|
+
with:
|
|
159
|
+
persist-credentials: false
|
|
152
160
|
- name: Set up Node
|
|
153
161
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
154
162
|
with:
|
|
@@ -168,6 +176,7 @@ jobs:
|
|
|
168
176
|
- name: Checkout
|
|
169
177
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
170
178
|
with:
|
|
179
|
+
persist-credentials: false
|
|
171
180
|
# gitleaks scans full history on a non-shallow checkout, so an
|
|
172
181
|
# accidentally-committed secret in any prior commit on the
|
|
173
182
|
# branch is caught even if a later commit reverts it. The
|
|
@@ -225,6 +234,8 @@ jobs:
|
|
|
225
234
|
steps:
|
|
226
235
|
- name: Checkout
|
|
227
236
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
237
|
+
with:
|
|
238
|
+
persist-credentials: false
|
|
228
239
|
|
|
229
240
|
- name: Set up Node 24.14.1 LTS
|
|
230
241
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
@@ -254,6 +265,8 @@ jobs:
|
|
|
254
265
|
steps:
|
|
255
266
|
- name: Checkout
|
|
256
267
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
268
|
+
with:
|
|
269
|
+
persist-credentials: false
|
|
257
270
|
|
|
258
271
|
- name: Set up Node 24.14.1 LTS
|
|
259
272
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
@@ -294,6 +307,8 @@ jobs:
|
|
|
294
307
|
steps:
|
|
295
308
|
- name: Checkout
|
|
296
309
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
310
|
+
with:
|
|
311
|
+
persist-credentials: false
|
|
297
312
|
|
|
298
313
|
- name: Run Hadolint (strict, all severities)
|
|
299
314
|
# `--no-fail` is OFF; any error or warning fails the job.
|
|
@@ -336,6 +351,8 @@ jobs:
|
|
|
336
351
|
steps:
|
|
337
352
|
- name: Checkout
|
|
338
353
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
354
|
+
with:
|
|
355
|
+
persist-credentials: false
|
|
339
356
|
|
|
340
357
|
- name: Detect shell scripts
|
|
341
358
|
id: sh
|
|
@@ -94,6 +94,8 @@ jobs:
|
|
|
94
94
|
steps:
|
|
95
95
|
- name: Checkout
|
|
96
96
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
97
|
+
with:
|
|
98
|
+
persist-credentials: false
|
|
97
99
|
|
|
98
100
|
- name: Set up Node 24.14.1 LTS
|
|
99
101
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
@@ -102,11 +104,14 @@ jobs:
|
|
|
102
104
|
|
|
103
105
|
- name: Compute version + is_tag flag
|
|
104
106
|
id: version
|
|
107
|
+
env:
|
|
108
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
109
|
+
REF: ${{ github.ref }}
|
|
105
110
|
run: |
|
|
106
111
|
set -euo pipefail
|
|
107
112
|
PKG_VERSION=$(node -e "console.log(require('./package.json').version)")
|
|
108
113
|
echo "version=$PKG_VERSION" >> "$GITHUB_OUTPUT"
|
|
109
|
-
if [ "$
|
|
114
|
+
if [ "$EVENT_NAME" = "push" ] && [[ "$REF" == refs/tags/v* ]]; then
|
|
110
115
|
TAG_VERSION="${GITHUB_REF#refs/tags/v}"
|
|
111
116
|
echo "is_tag=true" >> "$GITHUB_OUTPUT"
|
|
112
117
|
if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
|
|
@@ -132,7 +137,7 @@ jobs:
|
|
|
132
137
|
|
|
133
138
|
- name: ShellCheck
|
|
134
139
|
if: steps.shells.outputs.found == 'true'
|
|
135
|
-
uses: ludeeus/action-shellcheck@
|
|
140
|
+
uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0
|
|
136
141
|
with:
|
|
137
142
|
severity: error
|
|
138
143
|
|
|
@@ -229,7 +234,7 @@ jobs:
|
|
|
229
234
|
id: subjects
|
|
230
235
|
run: |
|
|
231
236
|
set -euo pipefail
|
|
232
|
-
TARBALL=$(basename "$(
|
|
237
|
+
TARBALL=$(basename "$(find dist -maxdepth 1 -name '*.tgz' | head -1)")
|
|
233
238
|
HASHES=$(
|
|
234
239
|
(cd dist && sha256sum "$TARBALL") && \
|
|
235
240
|
sha256sum sbom.cdx.json sbom.vendored.cdx.json
|
|
@@ -292,7 +297,9 @@ jobs:
|
|
|
292
297
|
# repo specifically so the SLSA tag-pin call is permitted. The
|
|
293
298
|
# `slsa-action-not-pinned` codebase-patterns detector allowlists
|
|
294
299
|
# this specific callsite (see test/layer-0-primitives/codebase-patterns.test.js).
|
|
295
|
-
|
|
300
|
+
# SLSA's reusable builder workflow refuses non-tag refs (cannot be
|
|
301
|
+
# SHA-pinned); upstream tag-protection + immutable releases mitigate.
|
|
302
|
+
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 # zizmor: ignore[unpinned-uses] allow:slsa-framework-action-not-sha-pinned — SLSA's internal builder-fetch refuses non-tag refs; mitigated by slsa-framework's upstream tag-protection + immutable-release rules
|
|
296
303
|
with:
|
|
297
304
|
base64-subjects: "${{ needs.validate.outputs.hashes }}"
|
|
298
305
|
upload-assets: false
|
|
@@ -410,6 +417,7 @@ jobs:
|
|
|
410
417
|
# and failed immediately on the first PQC release run.
|
|
411
418
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
412
419
|
with:
|
|
420
|
+
persist-credentials: false
|
|
413
421
|
path: src
|
|
414
422
|
|
|
415
423
|
- name: Release-digest sidecars (SHA-256 + SHA3-512)
|
|
@@ -424,7 +432,7 @@ jobs:
|
|
|
424
432
|
# Both written in `<sha> <filename>` sha-sum-compatible format.
|
|
425
433
|
run: |
|
|
426
434
|
set -euo pipefail
|
|
427
|
-
TARBALL=$(
|
|
435
|
+
TARBALL=$(find dist -maxdepth 1 -name '*.tgz' | head -1)
|
|
428
436
|
node src/scripts/sha3-digest.js "$TARBALL"
|
|
429
437
|
|
|
430
438
|
- name: PQC sidecar — ML-DSA-65 signature of the tarball
|
|
@@ -463,7 +471,7 @@ jobs:
|
|
|
463
471
|
echo "available=false" >> "$GITHUB_OUTPUT"
|
|
464
472
|
exit 0
|
|
465
473
|
fi
|
|
466
|
-
TARBALL=$(
|
|
474
|
+
TARBALL=$(find dist -maxdepth 1 -name '*.tgz' | head -1)
|
|
467
475
|
# The signer expects keys/release-pqc-pub.json at the
|
|
468
476
|
# framework root for the self-verify cross-check. Symlink
|
|
469
477
|
# the checked-out src/keys/ into the working directory so
|
|
@@ -514,11 +522,11 @@ jobs:
|
|
|
514
522
|
set -euo pipefail
|
|
515
523
|
if gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
|
|
516
524
|
echo "::error::Release $TAG already exists. The workflow is authoritative for release creation as of v0.11.7."
|
|
517
|
-
echo "::error::Manual
|
|
518
|
-
echo "::error::Either delete the existing release
|
|
525
|
+
echo "::error::Manual 'gh release create' was removed from the release workflow in v0.11.7."
|
|
526
|
+
echo "::error::Either delete the existing release with 'gh release delete $TAG' and re-run this workflow, OR push a new tag."
|
|
519
527
|
exit 1
|
|
520
528
|
fi
|
|
521
|
-
TARBALL=$(
|
|
529
|
+
TARBALL=$(find dist -maxdepth 1 -name '*.tgz' | head -1)
|
|
522
530
|
# Title comes from the structured release-notes JSON's
|
|
523
531
|
# `headline` field — single source of truth. Format:
|
|
524
532
|
# `vX.Y.Z — <headline>`.
|
|
@@ -594,7 +602,7 @@ jobs:
|
|
|
594
602
|
# mis-classifies a relative path containing `/` as a git
|
|
595
603
|
# spec.
|
|
596
604
|
run: |
|
|
597
|
-
TARBALL=$(
|
|
605
|
+
TARBALL=$(find dist -maxdepth 1 -name '*.tgz' | head -1)
|
|
598
606
|
echo "Publishing: $TARBALL"
|
|
599
607
|
npm publish "./${TARBALL}" --provenance --access public
|
|
600
608
|
env:
|
|
@@ -57,6 +57,8 @@ jobs:
|
|
|
57
57
|
steps:
|
|
58
58
|
- name: Checkout
|
|
59
59
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
60
|
+
with:
|
|
61
|
+
persist-credentials: false
|
|
60
62
|
- name: Set up Node 24.14.1 LTS
|
|
61
63
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
62
64
|
with:
|
|
@@ -73,6 +75,8 @@ jobs:
|
|
|
73
75
|
steps:
|
|
74
76
|
- name: Checkout
|
|
75
77
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
78
|
+
with:
|
|
79
|
+
persist-credentials: false
|
|
76
80
|
- name: Run Hadolint (strict, all severities)
|
|
77
81
|
uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0
|
|
78
82
|
with:
|
|
@@ -88,6 +92,8 @@ jobs:
|
|
|
88
92
|
steps:
|
|
89
93
|
- name: Checkout
|
|
90
94
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
95
|
+
with:
|
|
96
|
+
persist-credentials: false
|
|
91
97
|
- name: Detect shell scripts
|
|
92
98
|
id: sh
|
|
93
99
|
run: |
|
|
@@ -97,7 +103,7 @@ jobs:
|
|
|
97
103
|
echo "found=$count" >> "$GITHUB_OUTPUT"
|
|
98
104
|
- name: Run ShellCheck
|
|
99
105
|
if: steps.sh.outputs.found != '0'
|
|
100
|
-
uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 #
|
|
106
|
+
uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0
|
|
101
107
|
with:
|
|
102
108
|
severity: style
|
|
103
109
|
format: tty
|
|
@@ -118,16 +124,18 @@ jobs:
|
|
|
118
124
|
steps:
|
|
119
125
|
- name: Checkout
|
|
120
126
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
127
|
+
with:
|
|
128
|
+
persist-credentials: false
|
|
121
129
|
|
|
122
130
|
- name: Set up QEMU (for ARM64 cross-build)
|
|
123
|
-
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4
|
|
131
|
+
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
|
|
124
132
|
|
|
125
133
|
- name: Set up Docker Buildx
|
|
126
|
-
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
|
|
134
|
+
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
|
127
135
|
|
|
128
136
|
- name: Log in to GHCR
|
|
129
137
|
if: ${{ !inputs.dry_run }}
|
|
130
|
-
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
|
|
138
|
+
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
|
131
139
|
with:
|
|
132
140
|
registry: ghcr.io
|
|
133
141
|
username: ${{ github.actor }}
|
|
@@ -162,7 +170,7 @@ jobs:
|
|
|
162
170
|
# Note: load: true forces single-arch (amd64). The multi-arch
|
|
163
171
|
# build happens on the post-scan push step below.
|
|
164
172
|
- name: Build (local-only, for Trivy)
|
|
165
|
-
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7
|
|
173
|
+
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
|
166
174
|
with:
|
|
167
175
|
context: .
|
|
168
176
|
file: examples/wiki/Dockerfile
|
|
@@ -210,7 +218,7 @@ jobs:
|
|
|
210
218
|
- name: Push (multi-arch, after Trivy gate)
|
|
211
219
|
id: push
|
|
212
220
|
if: ${{ !inputs.dry_run && steps.tags.outputs.is_tag == 'true' }}
|
|
213
|
-
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7
|
|
221
|
+
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
|
214
222
|
with:
|
|
215
223
|
context: .
|
|
216
224
|
file: examples/wiki/Dockerfile
|
|
@@ -236,7 +244,7 @@ jobs:
|
|
|
236
244
|
if: ${{ !inputs.dry_run && steps.tags.outputs.is_tag == 'true' && steps.push.outputs.digest }}
|
|
237
245
|
env:
|
|
238
246
|
DIGEST: ${{ steps.push.outputs.digest }}
|
|
239
|
-
run: cosign sign --yes "${
|
|
247
|
+
run: cosign sign --yes "${IMAGE}@${DIGEST}"
|
|
240
248
|
|
|
241
249
|
- name: Generate SHA3-512 digest
|
|
242
250
|
if: ${{ !inputs.dry_run && steps.tags.outputs.is_tag == 'true' && steps.push.outputs.digest }}
|
|
@@ -245,8 +253,8 @@ jobs:
|
|
|
245
253
|
DIGEST: ${{ steps.push.outputs.digest }}
|
|
246
254
|
run: |
|
|
247
255
|
set -euo pipefail
|
|
248
|
-
docker pull "${
|
|
249
|
-
HASH=$(docker save "${
|
|
256
|
+
docker pull "${IMAGE}@${DIGEST}"
|
|
257
|
+
HASH=$(docker save "${IMAGE}@${DIGEST}" | openssl dgst -sha3-512 | awk '{print $NF}')
|
|
250
258
|
echo "SHA3-512: $HASH"
|
|
251
259
|
echo "sha3=$HASH" >> "$GITHUB_OUTPUT"
|
|
252
260
|
{
|
|
@@ -275,8 +283,8 @@ jobs:
|
|
|
275
283
|
echo "|---|---|"
|
|
276
284
|
echo "| **Version** | ${VERSION} |"
|
|
277
285
|
echo "| **Platforms** | linux/amd64, linux/arm64 |"
|
|
278
|
-
echo "| **Registry** | ${
|
|
279
|
-
echo "| **Commit** | ${
|
|
286
|
+
echo "| **Registry** | ${IMAGE} |"
|
|
287
|
+
echo "| **Commit** | ${GITHUB_SHA} |"
|
|
280
288
|
echo "| **Dry run** | ${DRY_RUN} |"
|
|
281
289
|
echo "| **Tag push** | ${IS_TAG} |"
|
|
282
290
|
echo ""
|
|
@@ -297,6 +305,11 @@ jobs:
|
|
|
297
305
|
if: ${{ !inputs.dry_run && needs.publish.outputs.digest != '' }}
|
|
298
306
|
runs-on: ubuntu-latest
|
|
299
307
|
timeout-minutes: 10
|
|
308
|
+
env:
|
|
309
|
+
# Hoisted so run: blocks reference $DIGEST instead of inlining the
|
|
310
|
+
# ${{ needs.publish.outputs.digest }} expression (template-injection
|
|
311
|
+
# hardening — keeps GitHub-context values out of shell-parsed text).
|
|
312
|
+
DIGEST: ${{ needs.publish.outputs.digest }}
|
|
300
313
|
steps:
|
|
301
314
|
# Smoke-test runs on a fresh runner — it doesn't inherit the
|
|
302
315
|
# publish job's GHCR auth. Log in first so `docker pull` works
|
|
@@ -304,19 +317,19 @@ jobs:
|
|
|
304
317
|
# against a public package, so this is the right shape regardless
|
|
305
318
|
# of visibility.
|
|
306
319
|
- name: Log in to GHCR
|
|
307
|
-
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
|
|
320
|
+
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
|
308
321
|
with:
|
|
309
322
|
registry: ghcr.io
|
|
310
323
|
username: ${{ github.actor }}
|
|
311
324
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
312
325
|
|
|
313
326
|
- name: Pull published image
|
|
314
|
-
run: docker pull "${
|
|
327
|
+
run: docker pull "${IMAGE}@${DIGEST}"
|
|
315
328
|
|
|
316
329
|
- name: Verify OCI labels
|
|
317
330
|
run: |
|
|
318
331
|
set -euo pipefail
|
|
319
|
-
LABELS=$(docker inspect "${
|
|
332
|
+
LABELS=$(docker inspect "${IMAGE}@${DIGEST}" --format '{{json .Config.Labels}}')
|
|
320
333
|
echo "$LABELS" | python3 -m json.tool
|
|
321
334
|
echo "$LABELS" | python3 -c "
|
|
322
335
|
import sys, json
|
|
@@ -342,7 +355,7 @@ jobs:
|
|
|
342
355
|
--security-opt no-new-privileges:true \
|
|
343
356
|
--cap-drop ALL \
|
|
344
357
|
-p 3008:3008 \
|
|
345
|
-
"${
|
|
358
|
+
"${IMAGE}@${DIGEST}"
|
|
346
359
|
|
|
347
360
|
echo "Waiting for /healthz..."
|
|
348
361
|
for i in $(seq 1 30); do
|
|
@@ -396,7 +409,7 @@ jobs:
|
|
|
396
409
|
{
|
|
397
410
|
echo "### Post-publish smoke ❌"
|
|
398
411
|
echo ""
|
|
399
|
-
echo "Smoke test failed for ${
|
|
412
|
+
echo "Smoke test failed for ${IMAGE}@${DIGEST}."
|
|
400
413
|
echo "See the 'Capture container diagnostics on failure' step above for"
|
|
401
414
|
echo "docker ps / inspect / logs output."
|
|
402
415
|
} >> "$GITHUB_STEP_SUMMARY"
|
|
@@ -39,6 +39,7 @@ jobs:
|
|
|
39
39
|
- name: Checkout (full history needed for first-parent walk)
|
|
40
40
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
41
41
|
with:
|
|
42
|
+
persist-credentials: false
|
|
42
43
|
fetch-depth: 0
|
|
43
44
|
fetch-tags: true
|
|
44
45
|
|
|
@@ -53,10 +54,15 @@ jobs:
|
|
|
53
54
|
- name: Resolve tag + verify chain
|
|
54
55
|
env:
|
|
55
56
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
57
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
58
|
+
# Hoisted: a workflow_dispatch input is operator-supplied text;
|
|
59
|
+
# inlining ${{ github.event.inputs.tag }} into the shell is the
|
|
60
|
+
# template-injection vector. Reference $INPUT_TAG instead.
|
|
61
|
+
INPUT_TAG: ${{ github.event.inputs.tag }}
|
|
56
62
|
run: |
|
|
57
63
|
set -euo pipefail
|
|
58
|
-
if [ "$
|
|
59
|
-
TAG="$
|
|
64
|
+
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
|
|
65
|
+
TAG="$INPUT_TAG"
|
|
60
66
|
else
|
|
61
67
|
TAG="${GITHUB_REF#refs/tags/}"
|
|
62
68
|
fi
|
|
@@ -77,7 +83,20 @@ jobs:
|
|
|
77
83
|
# pass that test. The strict first-parent invariant is
|
|
78
84
|
# what the project's squash-merge policy actually
|
|
79
85
|
# produces; check it directly.
|
|
80
|
-
|
|
86
|
+
#
|
|
87
|
+
# Capture rev-list output first, then grep against a
|
|
88
|
+
# here-string. The obvious-looking
|
|
89
|
+
# `git rev-list --first-parent origin/main | grep -qx "$SHA"`
|
|
90
|
+
# is a `set -o pipefail` + `grep -q` trap: when grep -q
|
|
91
|
+
# finds the match it exits early and closes its stdin,
|
|
92
|
+
# rev-list gets SIGPIPE and exits 141, and pipefail then
|
|
93
|
+
# propagates 141 as the pipeline's exit. The outer
|
|
94
|
+
# `if !` negates 141 → enters the false-fail branch
|
|
95
|
+
# every time on a long first-parent chain. (False-failed
|
|
96
|
+
# every release v0.13.18-.22.) The here-string consumes
|
|
97
|
+
# rev-list to completion first; no pipe, no SIGPIPE.
|
|
98
|
+
FIRST_PARENT=$(git rev-list --first-parent origin/main)
|
|
99
|
+
if ! grep -qFx "$SHA" <<<"$FIRST_PARENT"; then
|
|
81
100
|
echo "::error::tag $TAG points at $SHA which is NOT on main's first-parent history"
|
|
82
101
|
echo "::error::this means the tag was created from a side-branch commit that never merged via the project's squash-merge flow"
|
|
83
102
|
echo "::error::the publish workflow refuses to proceed; investigate before re-tagging"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# zizmor configuration (auto-discovered at .github/zizmor.yml).
|
|
2
|
+
#
|
|
3
|
+
# Suppressions live here rather than as inline `# zizmor: ignore[...]`
|
|
4
|
+
# comments because the affected lines are `uses:` references that
|
|
5
|
+
# already carry a pinact version comment (`# vX.Y.Z`). zizmor only
|
|
6
|
+
# honors an ignore pragma when `zizmor:` is the first token of the
|
|
7
|
+
# YAML comment; a `# vX.Y.Z # zizmor: ignore[...]` line reads as the
|
|
8
|
+
# comment text "vX.Y.Z # zizmor: ..." and the pragma is never seen.
|
|
9
|
+
# A config-file ignore is the only placement that does not collide
|
|
10
|
+
# with the SHA-pin version comment that pinact requires.
|
|
11
|
+
|
|
12
|
+
rules:
|
|
13
|
+
cache-poisoning:
|
|
14
|
+
# actions/setup-node carries an optional `cache:` input that, when
|
|
15
|
+
# set, restores a dependency cache. zizmor flags the *capability*
|
|
16
|
+
# whenever the workflow also has a release-class trigger
|
|
17
|
+
# (`push: tags: ["v*"]`), because a poisoned cache restored during a
|
|
18
|
+
# publishing run is high-impact. None of these workflows set a
|
|
19
|
+
# `cache:` input — no dependency cache is created or restored, so
|
|
20
|
+
# there is nothing to poison. The finding is capability-driven, not
|
|
21
|
+
# an observed cache.
|
|
22
|
+
#
|
|
23
|
+
# Invariant for future edits: if any step in one of these files adds
|
|
24
|
+
# a `cache:` input to a setup-* action, remove that file from this
|
|
25
|
+
# list and review the cache-poisoning exposure for real.
|
|
26
|
+
ignore:
|
|
27
|
+
- ci.yml
|
|
28
|
+
- npm-publish.yml
|
|
29
|
+
- release-container.yml
|