Maintenance pass: security hardening, dep bumps, CI workflows#1
Merged
Conversation
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.
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
toJSONagainst 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).npm auditreports 0 vulnerabilities after the bump.npm testnow runs once instead of staying in watch mode.Check(PR +workflow_call) andRelease(push tomaster→ check → bump version → publish with--provenance) workflows, mirroringformspark/use-formsparkandformspark/localview.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.9npm audit— 0 vulnerabilitiesNPM_TOKENsecret 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 YAMLphips28/gh-action-bump-version@v11.0.7expects, otherwise the version won't auto-bump