Skip to content

Commit 468d0d9

Browse files
committed
[cve] Migrate jquery jquery.cookie to js.cookie for CVE-2022-23395
1 parent 6457491 commit 468d0d9

File tree

10 files changed

+212
-17
lines changed

10 files changed

+212
-17
lines changed

desktop/core/src/desktop/js/apps/editor/components/resultGrid/ko.resultDownloadModal.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ class DownloadResultModal {
7272

7373
params.executable.toContext(id).then(jsonContext => {
7474
this.cookieId = 'download-' + id;
75-
$.cookie(this.cookieId, null, { expires: -1, path: '/' });
75+
// eslint-disable-next-line no-undef
76+
Cookies.set(this.cookieId, null, { expires: -1, path: '/' });
7677

7778
this.addAndSubmitDownloadForm(jsonContext, params.format);
7879

@@ -84,14 +85,16 @@ class DownloadResultModal {
8485
trackCookie() {
8586
let timesChecked = 0;
8687
this.checkDownloadInterval = window.setInterval(() => {
87-
if (!$.cookie(this.cookieId)) {
88+
// eslint-disable-next-line no-undef
89+
if (!Cookies.get(this.cookieId)) {
8890
if (timesChecked > 9) {
8991
this.$downloadProgressModal.show();
9092
}
9193
} else {
9294
window.clearInterval(this.checkDownloadInterval);
9395
try {
94-
const cookieContent = $.cookie(this.cookieId);
96+
// eslint-disable-next-line no-undef
97+
const cookieContent = Cookies.get(this.cookieId);
9598
const result = JSON.parse(
9699
cookieContent
97100
.substr(1, cookieContent.length - 2)

desktop/core/src/desktop/js/jest/jquery.setup.js

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
// limitations under the License.
1616

1717
import $ from 'jquery';
18-
import 'jquery.cookie';
1918

2019
global.$ = $;
2120
global.jQuery = $;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import $ from 'jquery';
2+
import 'jquery.cookie';
3+
import Cookies from 'js-cookie';
4+
5+
describe('Cookie Migration from jquery-cookie to js-cookie', () => {
6+
afterEach(() => {
7+
$.removeCookie('test');
8+
Cookies.remove('test');
9+
});
10+
11+
it('migrating from jqeury-cookie to js-cookie should works in getting and setting a cookie api', () => {
12+
const value = 'value';
13+
14+
$.cookie('test', value);
15+
const jqueryCookieValue = $.cookie('test');
16+
17+
Cookies.set('test', value);
18+
const jsCookieValue = Cookies.get('test');
19+
20+
expect(jqueryCookieValue).toEqual(jsCookieValue);
21+
});
22+
23+
it('migrating from jqeury-cookie to js-cookie should works in setting the options api', () => {
24+
const value = 'value';
25+
26+
$.cookie('test', value, { path: '/', expires: 10 });
27+
const jqueryCookieValue = $.cookie('test');
28+
29+
Cookies.set('test', value, { path: '/', expires: 10 });
30+
const jsCookieValue = Cookies.get('test');
31+
32+
expect(jqueryCookieValue).toEqual(jsCookieValue);
33+
});
34+
});

desktop/core/src/desktop/js/jquery/jquery.common.js

-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import $ from 'jquery';
1818
import 'jquery/jquery.migration';
1919

2020
import 'jquery-contextmenu'; // TODO: Remove, it's only used for "old" query builder
21-
import 'jquery.cookie';
2221
import 'jquery-form';
2322
import 'jquery/plugins/jquery.selectize';
2423
import 'selectize-plugin-clear';

desktop/core/src/desktop/static/desktop/js/admin-wizard-inline.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,10 @@ $(document).ready(function () {
168168
});
169169
});
170170

171-
$("#updateSkipWizard").prop('checked', $.cookie("hueLandingPage", { path: "/" }) == "home");
171+
$("#updateSkipWizard").prop('checked', Cookies.set("hueLandingPage", { path: "/" }) == "home");
172172

173173
$("#updateSkipWizard").change(function () {
174-
$.cookie("hueLandingPage", this.checked ? "home" : "wizard", {
174+
Cookies.set("hueLandingPage", this.checked ? "home" : "wizard", {
175175
path: "/",
176176
secure: window.location.protocol.indexOf('https') > -1
177177
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*!
2+
* Javascript Cookie v1.5.1
3+
* https://github.com/js-cookie/js-cookie
4+
*
5+
* Copyright 2006, 2014 Klaus Hartl
6+
* Released under the MIT license
7+
*/
8+
(function (factory) {
9+
var jQuery;
10+
if (typeof define === 'function' && define.amd) {
11+
// AMD (Register as an anonymous module)
12+
define(['jquery'], factory);
13+
} else if (typeof exports === 'object') {
14+
// Node/CommonJS
15+
try {
16+
jQuery = require('jquery');
17+
} catch(e) {}
18+
module.exports = factory(jQuery);
19+
} else {
20+
// Browser globals
21+
var _OldCookies = window.Cookies;
22+
var api = window.Cookies = factory(window.jQuery);
23+
api.noConflict = function() {
24+
window.Cookies = _OldCookies;
25+
return api;
26+
};
27+
}
28+
}(function ($) {
29+
30+
var pluses = /\+/g;
31+
32+
function encode(s) {
33+
return api.raw ? s : encodeURIComponent(s);
34+
}
35+
36+
function decode(s) {
37+
return api.raw ? s : decodeURIComponent(s);
38+
}
39+
40+
function stringifyCookieValue(value) {
41+
return encode(api.json ? JSON.stringify(value) : String(value));
42+
}
43+
44+
function parseCookieValue(s) {
45+
if (s.indexOf('"') === 0) {
46+
// This is a quoted cookie as according to RFC2068, unescape...
47+
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
48+
}
49+
50+
try {
51+
// Replace server-side written pluses with spaces.
52+
// If we can't decode the cookie, ignore it, it's unusable.
53+
// If we can't parse the cookie, ignore it, it's unusable.
54+
s = decodeURIComponent(s.replace(pluses, ' '));
55+
return api.json ? JSON.parse(s) : s;
56+
} catch(e) {}
57+
}
58+
59+
function read(s, converter) {
60+
var value = api.raw ? s : parseCookieValue(s);
61+
return isFunction(converter) ? converter(value) : value;
62+
}
63+
64+
function extend() {
65+
var key, options;
66+
var i = 0;
67+
var result = {};
68+
for (; i < arguments.length; i++) {
69+
options = arguments[ i ];
70+
for (key in options) {
71+
result[key] = options[key];
72+
}
73+
}
74+
return result;
75+
}
76+
77+
function isFunction(obj) {
78+
return Object.prototype.toString.call(obj) === '[object Function]';
79+
}
80+
81+
var api = function (key, value, options) {
82+
83+
// Write
84+
85+
if (arguments.length > 1 && !isFunction(value)) {
86+
options = extend(api.defaults, options);
87+
88+
if (typeof options.expires === 'number') {
89+
var days = options.expires, t = options.expires = new Date();
90+
t.setMilliseconds(t.getMilliseconds() + days * 864e+5);
91+
}
92+
93+
return (document.cookie = [
94+
encode(key), '=', stringifyCookieValue(value),
95+
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
96+
options.path ? '; path=' + options.path : '',
97+
options.domain ? '; domain=' + options.domain : '',
98+
options.secure ? '; secure' : ''
99+
].join(''));
100+
}
101+
102+
// Read
103+
104+
var result = key ? undefined : {},
105+
// To prevent the for loop in the first place assign an empty array
106+
// in case there are no cookies at all. Also prevents odd result when
107+
// calling "get()".
108+
cookies = document.cookie ? document.cookie.split('; ') : [],
109+
i = 0,
110+
l = cookies.length;
111+
112+
for (; i < l; i++) {
113+
var parts = cookies[i].split('='),
114+
name = decode(parts.shift()),
115+
cookie = parts.join('=');
116+
117+
if (key === name) {
118+
// If second argument (value) is a function it's a converter...
119+
result = read(cookie, value);
120+
break;
121+
}
122+
123+
// Prevent storing a cookie that we couldn't decode.
124+
if (!key && (cookie = read(cookie)) !== undefined) {
125+
result[name] = cookie;
126+
}
127+
}
128+
129+
return result;
130+
};
131+
132+
api.get = api.set = api;
133+
api.defaults = {};
134+
135+
api.remove = function (key, options) {
136+
// Must not alter options, thus extending a fresh object...
137+
api(key, '', extend(options, { expires: -1 }));
138+
return !api(key);
139+
};
140+
141+
if ( $ ) {
142+
$.cookie = api;
143+
$.removeCookie = api.remove;
144+
}
145+
146+
return api;
147+
}));

desktop/core/src/desktop/templates/common_notebook_ko_components.mako

+3-3
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ from desktop.lib.django_util import nonce_attribute
491491
window.hueAnalytics.log('notebook', 'download' + format);
492492
493493
var self = this;
494-
$.cookie('download-' + self.snippet.id(), null, { expires: -1, path: '/' })
494+
Cookies.set('download-' + self.snippet.id(), null, { expires: -1, path: '/' })
495495
self.$downloadForm.find('input[name=\'format\']').val(format);
496496
self.$downloadForm.find('input[name=\'notebook\']').val(ko.mapping.toJSON(self.notebook.getContext()));
497497
self.$downloadForm.find('input[name=\'snippet\']').val(ko.mapping.toJSON(self.snippet.getContext()));
@@ -502,15 +502,15 @@ from desktop.lib.django_util import nonce_attribute
502502
503503
var timesChecked = 0;
504504
self.checkDownloadInterval = window.setInterval(function () {
505-
if ($.cookie('download-' + self.snippet.id()) === null || typeof $.cookie('download-' + self.snippet.id()) === 'undefined') {
505+
if (Cookies.get('download-' + self.snippet.id()) === null || typeof Cookies.get('download-' + self.snippet.id()) === 'undefined') {
506506
if (timesChecked == 10) {
507507
$(self.downloadProgressModalId).modal('show');
508508
}
509509
}
510510
else {
511511
window.clearInterval(self.checkDownloadInterval);
512512
try {
513-
var cookieContent = $.cookie('download-' + self.snippet.id());
513+
var cookieContent = Cookies.get('download-' + self.snippet.id());
514514
var result = JSON.parse(cookieContent.substr(1, cookieContent.length - 2).replace(/\\"/g, '"').replace(/\\054/g, ','));
515515
self.downloadTruncated(result.truncated);
516516
self.downloadCounter(result.row_counter);

desktop/core/src/desktop/templates/hue.mako

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898

9999
% if not conf.DEV.get():
100100
<script src="${ static('desktop/js/hue.errorcatcher.js') }"></script>
101+
<script src="${ static('desktop/js/js.cookie.js') }"></script>
101102
% endif
102103
</head>
103104

package-lock.json

+16-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
"jquery-form": "4.3.0",
5454
"jquery-mousewheel": "3.1.13",
5555
"jquery-ui": "1.13.2",
56-
"jquery.cookie": "1.4.1",
5756
"knockout": "3.5.1",
5857
"knockout-sortable": "1.2.0",
5958
"knockout-switch-case": "2.1.0",
@@ -162,7 +161,9 @@
162161
"webpack": "5.94.0",
163162
"webpack-bundle-analyzer": "4.10.2",
164163
"webpack-bundle-tracker": "3.1.0",
165-
"webpack-cli": "5.1.4"
164+
"webpack-cli": "5.1.4",
165+
"jquery.cookie": "1.4.1",
166+
"js-cookie": "1.5.1"
166167
},
167168
"scripts": {
168169
"devinstall": "npm cache clean && npm install && npm prune",

0 commit comments

Comments
 (0)