Skip to content

Commit 586c421

Browse files
[Backport 8.16] Respect disablePrototypePoisoningProtection option (#2395)
Co-authored-by: Josh Mock <[email protected]>
1 parent 9947b0e commit 586c421

File tree

4 files changed

+83
-3
lines changed

4 files changed

+83
-3
lines changed

docs/basic-config.asciidoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,8 @@ const client = new Client({
252252
----
253253

254254
|`disablePrototypePoisoningProtection`
255-
|`boolean`, `'proto'`, `'constructor'` - By the default the client will protect you against prototype poisoning attacks. Read https://web.archive.org/web/20200319091159/https://hueniverse.com/square-brackets-are-the-enemy-ff5b9fd8a3e8?gi=184a27ee2a08[this article] to learn more. If needed you can disable prototype poisoning protection entirely or one of the two checks. Read the `secure-json-parse` https://github.com/fastify/secure-json-parse[documentation] to learn more. +
256-
_Default:_ `false`
255+
|`boolean`, `'proto'`, `'constructor'` - The client can protect you against prototype poisoning attacks. Read https://web.archive.org/web/20200319091159/https://hueniverse.com/square-brackets-are-the-enemy-ff5b9fd8a3e8?gi=184a27ee2a08[this article] to learn more about this security concern. If needed, you can enable prototype poisoning protection entirely (`false`) or one of the two checks (`'proto'` or `'constructor'`). For performance reasons, it is disabled by default. Read the `secure-json-parse` https://github.com/fastify/secure-json-parse[documentation] to learn more. +
256+
_Default:_ `true`
257257

258258
|`caFingerprint`
259259
|`string` - If configured, verify that the fingerprint of the CA certificate that has signed the certificate of the server matches the supplied fingerprint. Only accepts SHA256 digest fingerprints. +

docs/changelog.asciidoc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,26 @@
11
[[changelog-client]]
22
== Release notes
33

4+
[discrete]
5+
=== 8.16.0
6+
7+
[discrete]
8+
==== Features
9+
10+
[discrete]
11+
===== Support for Elasticsearch `v8.16`
12+
13+
You can find all the API changes
14+
https://www.elastic.co/guide/en/elasticsearch/reference/8.16/release-notes-8.16.0.html[here].
15+
16+
[discrete]
17+
==== Fixes
18+
19+
[discrete]
20+
===== Pass prototype poisoning options to serializer correctly
21+
22+
The client's `disablePrototypePoisoningProtection` option was set to `true` by default, but when it was set to any other value it was ignored, making it impossible to enable prototype poisoning protection without providing a custom serializer implementation.
23+
424
[discrete]
525
=== 8.15.1
626

src/client.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,21 @@ export default class Client extends API {
228228
this.diagnostic = opts[kChild].diagnostic
229229
} else {
230230
this.diagnostic = new Diagnostic()
231-
this.serializer = new options.Serializer()
231+
232+
let serializerOptions
233+
if (opts.disablePrototypePoisoningProtection != null) {
234+
if (typeof opts.disablePrototypePoisoningProtection === 'boolean') {
235+
serializerOptions = {
236+
enablePrototypePoisoningProtection: !opts.disablePrototypePoisoningProtection
237+
}
238+
} else {
239+
serializerOptions = {
240+
enablePrototypePoisoningProtection: opts.disablePrototypePoisoningProtection
241+
}
242+
}
243+
}
244+
this.serializer = new options.Serializer(serializerOptions)
245+
232246
this.connectionPool = new options.ConnectionPool({
233247
pingTimeout: options.pingTimeout,
234248
resurrectStrategy: options.resurrectStrategy,

test/unit/client.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,3 +482,49 @@ test('Ensure new client does not time out at default (30s) when client sets requ
482482
t.end()
483483
}
484484
})
485+
486+
test('Pass disablePrototypePoisoningProtection option to serializer', async t => {
487+
let client = new Client({
488+
node: 'http://localhost:9200',
489+
disablePrototypePoisoningProtection: false
490+
})
491+
t.same(client.serializer[symbols.kJsonOptions], {
492+
protoAction: 'error',
493+
constructorAction: 'error'
494+
})
495+
496+
client = new Client({
497+
node: 'http://localhost:9200',
498+
disablePrototypePoisoningProtection: true
499+
})
500+
t.same(client.serializer[symbols.kJsonOptions], {
501+
protoAction: 'ignore',
502+
constructorAction: 'ignore'
503+
})
504+
505+
client = new Client({
506+
node: 'http://localhost:9200',
507+
disablePrototypePoisoningProtection: 'proto'
508+
})
509+
t.same(client.serializer[symbols.kJsonOptions], {
510+
protoAction: 'error',
511+
constructorAction: 'ignore'
512+
})
513+
514+
client = new Client({
515+
node: 'http://localhost:9200',
516+
disablePrototypePoisoningProtection: 'constructor'
517+
})
518+
t.same(client.serializer[symbols.kJsonOptions], {
519+
protoAction: 'ignore',
520+
constructorAction: 'error'
521+
})
522+
})
523+
524+
test('disablePrototypePoisoningProtection is true by default', async t => {
525+
const client = new Client({ node: 'http://localhost:9200' })
526+
t.same(client.serializer[symbols.kJsonOptions], {
527+
protoAction: 'ignore',
528+
constructorAction: 'ignore'
529+
})
530+
})

0 commit comments

Comments
 (0)