Skip to content

Commit e6047f6

Browse files
committed
CodeQL - Fix Remote property injection
1 parent 622785e commit e6047f6

File tree

1 file changed

+58
-66
lines changed

1 file changed

+58
-66
lines changed

assets/webconfig/js/wizards/LedDevice_philipshue.js

Lines changed: 58 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import { ledDeviceWizardUtils as utils } from './LedDevice_utils.js';
66

77
const philipshueWizard = (() => {
88

9-
// External properties, 2-dimensional arry of [ledType][key]
10-
let devicesProperties = {};
9+
// External properties, 2-dimensional map of [ledType][key]
10+
const devicesProperties = new Map();
1111

1212
let hueIPs = [];
1313
let hueIPsinc = 0;
@@ -20,11 +20,6 @@ const philipshueWizard = (() => {
2020
let isAPIv2Ready = true;
2121
let isEntertainmentReady = true;
2222

23-
function isSafeKey(key) {
24-
const unsafeKeys = ['__proto__', 'prototype', 'constructor'];
25-
return typeof key === 'string' && !unsafeKeys.includes(key);
26-
}
27-
2823
function checkHueBridge(cb, hueUser) {
2924
const usr = (typeof hueUser != "undefined") ? hueUser : 'config';
3025
if (usr === 'config') {
@@ -248,12 +243,12 @@ const philipshueWizard = (() => {
248243
return layoutObjects;
249244
}
250245

251-
function updateBridgeDetails(properties) {
252-
const ledDeviceProperties = properties.config;
246+
function updateBridgeDetails(ledType, key, username) {
247+
const ledDeviceProperties = getLedDeviceProperty(ledType, key, username);
253248

254249
if (!jQuery.isEmptyObject(ledDeviceProperties)) {
255-
isEntertainmentReady = properties.isEntertainmentReady;
256-
isAPIv2Ready = properties.isAPIv2Ready;
250+
isEntertainmentReady = ledDeviceProperties.isEntertainmentReady;
251+
isAPIv2Ready = ledDeviceProperties.isAPIv2Ready;
257252

258253
if (ledDeviceProperties.name && ledDeviceProperties.bridgeid && ledDeviceProperties.modelid) {
259254
$('#wiz_hue_discovered').html(
@@ -345,6 +340,27 @@ const philipshueWizard = (() => {
345340
}
346341
}
347342

343+
function getOrCreate(map, key, createValue) {
344+
if (!map.has(key)) {
345+
map.set(key, createValue());
346+
}
347+
return map.get(key);
348+
}
349+
350+
function getLedDeviceProperty(ledType, key, username) {
351+
const ledTypeMap = devicesProperties.get(ledType);
352+
if (!ledTypeMap) return undefined;
353+
const keyMap = ledTypeMap.get(key);
354+
if (!keyMap) return undefined;
355+
return keyMap.get(username);
356+
}
357+
358+
function setLedDeviceProperty(ledType, key, username, ledDeviceProperties) {
359+
const ledTypeMap = getOrCreate(devicesProperties, ledType, () => new Map());
360+
const keyMap = getOrCreate(ledTypeMap, key, () => new Map());
361+
keyMap.set(username, ledDeviceProperties);
362+
}
363+
348364
async function getProperties(cb, hostAddress, port, username, resourceFilter) {
349365
let params = { host: hostAddress, username: username, filter: resourceFilter };
350366
if (port !== 'undefined') {
@@ -354,35 +370,25 @@ const philipshueWizard = (() => {
354370
const ledType = 'philipshue';
355371
const key = hostAddress;
356372

357-
if (!isSafeKey(key) || !isSafeKey(username)) {
358-
cb(false, username);
359-
return;
360-
}
361-
362-
//Create ledType cache entry
363-
if (!devicesProperties[ledType]) {
364-
devicesProperties[ledType] = {};
365-
}
366-
367-
// Use device's properties, if properties in chache
368-
if (devicesProperties[ledType][key] && devicesProperties[ledType][key][username]) {
369-
updateBridgeDetails(devicesProperties[ledType][key]);
373+
const cachedLedProperties = getLedDeviceProperty(ledType, key, username);
374+
// Use device's properties, if properties in cache
375+
if (cachedLedProperties) {
376+
updateBridgeDetails(ledType, key, username);
370377
cb(true, username);
371378
} else {
372379
const res = await requestLedDeviceProperties(ledType, params);
373380
if (res && !res.error) {
374-
const ledDeviceProperties = res.info.properties;
381+
let ledDeviceProperties = res.info.properties;
375382
if (!jQuery.isEmptyObject(ledDeviceProperties)) {
376383

377-
devicesProperties[ledType][key] = {};
378-
devicesProperties[ledType][key][username] = ledDeviceProperties;
379-
380384
isAPIv2Ready = res.info.isAPIv2Ready;
381-
devicesProperties[ledType][key].isAPIv2Ready = isAPIv2Ready;
382385
isEntertainmentReady = res.info.isEntertainmentReady;
383-
devicesProperties[ledType][key].isEntertainmentReady = isEntertainmentReady;
384386

385-
updateBridgeDetails(devicesProperties[ledType][key]);
387+
ledDeviceProperties.isAPIv2Ready = isAPIv2Ready
388+
ledDeviceProperties.isEntertainmentReady = isEntertainmentReady;
389+
setLedDeviceProperty(ledType, key, username, ledDeviceProperties);
390+
391+
updateBridgeDetails(ledType, key, username);
386392
if (username === "config") {
387393
cb(true);
388394
} else {
@@ -701,34 +707,23 @@ const philipshueWizard = (() => {
701707
}
702708

703709
function get_hue_groups(username) {
704-
const host = hueIPs[hueIPsinc].host;
705-
706-
if (devicesProperties['philipshue'][host] && devicesProperties['philipshue'][host][username]) {
707-
const ledProperties = devicesProperties['philipshue'][host][username];
708-
709-
if (isAPIv2Ready) {
710-
if (!jQuery.isEmptyObject(ledProperties.data)) {
711-
if (Object.keys(ledProperties.data).length > 0) {
712-
hueEntertainmentConfigs = ledProperties.data.filter(config => {
713-
return config.type === "entertainment_configuration";
714-
});
715-
hueEntertainmentServices = ledProperties.data.filter(config => {
716-
return (config.type === "entertainment" && config.renderer === true);
717-
});
718-
}
719-
}
720-
} else if (!jQuery.isEmptyObject(ledProperties.groups)) {
721-
hueEntertainmentConfigs = [];
722-
let hueGroups = ledProperties.groups;
723-
for (const groupid in hueGroups) {
724-
if (hueGroups[groupid].type == 'Entertainment') {
725-
hueGroups[groupid].id = groupid;
726-
hueEntertainmentConfigs.push(hueGroups[groupid]);
727-
}
710+
const host = hueIPs[hueIPsinc]?.host;
711+
const ledProperties = getLedDeviceProperty('philipshue', host, username);
712+
if (ledProperties) {
713+
if (isAPIv2Ready && Array.isArray(ledProperties?.data) && ledProperties.data.length > 0) {
714+
hueEntertainmentConfigs = ledProperties.data.filter(config => config.type === "entertainment_configuration");
715+
hueEntertainmentServices = ledProperties.data.filter(config => config.type === "entertainment" && config.renderer === true);
716+
} else if (ledProperties?.groups && Object.keys(ledProperties.groups).length > 0) {
717+
hueEntertainmentConfigs = [];
718+
const hueGroups = ledProperties.groups;
719+
for (const [groupid, group] of Object.entries(hueGroups)) {
720+
if (group.type === 'Entertainment') {
721+
hueEntertainmentConfigs.push({ ...group, id: groupid });
728722
}
729723
}
724+
}
730725

731-
if (Object.keys(hueEntertainmentConfigs).length > 0) {
726+
if (hueEntertainmentConfigs?.length > 0) {
732727

733728
$('.lidsb').html("");
734729
$('#wh_topcontainer').toggle(false);
@@ -783,18 +778,14 @@ const philipshueWizard = (() => {
783778
function get_hue_lights(username) {
784779
const host = hueIPs[hueIPsinc].host;
785780

786-
if (devicesProperties['philipshue'][host] && devicesProperties['philipshue'][host][username]) {
787-
const ledProperties = devicesProperties['philipshue'][host][username];
788-
781+
const ledProperties = getLedDeviceProperty('philipshue', host, username);
782+
if (ledProperties) {
789783
if (isAPIv2Ready) {
790-
if (!jQuery.isEmptyObject(ledProperties.data)) {
791-
if (Object.keys(ledProperties.data).length > 0) {
792-
hueLights = ledProperties.data.filter(config => {
793-
return config.type === "light";
794-
});
795-
}
784+
const data = ledProperties?.data;
785+
if (Array.isArray(data) && data.length > 0) {
786+
hueLights = data.filter(config => config.type === "light");
796787
}
797-
} else if (!jQuery.isEmptyObject(ledProperties.lights)) {
788+
} else if (Array.isArray(ledProperties?.lights) && ledProperties.lights.length > 0) {
798789
hueLights = ledProperties.lights;
799790
}
800791

@@ -810,6 +801,7 @@ const philipshueWizard = (() => {
810801
lightOptions.unshift("entertainment");
811802
} else {
812803
lightOptions.unshift("disabled");
804+
groupLights = [];
813805
if (isAPIv2Ready) {
814806
for (const light in hueLights) {
815807
groupLights.push(hueLights[light].id);

0 commit comments

Comments
 (0)