Skip to content

Potential fix for code scanning alert no. 11: Clear text storage of sensitive information - #48

Merged
Dargon789 merged 5 commits into
mainfrom
alert-autofix-11
Oct 28, 2025
Merged

Potential fix for code scanning alert no. 11: Clear text storage of sensitive information#48
Dargon789 merged 5 commits into
mainfrom
alert-autofix-11

Conversation

@Dargon789

@Dargon789 Dargon789 commented Oct 28, 2025

Copy link
Copy Markdown
Owner

Potential fix for https://github.com/Dargon789/aa-sdk/security/code-scanning/11

To fix the vulnerability, we should ensure that any sensitive session data written to localStorage is encrypted before storage, and decrypted when read back. The best way to do this is to use a strong symmetric encryption algorithm from a well-known library, such as AES from Node.js's built-in crypto module (also available via browser-compatible polyfills when needed). We will introduce a simple encrypt and decrypt utility, use it to wrap the session when serializing/deserializing in setTemporarySession and getTemporarySession. The encryption key should be provided via configuration (never hard-coded) and must be kept securely (outside localStorage). For simplicity, we'll define a placeholder for obtaining the key (this could be derived from user authentication context or other secure mechanism).

Changes required:

  • Add an import of a Crypto library for encryption/decryption (Node's built-in crypto in Node environments; for browser, use the Web Crypto API, here we'll show the Node/Polyfill import for universality).
  • Define encrypt and decrypt helpers.
  • Update setTemporarySession to store the encrypted session object string.
  • Update getTemporarySession to read, decrypt, parse, and return the session object.
  • (Optionally) introduce configuration for encryption key origin.

All changes will be made in account-kit/signer/src/session/manager.ts.

Suggested fixes powered by Copilot Autofix. Review carefully before merging.

Summary by Sourcery

Secure temporary session storage by encrypting data in localStorage with AES using a configurable key

New Features:

  • Encrypt temporary session data before writing to localStorage and decrypt it upon retrieval

Enhancements:

  • Introduce encryptSession and decryptSession helpers and require a configurable SESSION_ENCRYPTION_KEY

Build:

  • Add crypto-js dependency for encryption functionality

…ensitive information

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
@sourcery-ai

sourcery-ai Bot commented Oct 28, 2025

Copy link
Copy Markdown

Reviewer's Guide

This PR secures temporary session storage by introducing AES-based encryption and decryption utilities with PBKDF2 key derivation, wiring them into the session manager methods, and configuring the encryption key via environment variables.

Sequence diagram for storing an encrypted temporary session

sequenceDiagram
  participant SessionManager
  participant CryptoJS
  participant LocalStorage
  SessionManager->>encryptSession: encryptSession(session, key)
  encryptSession->>CryptoJS: AES.encrypt(JSON.stringify(session), derivedKey)
  encryptSession-->>SessionManager: encryptedData
  SessionManager->>LocalStorage: setItem(key, encryptedData)
Loading

Sequence diagram for retrieving and decrypting a temporary session

sequenceDiagram
  participant SessionManager
  participant LocalStorage
  participant decryptSession
  participant CryptoJS
  SessionManager->>LocalStorage: getItem(key)
  LocalStorage-->>SessionManager: encryptedData
  SessionManager->>decryptSession: decryptSession(encryptedData, key)
  decryptSession->>CryptoJS: AES.decrypt(encryptedData, derivedKey)
  decryptSession-->>SessionManager: sessionObject
Loading

Entity relationship diagram for encrypted session storage format

erDiagram
  SESSION {
    string salt
    string ciphertext
  }
  SESSION ||--o{ LOCAL_STORAGE : stores
  LOCAL_STORAGE {
    string key
    string value
  }
Loading

Class diagram for updated SessionManager and encryption utilities

classDiagram
  class SessionManager {
    +setTemporarySession(session: TemporarySession)
    +getTemporarySession(): TemporarySession | null
    +on<E>(event: E, handler: function)
    sessionKey: string
    storage: Storage
  }
  class encryptSession {
    +encryptSession(sessionObj: object, keyParam?: string): string
  }
  class decryptSession {
    +decryptSession(data: string, keyParam?: string): any | null
  }
  SessionManager --> encryptSession : uses
  SessionManager --> decryptSession : uses
Loading

File-Level Changes

Change Details Files
Configure session encryption key
  • Define SESSION_ENCRYPTION_KEY constant from environment
  • Validate presence of encryption key in helpers and throw errors if missing
account-kit/signer/src/session/manager.ts
Implement encryptSession and decryptSession helpers
  • Generate random salt and derive key with PBKDF2
  • Encrypt session JSON to ciphertext with salt prefix
  • Parse salt and ciphertext to decrypt and JSON-parse session
account-kit/signer/src/session/manager.ts
Encrypt session data on write
  • Call encryptSession instead of JSON.stringify in setTemporarySession
  • Update comment to reflect encryption step
account-kit/signer/src/session/manager.ts
Decrypt session data on read
  • Retrieve raw cipher text and handle missing value
  • Invoke decryptSession and return parsed session object
account-kit/signer/src/session/manager.ts
Add crypto-js dependency
  • Include crypto-js in dependencies for encryption support
account-kit/signer/package.json

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@snyk-io

snyk-io Bot commented Oct 28, 2025

Copy link
Copy Markdown

⚠️ Snyk checks are incomplete.

Status Scanner Critical High Medium Low Total (0)
⚠️ Open Source Security 0 0 0 0 See details

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@github-actions

github-actions Bot commented Oct 28, 2025

Copy link
Copy Markdown

🌿 Documentation Preview

Name Status Preview Updated (UTC)
Alchemy Docs ❌ Failed Oct 28, 2025, 9:33 AM

@github-actions
github-actions Bot had a problem deploying to docs-preview October 28, 2025 09:19 Failure
Repository owner deleted a comment from vercel Bot Oct 28, 2025
Comment thread account-kit/signer/src/session/manager.ts Fixed
…th insufficient computational effort

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
@github-actions
github-actions Bot had a problem deploying to docs-preview October 28, 2025 09:21 Failure
const salt = CryptoJS.lib.WordArray.random(16);
// Derive a key from the password using PBKDF2 with sufficient iterations
const key = PBKDF2(SESSION_ENCRYPTION_KEY, salt, { keySize: 256 / 32, iterations: 100_000 });
const encrypted = CryptoJS.AES.encrypt(plaintext, key).toString();

Check failure

Code scanning / CodeQL

Use of password hash with insufficient computational effort High

Password from
an access to oauthOrgId
is hashed insecurely.
Password from
a call to oauthWithPopup
is hashed insecurely.
Password from
an access to oauthOrgId
is hashed insecurely.

Copilot Autofix

AI 10 months ago

To fix this issue:

  • Replace the hardcoded encryption key and PBKDF2 with a secure password-based key derivation that uses a high-entropy secret or per-user unique key for derivation. Ideally, the key should come from secure configuration, not be hardcoded in source.
  • If storing passwords, switch to a more secure password hashing scheme like bcrypt, scrypt, or argon2. However, for encryption of session objects, the critical part is the derivation and secrecy of the key.
  • You should change the SESSION_ENCRYPTION_KEY so it's not hardcoded, and adjust encryptSession and decryptSession so they accept a key argument from outside—provided per session or loaded from a secure environment variable.
  • In case you need to hash passwords (not just encrypt data), switch to using bcrypt with a proper salt and rounds.
  • In account-kit/signer/src/session/manager.ts, update the key derivation so it uses a non-hardcoded key. For demonstration, retrieve the key from an environment variable (if possible), or make it injectable.
  • If you have access, you might use bcryptjs for portable bcrypt hashing (if you must do password hashing).
  • Add a check that throws an error if the session encryption key is unset.
  • Clearly document that the key for session encryption must be set securely.

Suggested changeset 1
account-kit/signer/src/session/manager.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/account-kit/signer/src/session/manager.ts b/account-kit/signer/src/session/manager.ts
--- a/account-kit/signer/src/session/manager.ts
+++ b/account-kit/signer/src/session/manager.ts
@@ -23,26 +23,35 @@
 
 // Encryption key for local session storage.
 // In production: obtain this from secure config, NOT hardcoded!
-const SESSION_ENCRYPTION_KEY = "__REPLACE_ME_WITH_SECURE_KEY_OR_DERIVATION__";
+// IMPORTANT: Set this key securely through environment/config, not hardcoded.
+const SESSION_ENCRYPTION_KEY = process.env.SESSION_ENCRYPTION_KEY;
 
-function encryptSession(sessionObj: object) {
+function encryptSession(sessionObj: object, keyParam?: string) {
+  if (!keyParam && !SESSION_ENCRYPTION_KEY) {
+    throw new Error("SESSION_ENCRYPTION_KEY must be set!");
+  }
+  const keyInput = keyParam ?? SESSION_ENCRYPTION_KEY;
   // Use a random salt for each session
   const plaintext = JSON.stringify(sessionObj);
   const salt = CryptoJS.lib.WordArray.random(16);
   // Derive a key from the password using PBKDF2 with sufficient iterations
-  const key = PBKDF2(SESSION_ENCRYPTION_KEY, salt, { keySize: 256 / 32, iterations: 100_000 });
+  const key = PBKDF2(keyInput, salt, { keySize: 256 / 32, iterations: 200_000 });
   const encrypted = CryptoJS.AES.encrypt(plaintext, key).toString();
   // Store salt (hex) and ciphertext together as "salt:ciphertext"
   return salt.toString(encHex) + ':' + encrypted;
 }
 
-function decryptSession(data: string): any | null {
+function decryptSession(data: string, keyParam?: string): any | null {
   try {
+    if (!keyParam && !SESSION_ENCRYPTION_KEY) {
+      throw new Error("SESSION_ENCRYPTION_KEY must be set!");
+    }
+    const keyInput = keyParam ?? SESSION_ENCRYPTION_KEY;
     // Expect format "salt:ciphertext"
     const [saltHex, encrypted] = data.split(":");
     if (!saltHex || !encrypted) throw new Error("Invalid encrypted session format");
     const salt = CryptoJS.enc.Hex.parse(saltHex);
-    const key = PBKDF2(SESSION_ENCRYPTION_KEY, salt, { keySize: 256 / 32, iterations: 100_000 });
+    const key = PBKDF2(keyInput, salt, { keySize: 256 / 32, iterations: 200_000 });
     const bytes = CryptoJS.AES.decrypt(encrypted, key);
     const decrypted = bytes.toString(CryptoJS.enc.Utf8);
     return JSON.parse(decrypted);
@@ -191,7 +185,7 @@
 
   public setTemporarySession = (session: TemporarySession) => {
     // Encrypt session before storage in localStorage for security
-    const encrypted = encryptSession(session);
+    const encrypted = encryptSession(session, SESSION_ENCRYPTION_KEY);
     localStorage.setItem(
       `${this.sessionKey}:temporary`,
       encrypted,
@@ -206,7 +200,7 @@
       return null;
     }
 
-    return decryptSession(cipherText);
+    return decryptSession(cipherText, SESSION_ENCRYPTION_KEY);
   };
 
   on = <E extends keyof SessionManagerEvents>(
EOF
@@ -23,26 +23,35 @@

// Encryption key for local session storage.
// In production: obtain this from secure config, NOT hardcoded!
const SESSION_ENCRYPTION_KEY = "__REPLACE_ME_WITH_SECURE_KEY_OR_DERIVATION__";
// IMPORTANT: Set this key securely through environment/config, not hardcoded.
const SESSION_ENCRYPTION_KEY = process.env.SESSION_ENCRYPTION_KEY;

function encryptSession(sessionObj: object) {
function encryptSession(sessionObj: object, keyParam?: string) {
if (!keyParam && !SESSION_ENCRYPTION_KEY) {
throw new Error("SESSION_ENCRYPTION_KEY must be set!");
}
const keyInput = keyParam ?? SESSION_ENCRYPTION_KEY;
// Use a random salt for each session
const plaintext = JSON.stringify(sessionObj);
const salt = CryptoJS.lib.WordArray.random(16);
// Derive a key from the password using PBKDF2 with sufficient iterations
const key = PBKDF2(SESSION_ENCRYPTION_KEY, salt, { keySize: 256 / 32, iterations: 100_000 });
const key = PBKDF2(keyInput, salt, { keySize: 256 / 32, iterations: 200_000 });
const encrypted = CryptoJS.AES.encrypt(plaintext, key).toString();
// Store salt (hex) and ciphertext together as "salt:ciphertext"
return salt.toString(encHex) + ':' + encrypted;
}

function decryptSession(data: string): any | null {
function decryptSession(data: string, keyParam?: string): any | null {
try {
if (!keyParam && !SESSION_ENCRYPTION_KEY) {
throw new Error("SESSION_ENCRYPTION_KEY must be set!");
}
const keyInput = keyParam ?? SESSION_ENCRYPTION_KEY;
// Expect format "salt:ciphertext"
const [saltHex, encrypted] = data.split(":");
if (!saltHex || !encrypted) throw new Error("Invalid encrypted session format");
const salt = CryptoJS.enc.Hex.parse(saltHex);
const key = PBKDF2(SESSION_ENCRYPTION_KEY, salt, { keySize: 256 / 32, iterations: 100_000 });
const key = PBKDF2(keyInput, salt, { keySize: 256 / 32, iterations: 200_000 });
const bytes = CryptoJS.AES.decrypt(encrypted, key);
const decrypted = bytes.toString(CryptoJS.enc.Utf8);
return JSON.parse(decrypted);
@@ -191,7 +185,7 @@

public setTemporarySession = (session: TemporarySession) => {
// Encrypt session before storage in localStorage for security
const encrypted = encryptSession(session);
const encrypted = encryptSession(session, SESSION_ENCRYPTION_KEY);
localStorage.setItem(
`${this.sessionKey}:temporary`,
encrypted,
@@ -206,7 +200,7 @@
return null;
}

return decryptSession(cipherText);
return decryptSession(cipherText, SESSION_ENCRYPTION_KEY);
};

on = <E extends keyof SessionManagerEvents>(
Copilot is powered by AI and may make mistakes. Always verify output.
@Dargon789 Dargon789 committed this autofix suggestion 10 months ago.
Repository owner deleted a comment from vercel Bot Oct 28, 2025
…th insufficient computational effort

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
Repository owner deleted a comment from vercel Bot Oct 28, 2025
@github-actions
github-actions Bot had a problem deploying to docs-preview October 28, 2025 09:27 Failure
@Dargon789
Dargon789 marked this pull request as ready for review October 28, 2025 09:29
sourcery-ai[bot]
sourcery-ai Bot previously approved these changes Oct 28, 2025

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • I don’t see an import for CryptoJS (and encHex) or PBKDF2; you’ll need to import those from ‘crypto-js’ (e.g. CryptoJS and CryptoJS.PBKDF2) or reference CryptoJS.enc.Hex explicitly.
  • Pulling SESSION_ENCRYPTION_KEY from process.env couples this module to Node; consider passing the key into SessionManager or the encrypt/decrypt helpers so it works reliably in browser environments and avoids hidden global state.
  • 200,000 PBKDF2 iterations on the client may cause noticeable latency—either make the iteration count configurable or switch to the Web Crypto API for better performance.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- I don’t see an import for CryptoJS (and encHex) or PBKDF2; you’ll need to import those from ‘crypto-js’ (e.g. CryptoJS and CryptoJS.PBKDF2) or reference CryptoJS.enc.Hex explicitly.
- Pulling SESSION_ENCRYPTION_KEY from process.env couples this module to Node; consider passing the key into SessionManager or the encrypt/decrypt helpers so it works reliably in browser environments and avoids hidden global state.
- 200,000 PBKDF2 iterations on the client may cause noticeable latency—either make the iteration count configurable or switch to the Web Crypto API for better performance.

## Individual Comments

### Comment 1
<location> `account-kit/signer/src/session/manager.ts:38` </location>
<code_context>
+  const plaintext = JSON.stringify(sessionObj);
+  const salt = CryptoJS.lib.WordArray.random(16);
+  // Derive a key from the password using PBKDF2 with sufficient iterations
+  const key = PBKDF2(keyInput, salt, { keySize: 256 / 32, iterations: 200_000 });
+  const encrypted = CryptoJS.AES.encrypt(plaintext, key).toString();
+  // Store salt (hex) and ciphertext together as "salt:ciphertext"
</code_context>

<issue_to_address>
**suggestion (performance):** High PBKDF2 iteration count may impact performance in browsers.

Benchmark the current iteration count in target browsers and consider using a Web Worker to prevent UI blocking if performance issues arise.

Suggested implementation:

```typescript
/**
 * Benchmarks PBKDF2 performance in the browser.
 * Returns the time in milliseconds for the given iteration count.
 */
function benchmarkPBKDF2(keyInput: string, salt: CryptoJS.lib.WordArray, iterations: number): Promise<number> {
  return new Promise((resolve) => {
    const start = performance.now();
    PBKDF2(keyInput, salt, { keySize: 256 / 32, iterations });
    const end = performance.now();
    resolve(end - start);
  });
}

/**
 * Derives a key using PBKDF2 in a Web Worker to avoid UI blocking.
 * Returns a Promise that resolves to the derived key.
 */
function pbkdf2Worker(keyInput: string, salt: string, iterations: number): Promise<CryptoJS.lib.WordArray> {
  return new Promise((resolve, reject) => {
    // Inline worker code as a string
    const workerCode = `
      self.onmessage = function(e) {
        importScripts('https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js');
        const { keyInput, salt, iterations } = e.data;
        const key = CryptoJS.PBKDF2(keyInput, CryptoJS.enc.Hex.parse(salt), { keySize: 256 / 32, iterations });
        self.postMessage(key.toString(CryptoJS.enc.Hex));
      };
    `;
    const blob = new Blob([workerCode], { type: "application/javascript" });
    const worker = new Worker(URL.createObjectURL(blob));
    worker.onmessage = function(e) {
      const keyHex = e.data;
      resolve(CryptoJS.enc.Hex.parse(keyHex));
      worker.terminate();
    };
    worker.onerror = function(err) {
      reject(err);
      worker.terminate();
    };
    worker.postMessage({ keyInput, salt, iterations });
  });
}

async function encryptSession(sessionObj: object, keyParam?: string): Promise<string> {
  if (!keyParam && !SESSION_ENCRYPTION_KEY) {
    throw new Error("SESSION_ENCRYPTION_KEY must be set!");
  }
  const keyInput = keyParam ?? SESSION_ENCRYPTION_KEY;
  // Use a random salt for each session
  const plaintext = JSON.stringify(sessionObj);
  const salt = CryptoJS.lib.WordArray.random(16);
  const iterations = 200_000;

  // Benchmark PBKDF2 performance
  const pbkdf2Time = await benchmarkPBKDF2(keyInput, salt, iterations);

  let key: CryptoJS.lib.WordArray;
  if (pbkdf2Time > 500) { // If PBKDF2 takes more than 500ms, use Web Worker
    try {
      key = await pbkdf2Worker(keyInput, salt.toString(encHex), iterations);
    } catch (err) {
      // Fallback to synchronous PBKDF2 if worker fails
      key = PBKDF2(keyInput, salt, { keySize: 256 / 32, iterations });
    }
  } else {
    key = PBKDF2(keyInput, salt, { keySize: 256 / 32, iterations });
  }

  const encrypted = CryptoJS.AES.encrypt(plaintext, key).toString();
  // Store salt (hex) and ciphertext together as "salt:ciphertext"
  return salt.toString(encHex) + ':' + encrypted;
}

```

1. The `encryptSession` function is now asynchronous and returns a Promise. You will need to update all callers to use `await encryptSession(...)` or handle the returned Promise.
2. Ensure that `encHex` and `PBKDF2` are properly imported or defined in this file.
3. If you want to avoid loading CryptoJS in the worker from CDN, you can bundle the worker code separately.
4. You may want to expose the benchmark result for logging or telemetry.
</issue_to_address>

### Comment 2
<location> `account-kit/signer/src/session/manager.ts:40-41` </location>
<code_context>
+  const key = PBKDF2(keyInput, salt, { keySize: 256 / 32, iterations: 200_000 });
+  const encrypted = CryptoJS.AES.encrypt(plaintext, key).toString();
+  // Store salt (hex) and ciphertext together as "salt:ciphertext"
+  return salt.toString(encHex) + ':' + encrypted;
+}
+
</code_context>

<issue_to_address>
**issue (typo):** Potential typo: 'encHex' is not defined.

Please update 'encHex' to 'CryptoJS.enc.Hex' to prevent runtime errors.

```suggestion
  // Store salt (hex) and ciphertext together as "salt:ciphertext"
  return salt.toString(CryptoJS.enc.Hex) + ':' + encrypted;
```
</issue_to_address>

### Comment 3
<location> `account-kit/signer/src/session/manager.ts:29` </location>
<code_context>
+// IMPORTANT: Set this key securely through environment/config, not hardcoded.
+const SESSION_ENCRYPTION_KEY = process.env.SESSION_ENCRYPTION_KEY;
+
+function encryptSession(sessionObj: object, keyParam?: string) {
+  if (!keyParam && !SESSION_ENCRYPTION_KEY) {
+    throw new Error("SESSION_ENCRYPTION_KEY must be set!");
</code_context>

<issue_to_address>
**issue (complexity):** Consider moving all cryptographic logic into a separate utility module to keep the session manager focused on session handling.

Consider extracting all the crypto boilerplate into its own module so your session‐manager stays focused on session logic. For example:

1. Create `src/utils/sessionCrypto.ts`:

```ts
import * as CryptoJS from "crypto-js";
import PBKDF2 from "crypto-js/pbkdf2";
import encHex from "crypto-js/enc-hex";

const DEFAULT_ITER = 200_000;
const KEY_SIZE = 256 / 32;

export function encryptSession(
  sessionObj: object,
  keyInput: string
): string {
  const plaintext = JSON.stringify(sessionObj);
  const salt = CryptoJS.lib.WordArray.random(16);
  const key = PBKDF2(keyInput, salt, { keySize: KEY_SIZE, iterations: DEFAULT_ITER });
  const encrypted = CryptoJS.AES.encrypt(plaintext, key).toString();
  return `${salt.toString(encHex)}:${encrypted}`;
}

export function decryptSession(
  data: string,
  keyInput: string
): any | null {
  try {
    const [saltHex, ciphertext] = data.split(":");
    if (!saltHex || !ciphertext) throw new Error("Invalid format");
    const salt = CryptoJS.enc.Hex.parse(saltHex);
    const key = PBKDF2(keyInput, salt, { keySize: KEY_SIZE, iterations: DEFAULT_ITER });
    const bytes = CryptoJS.AES.decrypt(ciphertext, key);
    return JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
  } catch {
    console.warn("Failed to decrypt session");
    return null;
  }
}
```

2. In your session manager file, remove the inline implementations and simply:

```ts
import { encryptSession, decryptSession } from "../utils/sessionCrypto";

//

public setTemporarySession(session: TemporarySession) {
  const encrypted = encryptSession(session, SESSION_ENCRYPTION_KEY);
  localStorage.setItem(`${this.sessionKey}:temporary`, encrypted);
}

public getTemporarySession(): TemporarySession | null {
  const cipherText = localStorage.getItem(`${this.sessionKey}:temporary`);
  return cipherText
    ? (decryptSession(cipherText, SESSION_ENCRYPTION_KEY) as TemporarySession)
    : null;
}
```

This keeps your manager file ~60 LOC smaller and all crypto‐details isolated.
</issue_to_address>

### Comment 4
<location> `account-kit/signer/src/session/manager.ts:27` </location>
<code_context>
const SESSION_ENCRYPTION_KEY = process.env.SESSION_ENCRYPTION_KEY;

</code_context>

<issue_to_address>
**suggestion (code-quality):** Prefer object destructuring when accessing and using properties. ([`use-object-destructuring`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/TypeScript/Default-Rules/use-object-destructuring))

```suggestion
const {SESSION_ENCRYPTION_KEY} = process.env;
```

<br/><details><summary>Explanation</summary>Object destructuring can often remove an unnecessary temporary reference, as well as making your code more succinct.

From the [Airbnb Javascript Style Guide](https://airbnb.io/javascript/#destructuring--object)
</details>
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread account-kit/signer/src/session/manager.ts
Comment thread account-kit/signer/src/session/manager.ts Outdated
Comment thread account-kit/signer/src/session/manager.ts
Comment thread account-kit/signer/src/session/manager.ts Outdated
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
@github-actions
github-actions Bot had a problem deploying to docs-preview October 28, 2025 09:32 Failure
Repository owner deleted a comment from vercel Bot Oct 28, 2025
@github-actions
github-actions Bot had a problem deploying to docs-preview October 28, 2025 09:33 Failure
@Dargon789
Dargon789 merged commit 28cf01b into main Oct 28, 2025
13 of 23 checks passed
@Dargon789
Dargon789 deleted the alert-autofix-11 branch October 28, 2025 09:34
@Dargon789 Dargon789 linked an issue Nov 8, 2025 that may be closed by this pull request
Dargon789 added a commit that referenced this pull request Jun 5, 2026
* build(deps): bump the npm_and_yarn group across 4 directories with 2 updates

Bumps the npm_and_yarn group with 2 updates in the / directory: [esbuild](https://github.com/evanw/esbuild) and [next](https://github.com/vercel/next.js).
Bumps the npm_and_yarn group with 1 update in the /account-kit/plugingen directory: [esbuild](https://github.com/evanw/esbuild).
Bumps the npm_and_yarn group with 1 update in the /doc-gen directory: [esbuild](https://github.com/evanw/esbuild).
Bumps the npm_and_yarn group with 1 update in the /examples/ui-demo directory: [next](https://github.com/vercel/next.js).


Updates `esbuild` from 0.20.2 to 0.25.0
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG-2024.md)
- [Commits](evanw/esbuild@v0.20.2...v0.25.0)

Updates `next` from 14.2.29 to 14.2.30
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](vercel/next.js@v14.2.29...v14.2.30)

Updates `esbuild` from 0.20.2 to 0.25.5
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG-2024.md)
- [Commits](evanw/esbuild@v0.20.2...v0.25.0)

Updates `esbuild` from 0.20.2 to 0.25.5
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG-2024.md)
- [Commits](evanw/esbuild@v0.20.2...v0.25.0)

Updates `next` from 14.2.29 to 14.2.30
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](vercel/next.js@v14.2.29...v14.2.30)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.25.0
  dependency-type: direct:production
  dependency-group: npm_and_yarn
- dependency-name: next
  dependency-version: 14.2.30
  dependency-type: direct:production
  dependency-group: npm_and_yarn
- dependency-name: esbuild
  dependency-version: 0.25.5
  dependency-type: direct:production
  dependency-group: npm_and_yarn
- dependency-name: esbuild
  dependency-version: 0.25.5
  dependency-type: direct:production
  dependency-group: npm_and_yarn
- dependency-name: next
  dependency-version: 14.2.30
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>

* docs: remove outdated naming guidance (alchemyplatform#1747)

* feat: update the max token amount (alchemyplatform#1745)

* feat(middleware): add signed permit to uo context for use in middleware

* chore(release): publish v4.48.0 [skip-ci]

* Create SECURITY.md

Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com>

* Potential fix for code scanning alert no. 10: Insecure randomness

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com>

* Create config.yml (#38)

Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com>

* build(deps): bump esbuild in the npm_and_yarn group across 1 directory (#41)

Bumps the npm_and_yarn group with 1 update in the / directory: [esbuild](https://github.com/evanw/esbuild).


Updates `esbuild` from 0.25.5 to 0.25.6
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](evanw/esbuild@v0.25.5...v0.25.6)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.25.6
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix: account-kit/rn-signer/example/Gemfile to reduce vulnerabilities (#44)

The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-RUBY-REXML-12878608

Co-authored-by: snyk-io[bot] <141718529+snyk-io[bot]@users.noreply.github.com>

* build(deps): bump rexml (#43)

Bumps the bundler group with 1 update in the /account-kit/rn-signer/example directory: [rexml](https://github.com/ruby/rexml).


Updates `rexml` from 3.3.9 to 3.4.2
- [Release notes](https://github.com/ruby/rexml/releases)
- [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md)
- [Commits](ruby/rexml@v3.3.9...v3.4.2)

---
updated-dependencies:
- dependency-name: rexml
  dependency-version: 3.4.2
  dependency-type: indirect
  dependency-group: bundler
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump the npm_and_yarn group across 2 directories with 4 updates (#42)

Bumps the npm_and_yarn group with 4 updates in the / directory: [esbuild](https://github.com/evanw/esbuild), [next](https://github.com/vercel/next.js), [sha.js](https://github.com/crypto-browserify/sha.js) and [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).
Bumps the npm_and_yarn group with 1 update in the /examples/ui-demo directory: [next](https://github.com/vercel/next.js).


Updates `esbuild` from 0.25.6 to 0.25.7
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](evanw/esbuild@v0.25.6...v0.25.7)

Updates `next` from 14.2.30 to 14.2.32
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](vercel/next.js@v14.2.30...v14.2.32)

Updates `sha.js` from 2.4.11 to 2.4.12
- [Changelog](https://github.com/browserify/sha.js/blob/master/CHANGELOG.md)
- [Commits](browserify/sha.js@v2.4.11...v2.4.12)

Updates `vite` from 5.4.19 to 5.4.20
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.20/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.20/packages/vite)

Updates `next` from 14.2.30 to 14.2.32
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](vercel/next.js@v14.2.30...v14.2.32)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.25.7
  dependency-type: direct:production
  dependency-group: npm_and_yarn
- dependency-name: next
  dependency-version: 14.2.32
  dependency-type: direct:production
  dependency-group: npm_and_yarn
- dependency-name: sha.js
  dependency-version: 2.4.12
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: vite
  dependency-version: 5.4.20
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: next
  dependency-version: 14.2.32
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump rexml (#45)

Bumps the bundler group with 1 update in the /examples/react-native-bare-example directory: [rexml](https://github.com/ruby/rexml).


Updates `rexml` from 3.4.1 to 3.4.2
- [Release notes](https://github.com/ruby/rexml/releases)
- [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md)
- [Commits](ruby/rexml@v3.4.1...v3.4.2)

---
updated-dependencies:
- dependency-name: rexml
  dependency-version: 3.4.2
  dependency-type: indirect
  dependency-group: bundler
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump the npm_and_yarn group across 1 directory with 2 updates (#46)

Bumps the npm_and_yarn group with 2 updates in the / directory: [axios](https://github.com/axios/axios) and [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `axios` from 1.9.0 to 1.12.2
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](axios/axios@v1.9.0...v1.12.2)

Updates `vite` from 5.4.20 to 5.4.21
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.21/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.21/packages/vite)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.12.2
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: vite
  dependency-version: 5.4.21
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Potential fix for code scanning alert no. 11: Clear text storage of sensitive information (#48)

* Potential fix for code scanning alert no. 11: Clear text storage of sensitive information

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>

* Potential fix for code scanning alert no. 15: Use of password hash with insufficient computational effort

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>

* Potential fix for code scanning alert no. 16: Use of password hash with insufficient computational effort

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>

* Update account-kit/signer/src/session/manager.ts

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>

* Update account-kit/signer/src/session/manager.ts

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>

---------

Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>

* build(deps-dev): bump the npm_and_yarn group across 4 directories with 1 update

Bumps the npm_and_yarn group with 1 update in the / directory: [@react-native-community/cli](https://github.com/react-native-community/cli/tree/HEAD/packages/cli).
Bumps the npm_and_yarn group with 1 update in the /account-kit/rn-signer directory: [@react-native-community/cli](https://github.com/react-native-community/cli/tree/HEAD/packages/cli).
Bumps the npm_and_yarn group with 1 update in the /account-kit/rn-signer/example directory: [@react-native-community/cli](https://github.com/react-native-community/cli/tree/HEAD/packages/cli).
Bumps the npm_and_yarn group with 1 update in the /examples/react-native-bare-example directory: [@react-native-community/cli](https://github.com/react-native-community/cli/tree/HEAD/packages/cli).


Updates `@react-native-community/cli` from 15.0.1 to 20.0.0
- [Release notes](https://github.com/react-native-community/cli/releases)
- [Changelog](https://github.com/react-native-community/cli/blob/main/packages/cli/CHANGELOG.md)
- [Commits](https://github.com/react-native-community/cli/commits/v20.0.0/packages/cli)

Updates `@react-native-community/cli` from 15.0.1 to 20.0.0
- [Release notes](https://github.com/react-native-community/cli/releases)
- [Changelog](https://github.com/react-native-community/cli/blob/main/packages/cli/CHANGELOG.md)
- [Commits](https://github.com/react-native-community/cli/commits/v20.0.0/packages/cli)

Updates `@react-native-community/cli` from 15.0.1 to 20.0.0
- [Release notes](https://github.com/react-native-community/cli/releases)
- [Changelog](https://github.com/react-native-community/cli/blob/main/packages/cli/CHANGELOG.md)
- [Commits](https://github.com/react-native-community/cli/commits/v20.0.0/packages/cli)

Updates `@react-native-community/cli` from 15.0.1 to 20.0.0
- [Release notes](https://github.com/react-native-community/cli/releases)
- [Changelog](https://github.com/react-native-community/cli/blob/main/packages/cli/CHANGELOG.md)
- [Commits](https://github.com/react-native-community/cli/commits/v20.0.0/packages/cli)

---
updated-dependencies:
- dependency-name: "@react-native-community/cli"
  dependency-version: 20.0.0
  dependency-type: direct:development
  dependency-group: npm_and_yarn
- dependency-name: "@react-native-community/cli"
  dependency-version: 20.0.0
  dependency-type: direct:development
  dependency-group: npm_and_yarn
- dependency-name: "@react-native-community/cli"
  dependency-version: 20.0.0
  dependency-type: direct:development
  dependency-group: npm_and_yarn
- dependency-name: "@react-native-community/cli"
  dependency-version: 20.0.0
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update config.yml

Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>

* Update .circleci/config.yml

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>

* build(deps-dev): bump @react-native-community/cli

Bumps the npm_and_yarn group with 1 update in the / directory: [@react-native-community/cli](https://github.com/react-native-community/cli/tree/HEAD/packages/cli).


Updates `@react-native-community/cli` from 15.0.1 to 17.0.1
- [Release notes](https://github.com/react-native-community/cli/releases)
- [Changelog](https://github.com/react-native-community/cli/blob/main/packages/cli/CHANGELOG.md)
- [Commits](https://github.com/react-native-community/cli/commits/v17.0.1/packages/cli)

---
updated-dependencies:
- dependency-name: "@react-native-community/cli"
  dependency-version: 17.0.1
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix: examples/react-native-bare-example/package.json to reduce vulnerabilities

The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-JSYAML-13961110

* fix: examples/react-native-expo-example/package.json to reduce vulnerabilities

The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-JSYAML-13961110

* fix: account-kit/rn-signer/example/package.json to reduce vulnerabilities (#60)

The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-EXPRESS-14157151

Co-authored-by: snyk-bot <snyk-bot@snyk.io>

* fix: examples/ui-demo/package.json to reduce vulnerabilities (#61)

The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-NEXT-14400636

Co-authored-by: snyk-bot <snyk-bot@snyk.io>

* fix: account-kit/react/package.json to reduce vulnerabilities

The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-PREACT-14897824
- https://snyk.io/vuln/SNYK-JS-REMIXRUNROUTER-14908530
- https://snyk.io/vuln/SNYK-JS-REMIXRUNROUTER-14908287

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: noam-alchemy <76969113+noam-alchemy@users.noreply.github.com>
Co-authored-by: Blake Duncan <blake.duncan@alchemy.com>
Co-authored-by: Dan <dan.coombs@alchemy.com>
Co-authored-by: Alchemy Bot <alchemy-bot@alchemy.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: snyk-io[bot] <141718529+snyk-io[bot]@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: snyk-bot <snyk-bot@snyk.io>
Co-authored-by: googleworkspace-bot <googleworkspace-bot@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

#ERC-20 gas payment flow with paymaster quote

2 participants