Repository navigation
test(security): hold end user talk links to an https host allow-list - #1375
hivecommons-hive[bot] wants to merge 1 commit into
Conversation
data/kubecon-na-2026-end-user-talks.json is the only data feed rendered as <a href> that no gate validates. src/components/EndUserTalkSchedule renders sourceUrl, apiUrl and 83 talk.url values as links whose destination the anchor text never shows, while validate-metrics, validate-case-studies and validate-radar-reports each hold their own feed's URLs to an https host allow-list that rejects a userinfo component. tests/end-user-talk-schedule.test.mjs cannot supply that gate: it asserts the component reproduces whatever the corpus says, and its anchor filter matches a '/program/schedule/?id=' substring a hostile host keeps. The gate is a test rather than a validate:* script because workflow-scripts requires every validate:*/check:* entry to be run by a workflow step or recorded as exempt, and the unit suite is already run by ci.yml and deploy-gh-pages.yml. Closes #1374 Signed-off-by: sec-check <sec-check@hive.kubestellar.io>
|
Important Held for human review by the hive's ACMM level gate. This PR was opened by the "sec-check" agent while Hive policy required a human checkpoint for that agent. Non-outreach agents are held at ACMM L3–L5; the Hive will keep the |
|
Superseded by #1406, which folds these assertions into |
Fold the URL gate proposed in cncf#1375 into tests/end-user-talks-data.test.mjs so the snapshot has one integrity contract rather than two files. Reuse checkUrl() from scripts/lib/validate-utils.mjs (landed in cncf#1381) instead of adding another copy of the scheme/userinfo/host check; sourceUrl and every talk.url must resolve to events.linuxfoundation.org and stay on the schedule page's pathname, apiUrl to sessionize.com. Closes cncf#1374 Signed-off-by: mrbobbytables <mrbobbytables@users.noreply.github.com> Co-authored-by: mrbobbytables <mrbobbytables@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Security Fix
data/kubecon-na-2026-end-user-talks.jsonis the only data feed this siterenders as
<a href>that no gate validates.src/components/EndUserTalkSchedule/index.jsrendersschedule.sourceUrlunder the fixed anchor text "live official schedule",
schedule.apiUrlunder"official Sessionize API", 83
talk.urlvalues under their talk titles, and#${day.id}for the day jump links — 85 hrefs whose destination the anchortext never shows.
Every sibling feed is gated:
scripts/validate-metrics.mjs,scripts/validate-case-studies.mjsandscripts/validate-radar-reports.mjseach parse their URLs and hold the host to an allow-list, rejecting a userinfo
component (
https://events.linuxfoundation.org@evil.example/) that resolves toa hostile host while reading as the official one in a skimmed JSON diff.
tests/end-user-talk-schedule.test.mjscannot supply that gate: it asserts thecomponent faithfully reproduces whatever the corpus says, so it stays green on
a re-pointed URL — its anchor filter matches the
/program/schedule/?id=substring, which both the userinfo and the
…linuxfoundation.org.evil.examplespellings keep.
What this adds
One file,
tests/end-user-talks-link-safety.test.mjs:sourceUrland everytalk.urlmust behttps:, carry no userinfo, andresolve to hostname
events.linuxfoundation.org;apiUrltosessionize.com— the two hostsscripts/collect-end-user-talks.mjsbuildsits output from.
talk.urlmust stay on the schedule page's own pathname, so a linkcannot be re-aimed elsewhere on the same host.
generatedAtmust parse (it is rendered throughnew Date(...).toLocaleDateString(), which publishes the literal string"Invalid Date" rather than failing the build).
day.idmust be a plain lowercase slug and unique, since it is written intoboth an element
idand anhref="#...".publishableUrl()itself is pinned against the ten rejection shapes, so theguard cannot pass vacuously if the corpus is ever empty.
Why a test rather than a
validate:end-user-talksscripttests/workflow-scripts.test.mjsrequires everyvalidate:*/check:*entryin
package.jsonto be run by a step in.github/workflows/, or recorded inGATES_NOT_RUN_BY_CIas a deliberate omission. Recording it there would leavethe hole open while looking closed. The unit suite is already run on both paths
this needs to block —
ci.yml:40(test:unit:coverage:check) anddeploy-gh-pages.yml:41(test:unit) — so a test file closes it with noworkflow change and no exemption. Issue #1374 records the exact two workflow
steps for a maintainer who prefers the
validate:*shape for consistency; thatvariant needs a human or an
ISSUES_PRS_MERGEagent, because anISSUES_AND_PRStoken is minted at thecontributortier and GitHub rejectsany push touching
.github/workflows/**. This PR does not depend on it andis complete on its own.
Verification
node --test tests/end-user-talks-link-safety.test.mjs— 4 pass.sourceUrltohttps://events.linuxfoundation.org@evil.example/program/schedule/and onetalk.urltohttps://events.linuxfoundation.org.evil.example/…fails twoof the four assertions with the offending value named;
tests/end-user-talk-schedule.test.mjspasses on that same mutated corpus,which is the gap this closes. Corpus restored afterwards — the diff is the
one new test file and nothing else.
tests/workflow-scripts.test.mjs+tests/refresh-script-wiring.test.mjs—26 pass.
validator-smoke-coverage,e2e-coverage-describe-gate,e2e-data-dependent-skips,site-config(the suites that enumeratetests/) — 49 pass.npx prettier --checkclean. No source file is added, so the--check-source-file-regions/--require-source-filesobligations areunchanged:
SOURCE_ROOTSintests/tools/coverage-report.mjsisscripts,src,tests/tools, and atests/*.test.mjsfile is neithersource nor harness.
Disjointness from the open hold-gated PRs
scripts/collect-launch-metrics.mjs,scripts/collect-metrics.mjs,scripts/lib/github.mjs— none touched here.tests/coverage-report-source-files.test.mjs,tests/tools/coverage-report.mjs— read only, never edited here.This PR adds exactly one new file and modifies none.
Closes #1374
Filed by sec-check agent (ACMM L4/L5 — hold-gated mode). Hold-gated: human review required.
— hive: agent=sec-check backend=copilot model=claude-opus-5 copilot=1.0.88