Skip to content

Maintenance pass: security hardening, dep bumps, CI workflows#1

Merged
botre merged 5 commits into
masterfrom
maintenance-pass
May 9, 2026
Merged

Maintenance pass: security hardening, dep bumps, CI workflows#1
botre merged 5 commits into
masterfrom
maintenance-pass

Conversation

@botre

@botre botre commented May 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Security: harden toJSON against prototype pollution (rejects key paths containing __proto__, prototype, constructor) and against memory-DoS via large array indices (numeric segments must be non-negative integers within a bounded range).
  • Deps: bump prettier 3.3 → 3.8, tsup 8.2 → 8.5, typescript 5.5 → 5.9, vitest 2.0 → 4.1. Vitest 3 + 4 migration guides reviewed; nothing in this suite is affected. npm audit reports 0 vulnerabilities after the bump.
  • DX: npm test now runs once instead of staying in watch mode.
  • CI: add Check (PR + workflow_call) and Release (push to master → check → bump version → publish with --provenance) workflows, mirroring formspark/use-formspark and formspark/localview.
  • Docs: fix "nestable" → "nested" typo in the README.

Test plan

  • npm test — 12/12 pass (10 existing + 2 new for prototype-pollution and oversized-index defense)
  • npm run build — ESM + CJS + IIFE + DTS build cleanly on tsup 8.5 + TS 5.9
  • npm audit — 0 vulnerabilities
  • Confirm npm-publish auth (NPM_TOKEN secret or trusted-publisher OIDC) is wired up before merging — the workflow mirrors the other formspark repos but the token mechanism isn't visible in their YAML
  • Confirm commit-message conventions match what phips28/gh-action-bump-version@v11.0.7 expects, otherwise the version won't auto-bump

botre added 5 commits May 9, 2026 08:46
Skip key paths containing __proto__, prototype, or constructor so
attacker-controlled FormData keys cannot mutate Object.prototype.

Treat numeric path segments as array indices only when they are
non-negative integers within a bounded range, preventing huge sparse
allocations from keys like items[999999999].

Also fix a "nestable" -> "nested" typo in the README.
prettier 3.3 -> 3.8, tsup 8.2 -> 8.5, typescript 5.5 -> 5.9, vitest
2.0 -> 4.1. Reviewed the vitest 3 and 4 migration guides; the breaking
changes (test-options arg order, stricter error equality, snapshot
shadow-DOM, mock-name change) do not affect this suite. Stayed on
TypeScript 5.x rather than the freshly-released 6.0.

Switched the test script to "vitest run" so CI does not hang in watch
mode.

npm audit reports 0 vulnerabilities after the bump.
Mirror the formspark/use-formspark and formspark/localview setup:
check.yml runs build + tests on PRs and via workflow_call, release.yml
runs on push to master, calls check, then bumps the version from
commit messages and publishes to npm with provenance.
Line coverage was already 100%, but several semantic edge cases were
not pinned. Added tests for:

- empty FormData and empty-string values
- repeated keys (last write wins)
- File values pass through as-is
- type collisions in both directions (scalar then nested, nested then
  scalar)
- MAX_ARRAY_INDEX boundary (10000 array, 10001 falls through to object)
- negative indices become object keys
- empty brackets collapse to a scalar key
- dots inside [] are still split, so items[1.5] becomes items[1][5]

Also adds @vitest/coverage-v8 so coverage can be run locally.
Switch from a single split regex to a tokenizer that captures
[...] segments as one part regardless of inner characters. Previously
items[1.5] parsed as items[1][5] because the splitter did not
distinguish a dot inside brackets from a dot separator. Now it parses
as items["1.5"], which (combined with the float-index guard) becomes a
plain object key.

Same fix lets items[a.b] become { items: { "a.b": "x" } } instead of a
nonsensical nested structure.
@botre botre merged commit 41c84fc into master May 9, 2026
1 check passed
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