A minified vendored bundle is committed to the repo, which REPO_POLICIES forbids #145

Closed
opened 2026-08-12 12:53:08 +02:00 by clawbot · 1 comment
Collaborator

Raised by the independent review of #144 while sweeping shipped assets for debug logging. Pre-existing and not attacker-reachable, so it is not milestoned 1.0.0 — it belongs to the next cycle.

static/js/alpine.min.js is a committed, minified third-party bundle. REPO_POLICIES.md:248 forbids committing minified bundles.

It also carries 8 console.warn calls, which is why it surfaced: the debug-logging sweep in #141 deliberately excluded it as vendored, which is defensible for that sweep but leaves the underlying policy breach in place.

The policy exists because a minified blob is unreviewable — nobody can tell what is in it, and it is exactly the shape a supply-chain compromise takes. REPO_POLICIES.md also requires every external dependency be referenced by content hash.

Definition of done

  • Alpine is no longer present as a committed minified blob.
  • However it is obtained, the reference is pinned by content hash per REPO_POLICIES.md, and the hash is verified at fetch time.
  • The page still works: templates/base.html:14 is the only loader, so whatever replaces it must satisfy that.

Options worth weighing in the PR

  1. Fetch it at build time in the Dockerfile from a pinned URL with a verified sha256, the way script/bootstrap handles other external tools.
  2. Vendor the UNminified source, which is reviewable, and let the build minify it.
  3. Drop Alpine if the UI's use of it is small enough to write directly.

State which you chose and why. Option 3 is worth genuinely checking before assuming 1 or 2 — grep the templates for how much Alpine is actually used.

Implementation requirements

  • Branch from next, PR based on next, single commit, title ending (closes #N).
  • Do not modify TODO.md.
  • Gate on make check plus the Docker lint path with the cache defeated (#119).
Raised by the independent review of https://git.eeqj.de/sneak/webhooker/pulls/144 while sweeping shipped assets for debug logging. Pre-existing and not attacker-reachable, so it is not milestoned 1.0.0 — it belongs to the next cycle. `static/js/alpine.min.js` is a committed, minified third-party bundle. `REPO_POLICIES.md:248` forbids committing minified bundles. It also carries 8 `console.warn` calls, which is why it surfaced: the debug-logging sweep in https://git.eeqj.de/sneak/webhooker/issues/141 deliberately excluded it as vendored, which is defensible for that sweep but leaves the underlying policy breach in place. The policy exists because a minified blob is unreviewable — nobody can tell what is in it, and it is exactly the shape a supply-chain compromise takes. `REPO_POLICIES.md` also requires every external dependency be referenced by content hash. ## Definition of done - Alpine is no longer present as a committed minified blob. - However it is obtained, the reference is pinned by content hash per `REPO_POLICIES.md`, and the hash is verified at fetch time. - The page still works: `templates/base.html:14` is the only loader, so whatever replaces it must satisfy that. ## Options worth weighing in the PR 1. Fetch it at build time in the Dockerfile from a pinned URL with a verified sha256, the way `script/bootstrap` handles other external tools. 2. Vendor the UNminified source, which is reviewable, and let the build minify it. 3. Drop Alpine if the UI's use of it is small enough to write directly. State which you chose and why. Option 3 is worth genuinely checking before assuming 1 or 2 — grep the templates for how much Alpine is actually used. ## Implementation requirements - Branch from `next`, PR based on `next`, single commit, title ending ` (closes #N)`. - Do not modify `TODO.md`. - Gate on `make check` plus the Docker lint path with the cache defeated (https://git.eeqj.de/sneak/webhooker/issues/119).
clawbot self-assigned this 2026-08-12 12:53:09 +02:00
clawbot added this to the 1.0.0 milestone 2026-08-17 22:36:42 +02:00
Author
Collaborator

Moved INTO the 1.0.0 milestone, reversing the "not milestoned" line in the body above.

Reason: the test for 1.0 is not only what an attacker can reach but whether the shipped artifact is verifiable. A 1.0 release that serves unreviewable, un-hash-pinned third-party JavaScript into the admin's browser fails that directly, and it breaks two rules REPO_POLICIES.md states the release claims to follow (no committed minified bundles; every external reference pinned by content hash). "Pre-existing" is an argument about when it started, not about whether it should be in the tag.

Direction: take option 1 — fetch at build time from a pinned URL with a verified sha256, the way script/bootstrap already handles external tools — unless you find a concrete blocker, in which case option 2. Option 3 (drop Alpine) is real: a template grep shows only 19 directive uses across navbar.html, source_detail.html and source_logs.html. But rewriting working interactive UI by hand at the end of a release cycle trades a supply-chain problem for a regression risk in three pages nobody will re-test carefully, so it is the wrong trade right now. File it as a follow-up if you think it is worth doing later.

One correction to the body: the loader is templates/base.html:13, not :14 — line 14 is now app.js.

Moved INTO the `1.0.0` milestone, reversing the "not milestoned" line in the body above. Reason: the test for 1.0 is not only what an attacker can reach but whether the shipped artifact is verifiable. A 1.0 release that serves unreviewable, un-hash-pinned third-party JavaScript into the admin's browser fails that directly, and it breaks two rules `REPO_POLICIES.md` states the release claims to follow (no committed minified bundles; every external reference pinned by content hash). "Pre-existing" is an argument about when it started, not about whether it should be in the tag. Direction: take **option 1** — fetch at build time from a pinned URL with a verified sha256, the way `script/bootstrap` already handles external tools — unless you find a concrete blocker, in which case option 2. Option 3 (drop Alpine) is real: a template grep shows only 19 directive uses across `navbar.html`, `source_detail.html` and `source_logs.html`. But rewriting working interactive UI by hand at the end of a release cycle trades a supply-chain problem for a regression risk in three pages nobody will re-test carefully, so it is the wrong trade right now. File it as a follow-up if you think it is worth doing later. One correction to the body: the loader is `templates/base.html:13`, not `:14` — line 14 is now `app.js`.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/webhooker#145