Releases: badrap/valita
Releases · badrap/valita
v0.1.7
v0.1.6
v0.1.5
v0.1.4
- Rewrite parts of the internal bookkeeping for
v.object(...)
, hopefully clarifying it a bit. For details take a look at the relevant code.
v0.1.3
This release modifies how object()
and record()
handle input that contains a property called __proto__.
As it happens, __proto__ is a bit special in JavaScript, as it allows the [[Prototype]] of an object to be mutated:
let obj = {}
obj.__proto__ = { a: 1 }
obj.a === 1 // true
Interestingly, JSON.parse doesn't set the prototype based on __proto__:
let input = JSON.parse('{ "__proto__": { "a": 1 } }')
input.a === 1 // false
input.__proto__.a === 1 // true
// cloning with e.g. Object.assign sets the prototype, though
Object.assign({}, input).a === 1 // true
JSON.parse is often used to parse input in HTTP servers. So, as Valita was built for validating & parsing arbitrary input data, it may encounter data that contains the __proto__
property. Some weird effects could be observed when Valita versions v0.1.2 and earlier encountered such input and needed to clone the input object:
import * as v from "@badrap/valita"
let t = v.object({ a: v.string().optional() }).rest(v.unknown().map((x) => x))
let o = t.parse(JSON.parse('{ "__proto__": { "a": 1 } }'))
// __proto__ is defined in the output...
o.__proto__.a === 1 // true
// ...but o.a shouldn't be, yet it is
o.a === 1 // true
This is now mitigated in Valita v0.1.3:
import * as v from "@badrap/valita"
let t = v.object({ a: v.string().optional() }).rest(v.unknown().map((x) => x))
let o = t.parse(JSON.parse('{ "__proto__": { "a": 1 } }'))
// __proto__ is still defined in the output...
o.__proto__.a === 1 // true
// ...and o.a isn't
o.a === undefined // true
Notes
- An alternative approach to deal with __proto__ properties would have been to remove them from the output. However, we don't think Valita is not the right place to make such an decision. There are good options for sanitizing your input data, for example using Fastify's secure-json-parse instead of plain JSON.parse.
- The special behavior of __proto__ can be disabled in Node.js via the
--disable-proto=delete
option. Deno has disabled this behavior altogether by default. - These changes make also Valita more compatible with running Node.js with
--disable-proto=throw
, which is a good step for catching sources of __proto__ shenanigans. - Further reading about prototype pollution / poisoning:
v0.1.2
- Publish to https://deno.land/x/valita