-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Added: A Sample Logic for a mask. #2913
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
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 |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| import config from "./config"; | ||
| import { maskCredential, unmaskCredential } from "../security/security"; | ||
|
|
||
| /** | ||
| * @typedef {object} User | ||
|
|
@@ -43,6 +44,51 @@ const loginEvents = { | |
| }, | ||
| }; | ||
|
|
||
| /** Function for get the object of user under the Server, | ||
| * clone the structure and mask in the Strings. | ||
| */ | ||
| function secureUserObject(user) { | ||
| if (!user) return null; | ||
|
|
||
| const secured = { ...user }; | ||
|
|
||
| // Array with String Properties of Object | ||
| const textProperties = [ | ||
| "name", "role", "email", "github", "website", | ||
| "avatar_url", "pro_purchased_at", "created_at", "updated_at" | ||
| ]; | ||
|
|
||
| // Apply the Mask | ||
| textProperties.forEach(prop => { | ||
| if (typeof secured[prop] === "string") { | ||
| secured[prop] = maskCredential(secured[prop]); | ||
| } | ||
| }); | ||
|
|
||
| return secured; | ||
|
Comment on lines
+63
to
+68
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.
|
||
| } | ||
|
|
||
| /** Function to unmask the user object properties | ||
| * so the interface can read them safely without crashing. | ||
| */ | ||
| export function getDecryptedUser(user) { | ||
| if (!user) return null; | ||
| const decrypted = { ...user }; | ||
|
|
||
| const textProperties = [ | ||
| "name", "role", "email", "github", "website", | ||
| "avatar_url", "pro_purchased_at", "created_at", "updated_at" | ||
| ]; | ||
|
|
||
| textProperties.forEach(prop => { | ||
| if (Array.isArray(decrypted[prop])) { | ||
| decrypted[prop] = unmaskCredential(decrypted[prop]); | ||
| } | ||
| }); | ||
|
|
||
| return decrypted; | ||
| } | ||
|
|
||
| class AuthService { | ||
| #loginCallbacks = new Set(); | ||
| #loginTimeout = null; | ||
|
|
@@ -105,17 +151,18 @@ class AuthService { | |
| * @returns {Promise<User>} | ||
| */ | ||
| async getLoggedInUser(forceFetch = false) { | ||
| if (loggedInUser && !forceFetch) return loggedInUser; | ||
| if (loggedInUser && !forceFetch) return getDecryptedUser(loggedInUser); | ||
|
|
||
| try { | ||
| const res = await fetch(`${config.API_BASE}/login`); | ||
|
|
||
| if (res.ok) { | ||
| loggedInUser = await res.json(); | ||
| localStorage.setItem(CACHE_USER_KEY, JSON.stringify(loggedInUser)); | ||
| clearTimeout(cacheTimeout); | ||
| cacheTimeout = setTimeout(() => (loggedInUser = null), 600_000); | ||
| return loggedInUser; | ||
| const rawuser = await res.json(); | ||
| loggedInUser = secureUserObject(rawuser); | ||
| localStorage.setItem(CACHE_USER_KEY, JSON.stringify(loggedInUser)); | ||
| clearTimeout(cacheTimeout); | ||
| cacheTimeout = setTimeout(() => (loggedInUser = null), 600_000); | ||
| return getDecryptedUser(loggedInUser); | ||
| } | ||
|
|
||
| if (res.status === 401) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| /** | ||
| * Copyright (C) dev12124 (dev brazilian, João Guilherme da Silva Freitas Lima), | ||
| * License: MIT license. | ||
| */ | ||
|
|
||
| /** Variable for mask the Sensible Credentials of Acode, | ||
| * in JavaScript: Create a Variable (e.g: let key = "secret password"), | ||
| * this Variable is in the RAM (Random Access Memory) and a Malware-Plugin installed | ||
| * have access and modify the Variable. */ | ||
| const MASK_KEY = 0x5A; | ||
|
|
||
| // The function to he apply a Mask | ||
| export function maskCredential(secretString) { | ||
| if (!secretString) return []; | ||
|
|
||
| // Transforms the String in a Numbers Array (bytes) maskareds | ||
| return Array.from(secretString).map(char => char.charCodeAt(0) ^ MASK_KEY); | ||
|
Comment on lines
+10
to
+17
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. The fixed XOR constant does not protect these values from the malicious-plugin threat described by this change. Plugins execute as scripts in the application's JavaScript context, so they can reverse the transformation themselves, especially because the inverse operation is exported alongside it. This adds a new credential representation and integration burden without providing confidentiality or integrity; protecting this data requires an isolation or access-control boundary rather than an in-process reversible mask. Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! |
||
| } | ||
|
|
||
| // The Function to remove the Mask | ||
| export function unmaskCredential(maskedArray) { | ||
| if (!Array.isArray(maskedArray)) return " "; | ||
|
|
||
| // Remove the Mask | ||
| 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.
This masking changes string fields such as
name,email,github, andavatar_urlinto number arrays, but no caller converts them back before use. Once the precedingsecurederror is corrected, existing consumers will receive arrays; for example, the sidebar eventually calls.split(" ")onuser.name, causing profile rendering to fail, while avatar and profile URLs become invalid.