release: v3.14.1 - refuse prototype-polluting mount-path segments in… - #308
Open
cldmv-bot[bot] wants to merge 10 commits into
Open
release: v3.14.1 - refuse prototype-polluting mount-path segments in…#308cldmv-bot[bot] wants to merge 10 commits into
cldmv-bot[bot] wants to merge 10 commits into
Conversation
A dotted or array mount path passed to api.slothlet.api.add() was split into segments and written into the api tree without guarding prototype-chain segment names. A path containing __proto__, constructor, or prototype therefore mutated Object.prototype / Function.prototype globally instead of the api tree — classic prototype pollution — with no error raised. normalizeApiPath now refuses any of these three names in any segment position (both the dotted-string and array path forms) with INVALID_CONFIG_API_PATH_INVALID and the new API_PATH_REASON_UNSAFE_SEGMENT reason, mirroring the existing reserved-name guard. Adds the reason string to all 12 language packs and coverage for both path forms plus a no-pollution assertion. This corrects never-intended behavior (a silent global write), so it ships as a patch — no legitimate consumer mounts at __proto__/constructor/prototype. Fixes #302
…dpoints The wrapper get trap resolved a property read to `impl[prop]` and, for any function-valued result, wrapped it as a child endpoint and registered ownership. On a callable leaf, that meant merely READING an inherited Function.prototype member — `apply`, `call`, `bind`, `constructor` — (or the non-enumerable own `prototype` slot) rewrote the leaf's loader record: it flipped from kind "function" to "namespace" and grew a phantom child (`leaf.apply`, …). A later leaves() or re-composition then surfaced Function.prototype.apply in place of the leaf. `leaf.apply(thisArg, args)` — a common forwarding idiom — silently corrupted the served surface (Reflect.apply was the only safe workaround). The get trap now returns the function's own built-in members directly instead of wrapping them: for a function impl, a property that is not a user-added ENUMERABLE own property is returned as-is. Genuine enumerable own children of a callable still materialize as endpoints. Covered in eager and lazy modes, including a callable that carries a real user child. Fixes #304
The prototype-pollution guard added to normalizeApiPath preempted the dedicated
LOOSE_SET_RESERVED_KEY error that setOwnedProperty raises for `self.<key> = …`
assignments: setOwnedProperty calls normalizeApiPath first, so a
`self.prototype = {}` / `self['__proto__'] = obj` now threw the generic
INVALID_CONFIG_API_PATH_INVALID instead, breaking
runtime/self-assign-prototype-pollution.
Run the reserved-segment check (LOOSE_SET_RESERVED_KEY) before normalizeApiPath
so the self-assign surface keeps its own error while the api.add() mount-path
surface keeps the new unsafe-segment error. Both guards stay reachable and tested.
Address Copilot review on #305: - The "__-prefixed still accepted" test mounted at "plugins", so it never exercised a __-prefixed segment. Mount "__config.value" and a ["prototypeName","leaf"] substring path instead, proving the guard matches whole segments (only __proto__/constructor/prototype), not prefixes/substrings. - Capitalize the ru-ru API_PATH_REASON_UNSAFE_SEGMENT string to match that locale's sentence-cased sibling messages.
…port Address Copilot review on #307: add an afterAll that removes the per-run temp fixture dir under tmp/ (it was left behind on every run), and drop the unused `dirname` import.
…dProperty Address Copilot review on #305: the loose-set prototype-pollution guard allocated a fresh Set on every call and coerced via a template literal, which throws a raw TypeError on a Symbol instead of the intended SlothletError path. Reuse the module-level UNSAFE_PATH_SEGMENTS and coerce with String() — branchless and Symbol-safe.
🔒 Dependency Review
|
Contributor
Author
|
| File | Raw | Δ Raw | Gzipped | Δ Gzipped |
|---|---|---|---|---|
| dist/lib/builders/api-assignment.mjs | 15.5 kB | — | 3.4 kB | — |
| dist/lib/builders/api_builder.mjs | 48.8 kB | — | 9.9 kB | — |
| dist/lib/builders/builder.mjs | 2.7 kB | — | 1.2 kB | — |
| dist/lib/builders/modes-processor.mjs | 40.6 kB | — | 6.9 kB | — |
| dist/lib/errors.mjs | 4.4 kB | — | 1.7 kB | — |
| dist/lib/factories/component-base.mjs | 1.7 kB | — | 866 B | — |
| dist/lib/factories/context.mjs | 1010 B | — | 525 B | — |
| dist/lib/handlers/api-cache-manager.mjs | 3.4 kB | — | 1.4 kB | — |
| dist/lib/handlers/api-manager.mjs | 56.8 kB | +686 B (+1.2%) |
11.8 kB | +104 B |
| dist/lib/handlers/context-async.mjs | 4.0 kB | — | 1.4 kB | — |
| dist/lib/handlers/context-live.mjs | 7.0 kB | — | 2.2 kB | — |
| dist/lib/handlers/framework-internals.mjs | 1.1 kB | — | 611 B | — |
| dist/lib/handlers/hook-manager.mjs | 19.6 kB | — | 4.9 kB | — |
| dist/lib/handlers/lifecycle-token.mjs | 959 B | — | 540 B | — |
| dist/lib/handlers/lifecycle.mjs | 2.2 kB | — | 1010 B | — |
| dist/lib/handlers/materialize-manager.mjs | 1.2 kB | — | 672 B | — |
| dist/lib/handlers/metadata.mjs | 12.2 kB | — | 3.2 kB | — |
| dist/lib/handlers/module-manager.mjs | 9.3 kB | — | 3.0 kB | — |
| dist/lib/handlers/ownership.mjs | 6.3 kB | — | 2.1 kB | — |
| dist/lib/handlers/permission-manager.mjs | 15.9 kB | — | 4.0 kB | — |
| dist/lib/handlers/trusted-root.mjs | 3.1 kB | — | 1.2 kB | — |
| dist/lib/handlers/unified-wrapper.mjs | 74.8 kB | +164 B (+0.2%) | 13.3 kB | +32 B |
| dist/lib/handlers/version-manager.mjs | 14.4 kB | — | 3.7 kB | — |
| dist/lib/helpers/caller-pinning.mjs | 804 B | — | 496 B | — |
| dist/lib/helpers/class-instance-wrapper.mjs | 2.7 kB | — | 1.1 kB | — |
| dist/lib/helpers/config.mjs | 14.5 kB | — | 3.8 kB | — |
| dist/lib/helpers/eventemitter-context.mjs | 9.0 kB | — | 1.8 kB | — |
| dist/lib/helpers/eventtarget-context.mjs | 3.3 kB | — | 1.2 kB | — |
| dist/lib/helpers/generate-manifest.mjs | 10.6 kB | — | 3.3 kB | — |
| dist/lib/helpers/hint-detector.mjs | 1.3 kB | — | 756 B | — |
| dist/lib/helpers/manifest-resolver.mjs | 1004 B | — | 611 B | — |
| dist/lib/helpers/modes-utils.mjs | 1.1 kB | — | 696 B | — |
| dist/lib/helpers/module-discovery.mjs | 7.5 kB | — | 2.5 kB | — |
| dist/lib/helpers/module-manifest-validator.mjs | 8.7 kB | — | 1.9 kB | — |
| dist/lib/helpers/module-sort.mjs | 1.0 kB | — | 593 B | — |
| dist/lib/helpers/pattern-matcher.mjs | 2.6 kB | — | 1.2 kB | — |
| dist/lib/helpers/platform.mjs | 1.8 kB | — | 953 B | — |
| dist/lib/helpers/resolve-from-caller.mjs | 3.0 kB | — | 1.3 kB | — |
| dist/lib/helpers/sanitize.mjs | 7.7 kB | — | 2.3 kB | — |
| dist/lib/helpers/scheduler-context.mjs | 1.9 kB | — | 876 B | — |
| dist/lib/helpers/utilities.mjs | 1.7 kB | — | 909 B | — |
| dist/lib/i18n/languages/de-de.json | 64.4 kB | +153 B (+0.2%) | 18.4 kB | +69 B |
| dist/lib/i18n/languages/en-gb.json | 56.8 kB | +141 B (+0.2%) | 16.0 kB | +45 B |
| dist/lib/i18n/languages/en-us.json | 56.8 kB | +141 B (+0.2%) | 16.0 kB | +46 B |
| dist/lib/i18n/languages/es-es.json | 63.9 kB | +148 B (+0.2%) | 17.8 kB | +62 B |
| dist/lib/i18n/languages/es-mx.json | 64.0 kB | +148 B (+0.2%) | 17.8 kB | +61 B |
| dist/lib/i18n/languages/fr-fr.json | 64.9 kB | +150 B (+0.2%) | 17.9 kB | +63 B |
| dist/lib/i18n/languages/hi-in.json | 107.3 kB | +257 B (+0.2%) | 20.2 kB | +94 B |
| dist/lib/i18n/languages/ja-jp.json | 76.5 kB | +176 B (+0.2%) | 18.9 kB | +75 B |
| dist/lib/i18n/languages/ko-kr.json | 66.3 kB | +170 B (+0.3%) | 17.9 kB | +77 B |
| dist/lib/i18n/languages/pt-br.json | 63.2 kB | +141 B (+0.2%) | 17.6 kB | +77 B |
| dist/lib/i18n/languages/ru-ru.json | 78.0 kB | +208 B (+0.3%) | 19.0 kB | +82 B |
| dist/lib/i18n/languages/zh-cn.json | 55.7 kB | +120 B (+0.2%) | 17.5 kB | +39 B |
| dist/lib/i18n/translations.mjs | 5.0 kB | — | 1.8 kB | — |
| dist/lib/modes/eager.mjs | 2.0 kB | — | 1006 B | — |
| dist/lib/modes/lazy.mjs | 2.5 kB | — | 1.2 kB | — |
| dist/lib/processors/flatten.mjs | 9.9 kB | — | 2.4 kB | — |
| dist/lib/processors/loader.mjs | 12.3 kB | — | 4.0 kB | — |
| dist/lib/processors/type-generator.mjs | 6.7 kB | — | 2.6 kB | — |
| dist/lib/processors/typescript.mjs | 10.7 kB | — | 4.0 kB | — |
| dist/lib/runtime/runtime-asynclocalstorage.mjs | 3.0 kB | — | 1.1 kB | — |
| dist/lib/runtime/runtime-livebindings.mjs | 3.1 kB | — | 1.1 kB | — |
| dist/lib/runtime/runtime.mjs | 2.2 kB | — | 800 B | — |
| dist/lib/typegen/typegen.mjs | 2.1 kB | — | 1.0 kB | — |
| dist/slothlet.mjs | 17.9 kB | — | 5.1 kB | — |
| Total | 1.29 MB | +2.7 kB | 346.5 kB | +926 B |
📊 Generated by bundle-size. Brotli sizes also measured but omitted from the table for brevity.
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.
🚀 What's Changed
💥 Breaking Changes
No breaking changes
✨ Features
No new features
🐛 Bug Fixes
fix: don't materialize a callable leaf's built-in members as child endpoints #307
fix: refuse prototype-polluting mount-path segments in api.add() #305
📦 Dependencies
No dependency updates
🔧 Other Changes
fix: don't materialize a callable leaf's built-in members as child endpoints #307
fix: refuse prototype-polluting mount-path segments in api.add() #305
style: apply automated lint/format fixes (1a7bc5b)
👥 Contributors
Avg: 100.0% ·
f4ce594· Node lts/*