[sec-check] fix: validate imported project card href by URL, not substring (scripts/import-architectures.mjs renderProjectCards + scripts/lib/project-card-links.mjs) - #249
Open
kubestellar-hive[bot] wants to merge 1 commit into
Conversation
…tring
renderProjectCards() chose each published <CNCFProjectCard> link target with
link.includes('cncf.io/projects/'), which any host satisfies by putting that
text in a path, query or fragment. Card content comes from cncf/architecture
and is imported unattended by the daily import workflow, so upstream Markdown
could point a CNCF-branded card at an arbitrary origin.
Add scripts/lib/project-card-links.mjs with isCncfProjectHref(), which parses
the URL and requires https, no userinfo, a cncf.io (or subdomain) host and a
/projects/ path, and use it to select the href. All 50 cards currently in
docs/architectures/ already satisfy the predicate, so generated output is
unchanged.
Signed-off-by: kubestellar-hive[bot] <kubestellar-hive@hive.kubestellar.io>
Contributor
Author
|
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 automatically remove the |
This was referenced Sep 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Security Fix
renderProjectCards()inscripts/import-architectures.mjschose the link target forevery published
<CNCFProjectCard>with a substring test:String.prototype.includesmatches anywhere in the URL, so any host satisfies it byputting that text in a path, query or fragment — verified on
main@00b44df:Card content comes from
cncf/architecture, which.github/workflows/import-architectures.ymlclones and imports unattended every day,so upstream Markdown could aim a CNCF-branded project card at an arbitrary origin.
What this changes
Claimed ground:
scripts/import-architectures.mjs→renderProjectCards()hrefselection only, plus the new
scripts/lib/project-card-links.mjsandtests/project-card-links.test.mjs.scripts/lib/project-card-links.mjs(new) —isCncfProjectHref()parses the URLwith
new URL()and requireshttps:, no userinfo, a host equal tocncf.ioorending in
.cncf.io, and a path under/projects/.scripts/import-architectures.mjs—renderProjectCards()selects the href withlinks.find(isCncfProjectHref); the existinghttps://www.cncf.io/projects/<slug>/fallback is untouched, so a rejected upstream link degrades to the canonical CNCF URL
rather than disappearing.
tests/project-card-links.test.mjs(new) — 7 tests covering the bypass URL above,lookalike hosts (
cncf.io.evil.example,notcncf.io), userinfo disguise(
https://www.cncf.io@evil.example/...),http://downgrade,javascript:, CNCFURLs outside
/projects/, and non-URL input.Verification
node --test tests/— 62/62 pass (55 before, 7 new).href=values currently indocs/architectures/*.mdsatisfy the new predicate (checked programmatically,0 rejected), so the next import produces identical cards.
npx prettier --checkclean on all three files.Disjointness
mirrorProjectAssets()andsanitizeArchitectureAssets()— different functions, no shared hunks.scripts/lib/mdx-active-content.mjsandscripts/validate-architectures.mjs— no shared files.logo=third-party hot-linking problem in the same function is filed separatelyas [sec-check] Imported project cards hot-link third-party logos (16 live cards): projectAsset() returns remote URLs unchanged (scripts/import-architectures.mjs) #248 and is not addressed here: fixing it requires regenerating every imported
architecture doc, which is a distinct deliverable.
Closes #247
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