From cd8cb403f3cf5864066e592decaa2c9f1283bdaf Mon Sep 17 00:00:00 2001 From: dev12124 Date: Sat, 19 Sep 2026 05:12:22 -0300 Subject: [PATCH 1/2] Added: A Sample Logic for a mask. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/lib/auth.js | 34 +++++++++++++++++++++++++++++----- src/security/security.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 src/security/security.js diff --git a/src/lib/auth.js b/src/lib/auth.js index cf4fa33c9f..e3a7893d35 100644 --- a/src/lib/auth.js +++ b/src/lib/auth.js @@ -1,4 +1,5 @@ import config from "./config"; +import { maskCredential, unmaskCredential } from "../security/security"; /** * @typedef {object} User @@ -43,6 +44,28 @@ 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; + + // 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; +} + class AuthService { #loginCallbacks = new Set(); #loginTimeout = null; @@ -111,11 +134,12 @@ class AuthService { 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 loggedInUser; } if (res.status === 401) { diff --git a/src/security/security.js b/src/security/security.js new file mode 100644 index 0000000000..7e3d29dc08 --- /dev/null +++ b/src/security/security.js @@ -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); +} + +// 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(""); +} From 2263642927f2f122a61fb8de13c46a2fccfd720b Mon Sep 17 00:00:00 2001 From: dev12124 Date: Sat, 19 Sep 2026 05:45:18 -0300 Subject: [PATCH 2/2] Fix missing object clone reference and decrypt user data on getter return --- src/lib/auth.js | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/lib/auth.js b/src/lib/auth.js index e3a7893d35..07fad9e501 100644 --- a/src/lib/auth.js +++ b/src/lib/auth.js @@ -49,7 +49,9 @@ const loginEvents = { */ function secureUserObject(user) { if (!user) return null; - + + const secured = { ...user }; + // Array with String Properties of Object const textProperties = [ "name", "role", "email", "github", "website", @@ -66,6 +68,27 @@ function secureUserObject(user) { return secured; } +/** 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; @@ -128,7 +151,7 @@ class AuthService { * @returns {Promise} */ async getLoggedInUser(forceFetch = false) { - if (loggedInUser && !forceFetch) return loggedInUser; + if (loggedInUser && !forceFetch) return getDecryptedUser(loggedInUser); try { const res = await fetch(`${config.API_BASE}/login`); @@ -139,7 +162,7 @@ class AuthService { localStorage.setItem(CACHE_USER_KEY, JSON.stringify(loggedInUser)); clearTimeout(cacheTimeout); cacheTimeout = setTimeout(() => (loggedInUser = null), 600_000); - return loggedInUser; + return getDecryptedUser(loggedInUser); } if (res.status === 401) {