fix: validate community roster GitHub handles before the API fetch - #316
Open
kubestellar-hive[bot] wants to merge 1 commit into
Open
kubestellar-hive[bot] wants to merge 1 commit into
kubestellar-hive[bot] wants to merge 1 commit into
Conversation
scripts/fetch-community-people.mjs interpolated the roster 'github' field straight into the api.github.com request path with no validation and no percent-encoding, so a handle containing a path separator or dot segment re-pointed the request at a different endpoint and published that response as somebody's profile. Reject any handle that is not a GitHub username (alphanumerics plus single internal hyphens, 1-39 chars) before fetching, percent-encode at the interpolation point, and reuse makeGitHubHeaders() from scripts/lib/github.mjs instead of hand-rolling the Authorization header. Closes #313 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 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
scripts/fetch-community-people.mjsinterpolated thegithubfield fromdata/community-roster.jsondirectly into an api.github.com request path,with no validation and no percent-encoding:
The literal prefix pins the origin, so this was never a cross-origin token
leak —
api.github.comcannot be replaced. What it allowed was endpointconfusion: a handle such as
../../orgs/evilresolves tohttps://api.github.com/orgs/evil, and that response body is what gets writteninto
data/community-people.json(name,company,bio,location,blog,avatar_url) and rendered bysrc/components/CommunityPeople..github/workflows/refresh-community-people.ymlruns this on a schedule andopens the refresh PR automatically, so a malformed handle propagates without
the roster diff being re-read.
What this changes
scripts/fetch-community-people.mjsonly:GITHUB_HANDLE, matching GitHub's username grammar (alphanumerics plussingle internal hyphens, 1-39 characters), and exits non-zero with the
offending entry named when a roster handle fails it. A malformed handle is a
roster defect, so failing the scheduled refresh surfaces it rather than
quietly publishing a substituted profile.
makeGitHubHeaders()fromscripts/lib/github.mjs, so this call site inherits centralised authhandling the way
scripts/collect-metrics.mjsdoes. The defaultUser-Agentin that helper is the samecncf-endusers-site-buildstringthat was inlined here, so request headers are unchanged.
Falsy handles keep their existing meaning: the two roster entries with
github: nullare still skipped, not rejected.Verification
data/community-roster.jsonsatisfy the newpredicate, so the committed roster is unaffected and generated output is
unchanged.
node --test tests/— 67/67 pass (55 before, 12 new).tests/community-roster-handles.test.mjsruns entirely offline via theexisting
runScriptWithFixtureshelper: every fixture entry usesgithub: nullso no network request is ever issued, and only the rejectedhandle decides the exit status.
npx prettier --checkis clean on the new test file. The pre-existingprettier violations in
scripts/fetch-community-people.mjsare left alone —they are present on
mainat00b44dfand reformatting the file wouldwiden this diff into unrelated lines.
Scope / overlap
Claims
scripts/fetch-community-people.mjs(theGITHUB_HANDLEpredicate,the header construction, and the
fetchcall) plus the new filetests/community-roster-handles.test.mjs. Checked against the open PR set:scripts/fetch-community-people.mjswith tests only(
tests/fetch-community-people.test.mjs,tests/helpers-fetch-mock.mjs) anddoes not modify the script — disjoint files, though a reviewer landing both
should note that this PR adds a fail-closed path for malformed handles.
scripts/lib/github.mjswith tests only(
tests/lib-github.test.mjs); this PR imports that module without changingit.
data/community-roster.jsonwith a contract test(
tests/community-roster-data.test.mjs); this PR does not touch that datafile.
blogfield(
src/components/CommunityPeople/index.js,src/lib/profile-links.mjs);this PR covers the fetch side and touches neither.
Closes #313
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