Disable prototype poisoning option (#1414)

* Introduce disablePrototypePoisoningProtection option

* Updated test

* Updated docs

* Fix bundler test
This commit is contained in:
Tomas Della Vedova
2021-03-15 08:51:45 +01:00
committed by GitHub
parent 36eaed6466
commit 6a30cd9955
9 changed files with 166 additions and 31 deletions

View File

@ -421,7 +421,7 @@ class Helpers {
*/
bulk (options, reqOptions = {}) {
const client = this[kClient]
const { serialize, deserialize } = client.serializer
const { serializer } = client
if (this[kMetaHeader] !== null) {
reqOptions.headers = reqOptions.headers || {}
reqOptions.headers['x-elastic-client-meta'] = this[kMetaHeader] + ',h=bp'
@ -505,19 +505,19 @@ class Helpers {
? Object.keys(action[0])[0]
: Object.keys(action)[0]
if (operation === 'index' || operation === 'create') {
actionBody = serialize(action)
payloadBody = typeof chunk === 'string' ? chunk : serialize(chunk)
actionBody = serializer.serialize(action)
payloadBody = typeof chunk === 'string' ? chunk : serializer.serialize(chunk)
chunkBytes += Buffer.byteLength(actionBody) + Buffer.byteLength(payloadBody)
bulkBody.push(actionBody, payloadBody)
} else if (operation === 'update') {
actionBody = serialize(action[0])
actionBody = serializer.serialize(action[0])
payloadBody = typeof chunk === 'string'
? `{"doc":${chunk}}`
: serialize({ doc: chunk, ...action[1] })
: serializer.serialize({ doc: chunk, ...action[1] })
chunkBytes += Buffer.byteLength(actionBody) + Buffer.byteLength(payloadBody)
bulkBody.push(actionBody, payloadBody)
} else if (operation === 'delete') {
actionBody = serialize(action)
actionBody = serializer.serialize(action)
chunkBytes += Buffer.byteLength(actionBody)
bulkBody.push(actionBody)
} else {
@ -669,13 +669,13 @@ class Helpers {
return
}
for (let i = 0, len = bulkBody.length; i < len; i = i + 2) {
const operation = Object.keys(deserialize(bulkBody[i]))[0]
const operation = Object.keys(serializer.deserialize(bulkBody[i]))[0]
onDrop({
status: 429,
error: null,
operation: deserialize(bulkBody[i]),
operation: serializer.deserialize(bulkBody[i]),
document: operation !== 'delete'
? deserialize(bulkBody[i + 1])
? serializer.deserialize(bulkBody[i + 1])
/* istanbul ignore next */
: null,
retried: isRetrying
@ -716,9 +716,9 @@ class Helpers {
onDrop({
status: status,
error: action[operation].error,
operation: deserialize(bulkBody[indexSlice]),
operation: serializer.deserialize(bulkBody[indexSlice]),
document: operation !== 'delete'
? deserialize(bulkBody[indexSlice + 1])
? serializer.deserialize(bulkBody[indexSlice + 1])
: null,
retried: isRetrying
})

5
lib/Serializer.d.ts vendored
View File

@ -17,7 +17,12 @@
* under the License.
*/
export interface SerializerOptions {
disablePrototypePoisoningProtection: boolean | 'proto' | 'constructor'
}
export default class Serializer {
constructor (opts?: SerializerOptions)
serialize(object: any): string;
deserialize(json: string): any;
ndserialize(array: any[]): string;

View File

@ -23,8 +23,17 @@ const { stringify } = require('querystring')
const debug = require('debug')('elasticsearch')
const sjson = require('secure-json-parse')
const { SerializationError, DeserializationError } = require('./errors')
const kJsonOptions = Symbol('secure json parse options')
class Serializer {
constructor (opts = {}) {
const disable = opts.disablePrototypePoisoningProtection
this[kJsonOptions] = {
protoAction: disable === true || disable === 'proto' ? 'ignore' : 'error',
constructorAction: disable === true || disable === 'constructor' ? 'ignore' : 'error'
}
}
serialize (object) {
debug('Serializing', object)
let json
@ -40,7 +49,7 @@ class Serializer {
debug('Deserializing', json)
let object
try {
object = sjson.parse(json)
object = sjson.parse(json, this[kJsonOptions])
} catch (err) {
throw new DeserializationError(err.message, json)
}