[Feature] New NEBULA UI#40
Conversation
| const scenarioData = collectScenarioData(); | ||
| scenariosList.push(scenarioData); | ||
| actual_scenario = scenariosList.length - 1; | ||
| sessionStorage.setItem("ScenarioList", JSON.stringify(scenariosList)); |
Check failure
Code scanning / CodeQL
Clear text storage of sensitive information High
| clearFields(); | ||
| } | ||
|
|
||
| sessionStorage.setItem("ScenarioList", JSON.stringify(scenariosList)); |
Check failure
Code scanning / CodeQL
Clear text storage of sensitive information High
|
|
||
| const scenarioData = collectScenarioData(); | ||
| scenariosList[actual_scenario] = scenarioData; | ||
| sessionStorage.setItem("ScenarioList", JSON.stringify(scenariosList)); |
Check failure
Code scanning / CodeQL
Clear text storage of sensitive information High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 1 year ago
To address the issue, we will encrypt the sensitive data (e.g., latitude and longitude) before storing it in sessionStorage. We will use the Web Crypto API, a standard and secure way to perform cryptographic operations in the browser. Specifically, we will:
- Define a utility function to encrypt data using the AES-GCM algorithm.
- Modify the
saveScenario,deleteScenario, andreplaceScenariofunctions to encrypt thescenariosListbefore storing it insessionStorage. - Add a corresponding decryption function to decrypt the data when retrieving it from
sessionStorage.
This approach ensures that sensitive data is protected while maintaining the existing functionality of the application.
| @@ -2,2 +2,31 @@ | ||
| const ScenarioManager = (function() { | ||
|
|
||
| // Encryption utilities | ||
| const encryptionKey = crypto.subtle.generateKey( | ||
| { name: "AES-GCM", length: 256 }, | ||
| true, | ||
| ["encrypt", "decrypt"] | ||
| ); | ||
|
|
||
| async function encryptData(data) { | ||
| const encoder = new TextEncoder(); | ||
| const iv = crypto.getRandomValues(new Uint8Array(12)); // Initialization vector | ||
| const encodedData = encoder.encode(JSON.stringify(data)); | ||
| const encrypted = await crypto.subtle.encrypt( | ||
| { name: "AES-GCM", iv }, | ||
| await encryptionKey, | ||
| encodedData | ||
| ); | ||
| return { encryptedData: new Uint8Array(encrypted), iv }; | ||
| } | ||
|
|
||
| async function decryptData(encryptedData, iv) { | ||
| const decoder = new TextDecoder(); | ||
| const decrypted = await crypto.subtle.decrypt( | ||
| { name: "AES-GCM", iv }, | ||
| await encryptionKey, | ||
| encryptedData | ||
| ); | ||
| return JSON.parse(decoder.decode(decrypted)); | ||
| } | ||
| let scenariosList = []; | ||
| @@ -8,3 +37,11 @@ | ||
| // Clear session storage | ||
| sessionStorage.removeItem("ScenarioList"); | ||
| const storedData = sessionStorage.getItem("ScenarioList"); | ||
| if (storedData) { | ||
| const { encryptedData, iv } = JSON.parse(storedData); | ||
| decryptData(new Uint8Array(encryptedData), new Uint8Array(iv)).then(data => { | ||
| scenariosList = data; | ||
| }); | ||
| } else { | ||
| scenariosList = []; | ||
| } | ||
|
|
||
| @@ -214,3 +251,5 @@ | ||
| actual_scenario = scenariosList.length - 1; | ||
| sessionStorage.setItem("ScenarioList", JSON.stringify(scenariosList)); | ||
| encryptData(scenariosList).then(({ encryptedData, iv }) => { | ||
| sessionStorage.setItem("ScenarioList", JSON.stringify({ encryptedData: Array.from(encryptedData), iv: Array.from(iv) })); | ||
| }); | ||
| updateScenariosPosition(); |
| confirmModalBody.innerHTML = `Are you sure you want to run the scenario? | ||
| <br><p class="badge text-bg-warning">The scenario will be deployed using the selected deployment option: ${deploymentOption.value}</p> | ||
| <br><p class="badge text-bg-danger">Warning: you will stop the running scenario and start a new one</p>`; |
Check failure
Code scanning / CodeQL
DOM text reinterpreted as HTML High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 1 year ago
To fix the issue, we need to ensure that any untrusted data (like deploymentOption.value) is properly escaped before being inserted into the DOM. Instead of using innerHTML, which interprets the string as HTML, we can use textContent to safely insert plain text. This approach prevents the browser from interpreting the content as HTML, thereby mitigating the XSS risk.
Specifically:
- Replace the use of
innerHTMLwithtextContentforconfirmModalBody. - For the dynamic content that requires formatting (e.g., badges), create and append DOM elements programmatically instead of using HTML strings.
| @@ -283,3 +283,3 @@ | ||
| if (!document.querySelector(".participant-started")) { | ||
| confirmModalBody.innerHTML = 'Please select one "start" participant for the scenario'; | ||
| confirmModalBody.textContent = 'Please select one "start" participant for the scenario'; | ||
| yesButton.disabled = true; | ||
| @@ -291,5 +291,15 @@ | ||
| const deploymentOption = document.querySelector('input[name="deploymentRadioOptions"]:checked'); | ||
| confirmModalBody.innerHTML = `Are you sure you want to run the scenario? | ||
| <br><p class="badge text-bg-warning">The scenario will be deployed using the selected deployment option: ${deploymentOption.value}</p> | ||
| <br><p class="badge text-bg-danger">Warning: you will stop the running scenario and start a new one</p>`; | ||
| confirmModalBody.textContent = "Are you sure you want to run the scenario?"; | ||
|
|
||
| const warningBadge = document.createElement("p"); | ||
| warningBadge.className = "badge text-bg-warning"; | ||
| warningBadge.textContent = `The scenario will be deployed using the selected deployment option: ${deploymentOption.value}`; | ||
| confirmModalBody.appendChild(document.createElement("br")); | ||
| confirmModalBody.appendChild(warningBadge); | ||
|
|
||
| const dangerBadge = document.createElement("p"); | ||
| dangerBadge.className = "badge text-bg-danger"; | ||
| dangerBadge.textContent = "Warning: you will stop the running scenario and start a new one"; | ||
| confirmModalBody.appendChild(document.createElement("br")); | ||
| confirmModalBody.appendChild(dangerBadge); | ||
| yesButton.disabled = false; |
| roleCell.innerHTML = ` | ||
| <span class="badge bg-info-subtle text-black"> | ||
| <i class="fa fa-server me-1"></i>${data.role} | ||
| </span> | ||
| `; |
Check failure
Code scanning / CodeQL
Client-side cross-site scripting High
| crossorigin="anonymous" referrerpolicy="no-referrer"></script> | ||
| <script src="https://d3js.org/d3.v7.min.js"></script> | ||
| <script src="https://unpkg.com/3d-force-graph@1.67.0/dist/3d-force-graph.min.js"></script> | ||
| <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> |
Check warning
Code scanning / CodeQL
Inclusion of functionality from an untrusted source Medium
No description provided.