Conversation
I´m added a Mask using 0x5A for have a mask in the Critic Variables. e.g:
I´m create a Variable using let named "secret_key" with attribute "secret_password". This Variable is in the RAM, and a Malware-Plugin installed have access this Variable and modify. And, e.g: The Variable loggedInUser have a Critic Properties ("email", "github", "website") and this Malware-Plugin access and view this Variable.
…ser data in RAM This PR introduces a security enhancement to mitigate credential scraping vulnerabilities in memory (RAM). Plain-text variables containing sensitive user info (such as emails, GitHub tokens, and websites) are vulnerable to inspection or tampering by potentially malicious third-party plugins running within the same environment. Changes implemented: - Added a security module (`security.js`) featuring simple and lightweight dynamic masking using a fixed XOR key (0x5A). - Integrated `secureUserObject` and `getDecryptedUser` inside `auth.js` to ensure data remains obfuscated while stored in RAM/localStorage, preventing crashes during UI rendering.
|
| return loggedInUser; | ||
| const rawuser = await res.json(); | ||
| loggedInUser = secureUserObject(rawuser); | ||
| localStorage.setItem(CACHE_USER_KEY, JSON.stringify(loggedInUser)); |
There was a problem hiding this comment.
Cached user remains masked After a successful login saves masked fields to the cache, a later
/login request that fails, such as while offline, returns that cache without decrypting it. Callers receive arrays instead of strings, so the sidebar can display numbers for the email or throw while generating an avatar from the name.
| if (!secretString) return []; | ||
|
|
||
| // Transforms the string into a masked array of bytes (numbers) | ||
| return Array.from(secretString).map(char => char.charCodeAt(0) ^ MASK_KEY); |
There was a problem hiding this comment.
Masking corrupts Unicode characters When a profile field contains an emoji or another supplementary Unicode character,
Array.from keeps it as one element but charCodeAt(0) records only half of it. Unmasking cannot restore the original character, so the displayed value is corrupted and the corrupted form is saved in the cache.
| return Array.from(secretString).map(char => char.charCodeAt(0) ^ MASK_KEY); | |
| return secretString.split("").map(char => char.charCodeAt(0) ^ MASK_KEY); |
| * reside in the RAM unprotected, making them vulnerable to access or modification | ||
| * by malicious installed plugins. | ||
| */ | ||
| const MASK_KEY = 0x5A; |
There was a problem hiding this comment.
Fixed key exposes cached data A malicious plugin runs as a script in the application page and can read
localStorage. It can reverse each stored number using the fixed 0x5A key in the client code, recovering the email and other masked fields. The masking therefore does not provide the intended protection against malicious plugins.
How this was verified: Plugin scripts share the page that writes the masked cache, and the stored numbers are reversed with the fixed key present in the client code.
Knowledge Base Used: Plugins and platform services
This PR introduces a security enhancement to mitigate credential scraping vulnerabilities in memory (RAM).
Plain-text variables containing sensitive user info (such as emails, GitHub tokens, and websites) are vulnerable to inspection or tampering by potentially malicious third-party plugins running within the same environment.
Changes implemented:
security.js) featuring simple and lightweight dynamic masking using a fixed XOR key (0x5A).secureUserObjectandgetDecryptedUserinsideauth.jsto ensure data remains obfuscated while stored in RAM/localStorage, preventing crashes during UI rendering.