fix: enforce ownPropertyOnly for inherited array indices (#924)

* fix: enforce ownPropertyOnly for inherited array indices

Route array index access (including negative indices, first/last, and the
first/last filters) through a shared readArrayElement helper so that
ownPropertyOnly hides prototype-inherited array indices, closing the
GHSA-fwxr-j5w2-587m bypass. The option's scope (property/index access
only, not filter transforms or iteration) is documented on the option.

Co-authored-by: Cursor <[email protected]>

* fix(filters): invoke Array.prototype methods on unsanitized array values

Call built-ins via Array.prototype.<m>.call(...) for values that come
from scope (join, compact, concat, slice, where/reject) so an overridden
instance method on unsanitized data cannot hijack filter behavior.
Methods on freshly-created arrays are left as-is.

Co-authored-by: Cursor <[email protected]>

* fix(filters): use String.prototype.slice for the string branch of slice

Route the non-array branch through String.prototype.slice.call so the
slice filter never dispatches through a possibly-overridden instance
method, matching the Array.prototype guard.

Co-authored-by: Cursor <[email protected]>

---------

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Yang Jun
2026-07-06 20:12:09 +08:00
committed by GitHub
co-authored by Cursor
parent 8bfb6428ae
commit 552819a84b
6 changed files with 103 additions and 19 deletions
+6
View File
@@ -42,6 +42,12 @@ export function stringify (value: any): string {
return String(value)
}
export function readArrayElement (arr: any[], index: number, ownPropertyOnly: boolean) {
if (index < 0) index = arr.length + index
if (ownPropertyOnly && !hasOwnProperty.call(arr, index)) return undefined
return arr[index]
}
export function toEnumerable<T = unknown> (val: any): T[] {
val = toValue(val)
if (isArray(val)) return val