Skip to content

fix(web): stop coercing non-string skill tag values into junk tags - #237

Merged
dirtybits merged 1 commit into
mainfrom
fix/normalize-skill-tags-nonstring-elements
Oct 21, 2026
Merged

dirtybits merged 1 commit into
mainfrom
fix/normalize-skill-tags-nonstring-elements

Conversation

@dirtybits

Copy link
Copy Markdown
Owner

Summary

normalizeSkillTags (web/lib/skillDraft.ts) coerced every array element via String(raw). A malformed POST /api/skills payload sends tags straight 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):

input old String(raw) result
{x:1} object-object
[1,2] 1-2
true true
123.45 123-45
null null
undefined undefined

The 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 — add if (typeof raw !== "string") continue; in the tag loop; replace String(raw) with the raw string.
  • web/__tests__/lib/skillDraft.test.ts — new normalizeSkillTags suite (11 tests).

Verification

  • New normalizeSkillTags tests: 11 passing (coercion paths, mixed valid/invalid, non-array payloads, and preserved valid-string behavior).
  • Full web test suite: 152 files / 1318 tests green (vitest, no file parallelism).
  • 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 because web/.env.local / DATABASE_URL is 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

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.
@dirtybits
dirtybits merged commit 8f2d935 into main Oct 21, 2026
3 checks passed
@dirtybits
dirtybits deleted the fix/normalize-skill-tags-nonstring-elements branch October 21, 2026 16:36

This branch was successfully deployed

1 active deployment
Preview — f090ce16 Deployed Oct 12, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant