Hello community, here is the log from the commit of package nodejs8 for openSUSE:Factory checked in at 2020-02-14 16:23:19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/nodejs8 (Old) and /work/SRC/openSUSE:Factory/.nodejs8.new.26092 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "nodejs8" Fri Feb 14 16:23:19 2020 rev:31 rq:773450 version:8.17.0 Changes: -------- --- /work/SRC/openSUSE:Factory/nodejs8/nodejs8.changes 2020-01-20 22:48:56.579193446 +0100 +++ /work/SRC/openSUSE:Factory/.nodejs8.new.26092/nodejs8.changes 2020-02-14 16:23:24.427126578 +0100 @@ -1,0 +2,13 @@ +Fri Feb 7 14:54:56 UTC 2020 - Adam Majer <[email protected]> + +- CVE-2019-15604.patch: fixes a remotely triggerable assertion + on a TLS server via a crafted certificate string + (CVE-2019-15604, bsc#1163104) + +- CVE-2019-15605.patch: fixes an HTTP request smuggling vulnerability + via malformed Transfer-Encoding header (CVE-2019-15605, bsc#1163102) + +- CVE-2019-15606.patch: trim HTTP header values of optional + white space (CVE-2019-15606, bsc#1163103) + +------------------------------------------------------------------- New: ---- CVE-2019-15604.patch CVE-2019-15605.patch CVE-2019-15606.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ nodejs8.spec ++++++ --- /var/tmp/diff_new_pack.nGCB0g/_old 2020-02-14 16:23:25.075126930 +0100 +++ /var/tmp/diff_new_pack.nGCB0g/_new 2020-02-14 16:23:25.075126930 +0100 @@ -1,7 +1,7 @@ # # spec file for package nodejs8 # -# Copyright (c) 2020 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2020 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -133,6 +133,10 @@ Patch32: fix_build_with_openssl_1.1.1d.patch +Patch33: CVE-2019-15606.patch +Patch34: CVE-2019-15604.patch +Patch35: CVE-2019-15605.patch + ## Patches specific to SUSE and openSUSE # PATCH-FIX-OPENSUSE -- set correct path for dtrace if it is built Patch101: nodejs-libpath.patch @@ -345,6 +349,9 @@ %endif %patch12 -p1 %patch32 -p1 +%patch33 -p1 +%patch34 -p1 +%patch35 -p1 %patch101 -p1 %patch102 -p1 # Add check_output to configure script (not part of Python 2.6 in SLE11). @@ -390,6 +397,7 @@ # script, so we'll do it thus: export CFLAGS="%{optflags}" export CXXFLAGS="%{optflags} -Wno-class-memaccess -Wno-error=return-type" +export LDFLAGS="%{?build_ldflags}" %if 0%{?cc_exec:1} export CC=%{?cc_exec} ++++++ CVE-2019-15604.patch ++++++ ported from commit f940bee3b7da865e28093472dee9ce664f273f6d Author: Fedor Indutny <[email protected]> Date: Tue Nov 26 12:47:00 2019 -0800 crypto: fix assertion caused by unsupported ext `X509V3_EXT_print` can return value different from `1` if the X509 extension does not support printing to a buffer. Instead of failing with an unrecoverable assertion - replace the relevant value in the hashmap with a JS null value. Fixes: https://hackerone.com/reports/746733 Backport-PR-URL: https://github.com/nodejs-private/node-private/pull/193 PR-URL: https://github.com/nodejs-private/node-private/pull/175 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Beth Griggs <[email protected]> Index: node-v8.17.0/src/node_crypto.cc =================================================================== --- node-v8.17.0.orig/src/node_crypto.cc +++ node-v8.17.0/src/node_crypto.cc @@ -1818,9 +1818,11 @@ static Local<Object> X509ToObject(Enviro ext = X509_get_ext(cert, index); CHECK_NE(ext, nullptr); - if (!SafeX509ExtPrint(bio, ext)) { - rv = X509V3_EXT_print(bio, ext, 0, 0); - CHECK_EQ(rv, 1); + if (!SafeX509ExtPrint(bio, ext) && + X509V3_EXT_print(bio, ext, 0, 0) != 1) { + info->Set(context, keys[i], Null(env->isolate())).FromJust(); + (void) BIO_reset(bio); + continue; } BIO_get_mem_ptr(bio, &mem); Index: node-v8.17.0/test/parallel/test-tls-cert-ext-encoding.js =================================================================== --- /dev/null +++ node-v8.17.0/test/parallel/test-tls-cert-ext-encoding.js @@ -0,0 +1,79 @@ +'use strict'; +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +// NOTE: This certificate is hand-generated, hence it is not located in +// `test/fixtures/keys` to avoid confusion. +// +// The key property of this cert is that subjectAltName contains a string with +// a type `23` which cannot be encoded into string by `X509V3_EXT_print`. +const pem = ` +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAzrmfPz5M3wTq2/CwMeSQr/N+R1FCJ+O5n+SMleKvBqaK63eJ +kL4BnySMc+ZLKCt4UQSsPFIBK63QFq8n6/vjuTDMJiBTsvzytw8zJt1Zr2HA71N3 +VIPt6NdJ/w5lgddTYxR7XudJZJ5lk3PkG8ZgrhuenPYP80UJYVzAC2YZ9KYe3r2B +rVbut1j+8h0TwVcx2Zg5PorsC/EVxHwo4dCmIHceodikr3UVqHneRcrDBytdG6Mo +IqHhZJwBeii/EES9tpWwWbzYYh+38aGGLIF2h5UlVpr0bdBVVUg+uVX3y/Qmu2Qv +4CrAO2IPV6JER9Niwl3ktzNjOMAUQG6BCRSqRQIDAQABAoIBAAmB0+cOsG5ZRYvT +5+aDgnv1EMuq2wYGnRTTZ/vErxP5OM5XcwYrFtwAzEzQPIieZywisOEdTFx74+QH +LijWLsTnj5v5RKAorejpVArnhyZfsoXPKt/CKYDZ1ddbDCQKiRU3be0RafisqDM9 +0zHLz8pyDrtdPaKMfD/0Cgj8KxlrLTmfD4otPXds8fZpQe1hR1y12XKVp47l1siW +qFGTaUPDJpQ67xybR08x5DOqmyo4cNMOuReRWrc/qRbWint9U1882eOH09gVfpJZ +Gp6FZVPSgz10MZdLSPLhXqZkY4IxIvNltjBDqkmivd12CD+GVr0qUmTJHzTpk+kG +/CWuRQkCgYEA4EFf8SJHEl0fLDJnOQFyUPY3MalMuopUkQ5CBUe3QXjQhHXsRDfj +Ci/lyzShJkHPbMDHb/rx3lYZB0xNhwnMWKS1gCFVgOCOTZLfD0K1Anxc1hOSgVxI +y5FdO9VW7oQNlsMH/WuDHps0HhJW/00lcrmdyoUM1+fE/3yPQndhUmMCgYEA6/z6 +8Gq4PHHNql+gwunAH2cZKNdmcP4Co8MvXCZwIJsLenUuLIZQ/YBKZoM/y5X/cFAG +WFJJuUe6KFetPaDm6NgZgpOmawyUwd5czDjJ6wWgsRywiTISInfJlgWLBVMOuba7 +iBL9Xuy0hmcbj0ByoRW9l3gCiBX3yJw3I6wqXTcCgYBnjei22eRF15iIeTHvQfq+ +5iNwnEQhM7V/Uj0sYQR/iEGJmUaj7ca6somDf2cW2nblOlQeIpxD1jAyjYqTW/Pv +zwc9BqeMHqW3rqWwT1Z0smbQODOD5tB6qEKMWaSN+Y6o2qC65kWjAXpclI110PME ++i+iEDRxEsaGT8d7otLfDwKBgQCs+xBaQG/x5p2SAGzP0xYALstzc4jk1FzM+5rw +mkBgtiXQyqpg+sfNOkfPIvAVZEsMYax0+0SNKrWbMsGLRjFchmMUovQ+zccQ4NT2 +4b2op8Rlbxk8R9ahK1s5u7Bu47YMjZSjJwBQn4OobVX3SI994njJ2a9JX4j0pQWK +AX5AOwKBgAfOsr8HSHTcxSW4F9gegj+hXsRYbdA+eUkFhEGrYyRJgIlQrk/HbuZC +mKd/bQ5R/vwd1cxgV6A0APzpZtbwdhvP0RWji+WnPPovgGcfK0AHFstHnga67/uu +h2LHnKQZ1qWHn+BXWo5d7hBRwWVaK66g3GDN0blZpSz1kKcpy1Pl +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIICwjCCAaqgAwIBAgIDAQABMA0GCSqGSIb3DQEBDQUAMBUxEzARBgNVBAMWCmxv +Y2FsLmhvc3QwHhcNMTkxMjA1MDQyODMzWhcNNDQxMTI5MDQyODMzWjAVMRMwEQYD +VQQDFgpsb2NhbC5ob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +zrmfPz5M3wTq2/CwMeSQr/N+R1FCJ+O5n+SMleKvBqaK63eJkL4BnySMc+ZLKCt4 +UQSsPFIBK63QFq8n6/vjuTDMJiBTsvzytw8zJt1Zr2HA71N3VIPt6NdJ/w5lgddT +YxR7XudJZJ5lk3PkG8ZgrhuenPYP80UJYVzAC2YZ9KYe3r2BrVbut1j+8h0TwVcx +2Zg5PorsC/EVxHwo4dCmIHceodikr3UVqHneRcrDBytdG6MoIqHhZJwBeii/EES9 +tpWwWbzYYh+38aGGLIF2h5UlVpr0bdBVVUg+uVX3y/Qmu2Qv4CrAO2IPV6JER9Ni +wl3ktzNjOMAUQG6BCRSqRQIDAQABoxswGTAXBgNVHREEEDAOlwwqLmxvY2FsLmhv +c3QwDQYJKoZIhvcNAQENBQADggEBAH5ThRLDLwOGuhKsifyiq7k8gbx1FqRegO7H +SIiIYYB35v5Pk0ZPN8QBJwNQzJEjUMjCpHXNdBxknBXRaA8vkbnryMfJm37gPTwA +m6r0uEG78WgcEAe8bgf9iKtQGP/iydKXpSSpDgKoHbswIxD5qtzT+o6VNnkRTSfK +/OGwakluFSoJ/Q9rLpR8lKjA01BhetXMmHbETiY8LSkxOymMldXSzUTD1WdrVn8U +L3dobxT//R/0GraKXG02mf3gZNlb0MMTvW0pVwVy39YmcPEGh8L0hWh1rpAA/VXC +f79uOowv3lLTzQ9na5EThA0tp8d837hdYrrIHh5cfTqBDxG0Tu8= +-----END CERTIFICATE----- +`; + +const tls = require('tls'); + +const options = { + key: pem, + cert: pem, +}; + +const server = tls.createServer(options, (socket) => { + socket.end(); +}); +server.listen(0, common.mustCall(function() { + const client = tls.connect({ + port: this.address().port, + rejectUnauthorized: false + }, common.mustCall(() => { + // This should not crash process: + client.getPeerCertificate(); + + server.close(); + client.end(); + })); +})); ++++++ CVE-2019-15605.patch ++++++ ++++ 2082 lines (skipped) ++++++ CVE-2019-15606.patch ++++++ commit 2eee90e959ca4abaf53caf238d063c396f2ea17c Author: Sam Roberts <[email protected]> Date: Fri Jan 10 15:00:11 2020 -0800 http: strip trailing OWS from header values HTTP header values can have trailing OWS, but it should be stripped. It is not semantically part of the header's value, and if treated as part of the value, it can cause spurious inequality between expected and actual header values. Note that a single SPC of leading OWS is common before the field-value, and it is already handled by the HTTP parser by stripping all leading OWS. It is only the trailing OWS that must be stripped by the parser user. header-field = field-name ":" OWS field-value OWS ; https://tools.ietf.org/html/rfc7230#section-3.2 OWS = *( SP / HTAB ) ; https://tools.ietf.org/html/rfc7230#section-3.2.3 Fixes: https://hackerone.com/reports/730779 PR-URL: https://github.com/nodejs-private/node-private/pull/191 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Beth Griggs <[email protected]> diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index c2cd7a213b..420e94564e 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -74,6 +74,10 @@ const uint32_t kOnMessageComplete = 3; const uint32_t kOnExecute = 4; +inline bool IsOWS(char c) { + return c == ' ' || c == '\t'; +} + // helper class for the Parser struct StringPtr { StringPtr() { @@ -133,13 +137,22 @@ struct StringPtr { Local<String> ToString(Environment* env) const { - if (str_) + if (size_ != 0) return OneByteString(env->isolate(), str_, size_); else return String::Empty(env->isolate()); } + // Strip trailing OWS (SPC or HTAB) from string. + Local<String> ToTrimmedString(Environment* env) { + while (size_ > 0 && IsOWS(str_[size_ - 1])) { + size_--; + } + return ToString(env); + } + + const char* str_; bool on_heap_; size_t size_; @@ -669,7 +682,7 @@ class Parser : public AsyncWrap, public StreamListener { size_t j = 0; while (i < num_values_ && j < arraysize(argv) / 2) { argv[j * 2] = fields_[i].ToString(env()); - argv[j * 2 + 1] = values_[i].ToString(env()); + argv[j * 2 + 1] = values_[i].ToTrimmedString(env()); i++; j++; } diff --git a/test/parallel/test-http-header-owstext.js b/test/parallel/test-http-header-owstext.js new file mode 100644 index 0000000000..bc094137a2 --- /dev/null +++ b/test/parallel/test-http-header-owstext.js @@ -0,0 +1,49 @@ +'use strict'; +const common = require('../common'); + +// This test ensures that the http-parser strips leading and trailing OWS from +// header values. It sends the header values in chunks to force the parser to +// build the string up through multiple calls to on_header_value(). + +const assert = require('assert'); +const http = require('http'); +const net = require('net'); + +function check(hdr, snd, rcv) { + const server = http.createServer(common.mustCall((req, res) => { + assert.strictEqual(req.headers[hdr], rcv); + req.pipe(res); + })); + + server.listen(0, common.mustCall(function() { + const client = net.connect(this.address().port, start); + function start() { + client.write('GET / HTTP/1.1\r\n' + hdr + ':', drain); + } + + function drain() { + if (snd.length === 0) { + return client.write('\r\nConnection: close\r\n\r\n'); + } + client.write(snd.shift(), drain); + } + + const bufs = []; + client.on('data', function(chunk) { + bufs.push(chunk); + }); + client.on('end', common.mustCall(function() { + const head = Buffer.concat(bufs) + .toString('latin1') + .split('\r\n')[0]; + assert.strictEqual(head, 'HTTP/1.1 200 OK'); + server.close(); + })); + })); +} + +check('host', [' \t foo.com\t'], 'foo.com'); +check('host', [' \t foo\tcom\t'], 'foo\tcom'); +check('host', [' \t', ' ', ' foo.com\t', '\t '], 'foo.com'); +check('host', [' \t', ' \t'.repeat(100), '\t '], ''); +check('host', [' \t', ' - - - - ', '\t '], '- - - -');
