fix: enforce safe encodeURIComponent/decodeURIComponent across packages - #94
Conversation
Add safeEncodeURIComponent and safeDecodeURIComponent to @standard-server/shared (mirroring @orpc/shared) and ban the raw globals in package source via no-restricted-globals, which also catches bare function references that the call-only ban/ban rule missed. Content-Disposition generation and API Gateway path escaping called the raw global and threw a URIError on filenames or paths containing a lone surrogate; both now emit U+FFFD instead. tryDecodeURIComponent is renamed to safeDecodeURIComponent.
@standard-server/aws-lambda
@standard-server/core
@standard-server/fastify
@standard-server/fetch
@standard-server/node
@standard-server/peer
@standard-server/shared
commit: |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Merging this PR will not alter performance
Comparing Footnotes
|
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- New
safeEncodeURIComponent/safeDecodeURIComponenthelpers —packages/shared/src/uri.tsreplaces the throwing raw globals;safeDecodeURIComponentis the renamedtryDecodeURIComponentwith identical behavior, and the encoder falls back to replacing lone surrogates with U+FFFD before re-encoding onURIError. - Content-Disposition —
packages/core/src/utils.tsnow uses the helpers, so a lone surrogate in a filename emits%EF%BF%BDinstead of throwing. - AWS Lambda path escaping —
packages/aws-lambda/src/url.tstoPathnameuses the safe encoder, closing the lone-surrogate throw on a decoded event path. - Lint enforcement —
eslint.config.jsdrops the oldban/bandecodeURIComponententry and adds apackages/*/src/**-scopedno-restricted-globalsblock (re-listing antfu'sglobal/self) that also catches bare references such aspath.replace(re, encodeURIComponent); tests/playgrounds opt out. - Tests — shared suite covers well-formed, lone, reversed, and mixed surrogates plus malformed percent input; lone-surrogate regression cases added to core and aws-lambda, including a cross-check against the WHATWG
URLpathname setter.
Verified locally: pnpm run lint clean, tsc -b clean for core/aws-lambda, and the three touched suites pass (85 tests). Confirmed the new no-restricted-globals block flags a bare encodeURIComponent reference in package source, and that no tryDecodeURIComponent references remain.
DeepSeek Flash (default — pick a model for stronger reviews) | 𝕏

Adds
safeEncodeURIComponentandsafeDecodeURIComponentto@standard-server/shared, mirroring@orpc/shared, and bans the raw globals in package source withno-restricted-globals. Content-Disposition generation and API Gateway path escaping previously called the raw global and threw aURIErroron a filename or path containing a lone surrogate; both now emit U+FFFD instead.Fixes
generateContentDispositionno longer throws on a lone surrogate in the filename.toStandardUrlin aws-lambda no longer throws on a lone surrogate in a decoded path, and its output matches the WHATWGURLpathname setter for that case.path.replace(re, encodeURIComponent)are now caught by lint. The previousban/banentry only matched call expressions, so the aws-lambda case slipped through.Breaking
tryDecodeURIComponentin@standard-server/sharedis renamed tosafeDecodeURIComponent. The package is internal and oRPC does not import the old name.Testing
pnpm eslint .,pnpm run type:check, andpnpm vitest run(59 files, 1128 tests) all pass.