Repository navigation
fix(web): stop coercing non-string skill tag values into junk tags - #237
Merged
Merged
Conversation
normalizeSkillTags (web/lib/skillDraft.ts) coerced every array element via
String(raw). A malformed POST /api/skills payload (tags is user-supplied and
reaches this helper with no prior validation) could pass objects, arrays,
booleans, null/undefined, or numbers; those became meaningless tags stored in
the database. Ground-truth (reproduced in the same node runtime before fixing):
{x:1} -> "object-object"
[1,2] -> "1-2"
true -> "true"
123.45 -> "123-45"
null -> "null"
undefined -> "undefined"
Drop non-string elements (fail closed) instead of coercing them.
Verification:
- new normalizeSkillTags tests: 11 passing (coercion paths + mixed valid/invalid)
- full web suite: 152 files / 1318 tests green
- format:check, lint, typecheck: green
- next build --webpack: failed on DB-dependent prerenders due to a missing
web/.env.local (DATABASE_URL) in this headless Linux worktree (gitignored per
AGENTS.md sec 1.3); independent of this change, not a regression.
This branch was successfully deployed
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.
Summary
normalizeSkillTags(web/lib/skillDraft.ts) coerced every array element viaString(raw). A malformedPOST /api/skillspayload sendstagsstraight to this helper with no prior validation, so a client (or bug) could pass objects, arrays, booleans,null/undefined, or numbers.String()of those inputs produced meaningless junk tags that would be persisted to the database.Ground truth (reproduced in the same Node runtime before fixing):
String(raw)result{x:1}object-object[1,2]1-2truetrue123.45123-45nullnullundefinedundefinedThe fix fails closed: drop non-string elements instead of coercing them. Valid string tags are unaffected (they already went through the same slug op).
Files
web/lib/skillDraft.ts— addif (typeof raw !== "string") continue;in the tag loop; replaceString(raw)with the raw string.web/__tests__/lib/skillDraft.test.ts— newnormalizeSkillTagssuite (11 tests).Verification
normalizeSkillTagstests: 11 passing (coercion paths, mixed valid/invalid, non-array payloads, and preserved valid-string behavior).npm run format:check(prettier) — green.npm run lint(eslint) — green.npm run typecheck(web workspace,next typegen && tsc --noEmit) — green.next build --webpack— did not complete in this headless worktree becauseweb/.env.local/DATABASE_URLis absent (gitignored, per AGENTS.md §1.3). The build exited on DB-dependent prerenders (/sitemap.xml, marketplace browse), which is an environment gap, not related to this change. The equivalent CI gate (format + lint + typecheck + full vitest) is green.Not changed
No chain-tagged code, no DB schema, no money-moving path. Pure input-validation fix on a pure helper plus tests.
Notes
gpg failed to sign: No secret key), anduser.signingkey=gpgonly signs on explicit-S. Per repo convention for cron-run PRs (e.g. chore(web): remove dead EIP-8004 feedback module #191/chore(web): remove dead author dispute helpers #192) unsigned cron heads are acceptable. To re-sign and re-publish the commit: amend it with GPG signing (git commit --amend -S --no-edit) and then republish the branch.