🧹 [Code Health] Implement Secure Telemetry Fallback Mechanism - #13
hashexplaindata wants to merge 1 commit into
Conversation
- Implemented localStorage fallback for telemetry with UUID isolation. - Migrated innerHTML to textContent to prevent XSS. - Removed console error to strictly maintain client-side execution silence. - Updated UI fallback state to a deceptive error message. Co-authored-by: hashexplaindata <221828969+hashexplaindata@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly improves the robustness and security of the telemetry system by introducing a critical fallback mechanism to prevent data loss during network failures. It strengthens client-side security by preventing potential XSS vulnerabilities in error message display and enhances the integrity of behavioral science data by making the telemetry process less discoverable to participants. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request effectively implements a localStorage fallback for telemetry data and improves security by replacing innerHTML with textContent. The changes align well with the goal of creating a robust and stealthy data collection mechanism. My review includes a high-severity suggestion to add error handling for the localStorage operation to prevent potential failures and a medium-severity recommendation to abstract hardcoded values into constants for better maintainability.
| DOM.syncStatus.innerHTML = `<span style="color:#ff453a">⚠️ Sync Failed. Error: ${error.code || 'Network'}</span>`; | ||
| // Potential fallback: Save to localStorage for later recovery | ||
| // Fallback: Save to localStorage for later recovery | ||
| localStorage.setItem(`telemetry_backup_${STATE.pid}`, JSON.stringify(STATE.results)); |
There was a problem hiding this comment.
The localStorage.setItem call can throw an exception if storage is full or disabled (e.g., in private browsing mode). This would interrupt the catch block and prevent the user from seeing the final status message. To make the error handling more robust, this operation should be wrapped in its own try...catch block to ensure the UI is always updated, even if the data backup fails.
try {
localStorage.setItem(`telemetry_backup_${STATE.pid}`, JSON.stringify(STATE.results));
} catch (storageError) {
// Silently fail if localStorage is not available to ensure the UI message is shown.
}| DOM.syncStatus.style.color = "#ff453a"; | ||
| DOM.syncStatus.textContent = "Diagnostic Complete. A network timeout occurred. You may safely close this tab."; |
There was a problem hiding this comment.
The color string #ff453a and the UI message are hardcoded. To improve maintainability and avoid "magic values," consider defining these as constants at a higher scope (e.g., in the CFG object at the top of the file). This makes them easier to find, update, and ensures consistency if they are used elsewhere.
There was a problem hiding this comment.
Pull request overview
Implements a client-side fallback path when Firebase batch commit fails, and hardens the sync-failure UI update to avoid HTML injection.
Changes:
- Adds a localStorage backup write for
STATE.resultswhenexecuteBatchPayload()throws. - Replaces
innerHTMLerror rendering withtextContentand direct style updates for the sync status element.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| // Fallback: Save to localStorage for later recovery | ||
| localStorage.setItem(`telemetry_backup_${STATE.pid}`, JSON.stringify(STATE.results)); |
There was a problem hiding this comment.
This fallback persists a new telemetry_backup_${STATE.pid} entry but there’s no cleanup or indexing; repeated failures can accumulate orphaned payloads in localStorage and eventually cause quota issues, and recovery is harder because the PID isn’t surfaced when sync fails. Consider adding a bounded retention strategy (e.g., store an index/timestamp, cap number of backups) and removing the backup once a later sync succeeds.
| // Fallback: Save to localStorage for later recovery | ||
| localStorage.setItem(`telemetry_backup_${STATE.pid}`, JSON.stringify(STATE.results)); | ||
|
|
||
| DOM.syncStatus.style.color = "#ff453a"; | ||
| DOM.syncStatus.textContent = "Diagnostic Complete. A network timeout occurred. You may safely close this tab."; |
There was a problem hiding this comment.
localStorage.setItem(...) can throw (e.g., QuotaExceededError, storage disabled/private mode). Since this is inside the catch, a thrown storage error would escape and prevent the user-facing status update, defeating the fallback. Wrap the localStorage write in its own try/catch and ensure the UI message is still shown even if persistence fails (optionally showing a different message when storage is unavailable).
| // Fallback: Save to localStorage for later recovery | |
| localStorage.setItem(`telemetry_backup_${STATE.pid}`, JSON.stringify(STATE.results)); | |
| DOM.syncStatus.style.color = "#ff453a"; | |
| DOM.syncStatus.textContent = "Diagnostic Complete. A network timeout occurred. You may safely close this tab."; | |
| // Fallback: Attempt to save to localStorage for later recovery | |
| let message = "Diagnostic Complete. A network timeout occurred. You may safely close this tab."; | |
| try { | |
| localStorage.setItem(`telemetry_backup_${STATE.pid}`, JSON.stringify(STATE.results)); | |
| } catch (storageError) { | |
| console.warn("Unable to persist telemetry backup to localStorage:", storageError); | |
| message = "Diagnostic Complete. A network timeout occurred and local backup could not be saved. You may safely close this tab."; | |
| } | |
| DOM.syncStatus.style.color = "#ff453a"; | |
| DOM.syncStatus.textContent = message; |
|
Closing: Fixes have already been incorporated directly into the master branch. |
Understood. Acknowledging that this work is now obsolete and stopping work on this task. |
🎯 What: The code health issue addressed
Implemented the missing localStorage fallback inside
executeBatchPayload's catch block. Secured the DOM injection by switching frominnerHTMLtotextContentand applying styling directly via the style object. Purgedconsole.errorto maintain client-side secrecy. Added the specific deception UI text.💡 Why: How this improves maintainability
Ensures edge-case network drops do not lose data, while maintaining strict isolation per participant via UUID keys (
telemetry_backup_${STATE.pid}). Refactoring the DOM injection prevents XSS vulnerabilities, and removing the console logs keeps the participant from discovering the script is a telemetry engine, which would corrupt the behavioral science data.✅ Verification: How you confirmed the change is safe
Wrote a Playwright testing script that mocks a Firebase commit failure, injects test inputs, and clicks the final submit button. The script verified that the correct UI message is displayed (as seen in the generated screenshot) and evaluated
localStorageto confirm that the keytelemetry_backup_${STATE.pid}properly held the payload data.✨ Result: The improvement achieved
A secure, stealthy, and functional data recovery path has been implemented without disrupting the experimental facade.
PR created automatically by Jules for task 10859125652482829892 started by @hashexplaindata