-
Notifications
You must be signed in to change notification settings - Fork 1.6k
security: protect sensitive user credentials in RAM via XOR mask. #2942
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
cd8cb40
2263642
2427f3c
b5f042b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,27 @@ | ||||||
| /** | ||||||
| * Copyright (C) dev12124 (dev brazilian, João Guilherme da Silva Freitas Lima), | ||||||
| * License: MIT license. | ||||||
| */ | ||||||
|
|
||||||
| /** | ||||||
| * Mask key used to obfuscate sensitive Acode credentials. | ||||||
| * In JavaScript, plain text variables reside unprotected in the RAM, | ||||||
| * making them vulnerable to access or modification by malicious plugins. | ||||||
| */ | ||||||
| const MASK_KEY = 0x5A; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This fixed XOR key does not protect the cached user fields from a malicious plugin. Plugins run in the app document, so one can read the masked user from the same How this was verified: Plugin scripts execute in the app document and can read the same localStorage entry that holds user fields encoded with the fixed XOR key. |
||||||
|
|
||||||
| // Applies a XOR mask to secure sensitive strings | ||||||
| export function maskCredential(secretString) { | ||||||
| if (!secretString) return []; | ||||||
|
|
||||||
| return Array.from(secretString).map(char => char.charCodeAt(0) ^ MASK_KEY); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For a name containing an emoji or another character outside the basic Unicode range,
Suggested change
|
||||||
| } | ||||||
|
|
||||||
| // Removes the XOR mask to restore the original string | ||||||
| export function unmaskCredential(maskedArray) { | ||||||
| if (!Array.isArray(maskedArray)) return " "; | ||||||
|
|
||||||
| return maskedArray | ||||||
| .map(byte => String.fromCharCode(byte ^ MASK_KEY)) | ||||||
| .join(""); | ||||||
| } | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
/loginfails after a user has been cached, the fallback returns the stored user without decrypting its string fields. Those fields are now arrays, so the sidebar can throw when it callsname.split(" ")instead of displaying the cached user. Decrypt the parsed cache before returning it.