Skip to content

[architect] Six more duplicated https-URL-safety validators left uncentralized after #1381's checkUrl() consolidation #1388

Closed

Description

@hivecommons-hive

Architecture Finding

Type: coupling / incomplete-abstraction (duplicated security-relevant validation logic)
Affected area: scripts/validate-*.mjs, scripts/lib/project-card-links.mjs, src/lib/profile-links.mjs

Open PR #1381 ("refactor: share https-URL validation across validator scripts")
consolidates the "parse as URL, require https:, reject a userinfo component
that can disguise the real host" check into a single checkUrl() helper in
scripts/lib/validate-utils.mjs, replacing independent copies in
validate-awards.mjs, validate-launch-metrics.mjs, validate-members.mjs,
validate-metrics.mjs, and validate-projects-born.mjs.

That consolidation is not complete. The identical pattern — new URL(value),
reject non-https: protocol, reject url.username/url.password, optionally
hold url.hostname to an allow-list — still exists as independent, drift-prone
copies in six more places:

  • scripts/validate-case-studies.mjs — publishableUrl() (host allow-list: cncf.io)
  • scripts/validate-radar-reports.mjs — publishableUrl() (host allow-list: cncf.io, and its own comment says it "mirrors scripts/validate-case-studies.mjs")
  • scripts/validate-community-groups.mjs — publishableRepositoryUrl() (host allow-list: github.com, comment says it "mirrors publishableUrl() in validate-case-studies.mjs and isCncfProjectHref() in lib/project-card-links.mjs")
  • scripts/validate-architectures.mjs — isHttpsUrl() (no host allow-list)
  • scripts/lib/project-card-links.mjs — isCncfProjectHref() (host allow-list: cncf.io, plus a path-prefix check)
  • src/lib/profile-links.mjs — websiteUrl() (scheme-optional variant: a bare host is coerced to https://, and non-https protocols in ALLOWED_PROTOCOLS are kept rather than rejected)

Each of these files' own comments already point at the sibling copies by name —
the duplication is known and acknowledged in-tree, it just hasn't been
centralized. checkUrl()'s options.allowedHostSuffixes already covers the
cncf.io/github.com allow-list cases; isCncfProjectHref()'s path-prefix
check and websiteUrl()'s scheme-optional coercion are the two call sites that
need an option added to checkUrl() rather than a drop-in call.

Impact

Six copies of a security-relevant parser (guarding against userinfo-authority
spoofing such as https://cncf.io@evil.example/) can silently drift from each
other and from the now-canonical checkUrl(), the same way validate-metrics.mjs
had a host allow-list the other four pre-#1381 copies lacked. A future
hardening (e.g. tightening the allow-list, rejecting IDN homograph hosts) has to
be remembered and re-applied at up to seven call sites instead of one.

Recommendation

Once #1381 merges checkUrl() into scripts/lib/validate-utils.mjs, extend it
(e.g. an options.pathPrefix and an options.coerceScheme/defaultScheme
option) and replace the six remaining local implementations with calls to it:

  • scripts/validate-case-studies.mjs
  • scripts/validate-radar-reports.mjs
  • scripts/validate-community-groups.mjs
  • scripts/validate-architectures.mjs
  • scripts/lib/project-card-links.mjs
  • src/lib/profile-links.mjs

This is a single follow-up PR (one mechanical pattern, six sites), not six
separate PRs. It is blocked on #1381 merging first, since checkUrl() does not
exist on main yet — filing now so the remaining call sites are tracked and
the follow-up is mechanical once the base helper lands.


Filed by architect agent (ACMM L5 — hold-gated mode)


🐝 Hive Agent: architect | Instance: hosted-available-lke648397-260827-5n31 | SHA: f5586b0

— hive: agent=architect backend=copilot model=claude-opus-4-6 copilot=1.0.88

Activity

  1. mrbobbytables commented on Oct 13, 2026

    @mrbobbytables
    Member

    Kept open as the follow-up to #1381 (merged; closed #1380). Note for whoever picks this up: #1406 deliberately reuses checkUrl() for the end-user-talks gate rather than adding a seventh copy, so the remaining list here is unchanged.

  2. added
    🐝 covered by PRHive verified that an open PR references or claims this issue; still actionable until confirmed
    on Oct 13, 2026
  3. hivecommons-hive commented on Oct 13, 2026

    @hivecommons-hive
    ContributorAuthor

    task-list sweep: 0 of 6 items ticked. Not closing yet — outstanding boxes remain.

    Outstanding items:

    • 🔲 scripts/validate-case-studies.mjs
    • 🔲 scripts/validate-radar-reports.mjs
    • 🔲 scripts/validate-community-groups.mjs
    • 🔲 scripts/validate-architectures.mjs
    • 🔲 scripts/lib/project-card-links.mjs
    • 🔲 src/lib/profile-links.mjs

    Merged PRs referencing this issue so far:

    This comment is edited in place by the task-list sweep on every cycle; it is not duplicated.

  4. added
    hive/likely-doneHive verified that a merged PR references or claims this issue; pending confirmation
    and removed
    🐝 covered by PRHive verified that an open PR references or claims this issue; still actionable until confirmed
    on Oct 13, 2026
  5. added a commit that references this issue on Oct 13, 2026
    1071be6
  6. removed
    hive/likely-doneHive verified that a merged PR references or claims this issue; pending confirmation
    on Oct 13, 2026
  7. hivecommons-hive commented on Oct 13, 2026

    @hivecommons-hive
    ContributorAuthor

    Verification pass (scanner, 2026-10-13) against main @40c6e97:

    New related finding filed separately: scripts/validate-enduser-members.mjs carries a seventh local copy that neither #1381 nor this issue's six named (its messages and null-handling differ from the shared contract, so it needs its own pass).


    🐝 Hive Agent: scanner | Instance: hosted-available-lke648397-260827-5n31 | SHA: unknown

    — hive: agent=scanner backend=copilot model=kimi-k3 copilot=1.0.88

  8. mrbobbytables commented on Oct 13, 2026

    @mrbobbytables
    Member

    Superseded by #1421 for the remaining validator; both are now closed by #1420.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/architectCreated by Hive for agent-filed issue provenancearchitectureCreated by Hive for agent-filed issue provenancehive/verified-opentech-debtCreated by Hive for agent-filed issue provenance

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions