Skip to content
This repository was archived by the owner on May 25, 2026. It is now read-only.

Security: Potential sensitive data exposure via plaintext localStorage#1174

Open
tuanaiseo wants to merge 1 commit into
ZoneMinder:masterfrom
tuanaiseo:contribai/fix/security/potential-sensitive-data-exposure-via-pl
Open

Security: Potential sensitive data exposure via plaintext localStorage#1174
tuanaiseo wants to merge 1 commit into
ZoneMinder:masterfrom
tuanaiseo:contribai/fix/security/potential-sensitive-data-exposure-via-pl

Conversation

@tuanaiseo
Copy link
Copy Markdown

Problem

The storage helper writes raw values/objects directly to window.localStorage without encryption, scope restrictions, or key allowlisting. If credentials, API keys, or session tokens are stored through this helper, they are accessible to any injected script and may persist indefinitely.

Severity: high
File: www/js/ionicUtils.js

Solution

Do not store secrets in localStorage. Move sensitive values to platform secure storage (Keychain/Keystore via Cordova secure plugins), minimize retention, and enforce key-level policy to prevent accidental secret writes.

Changes

  • www/js/ionicUtils.js (modified)

Testing

  • Existing tests pass
  • Manual review completed
  • No new warnings/errors introduced

The storage helper writes raw values/objects directly to `window.localStorage` without encryption, scope restrictions, or key allowlisting. If credentials, API keys, or session tokens are stored through this helper, they are accessible to any injected script and may persist indefinitely.

Affected files: ionicUtils.js

Signed-off-by: tuanaiseo <221258316+tuanaiseo@users.noreply.github.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR aims to reduce the risk of sensitive data exposure by preventing certain “sensitive-looking” keys from being persisted to window.localStorage via the $localstorage helper.

Changes:

  • Added a regex-based check to block writes to localStorage when the key name appears to contain sensitive terms.
  • Applied this check to both set and setObject.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread www/js/ionicUtils.js
Comment on lines +11 to +12
function canStoreKey(key) {
return key && !sensitiveKeyPattern.test(key);
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

canStoreKey currently implements a denylist via regex. This is easy to bypass by storing a secret under a non-matching key (e.g., s, data, etc.), so it doesn’t reliably prevent accidental credential/token persistence. Consider switching to an allowlist of explicitly approved keys (or a required prefix + allowlisted suffixes) and rejecting everything else by default.

Suggested change
function canStoreKey(key) {
return key && !sensitiveKeyPattern.test(key);
var allowedKeyPrefixes = ['app_', 'cfg_', 'config_', 'cache_', 'tmp_', 'pref_', 'prefs_', 'setting_', 'settings_', 'user_', 'profile_'];
function canStoreKey(key) {
if (typeof key !== 'string' || !key) {
return false;
}
var hasAllowedPrefix = allowedKeyPrefixes.some(function (prefix) {
return key.indexOf(prefix) === 0;
});
if (!hasAllowedPrefix) {
return false;
}
return !sensitiveKeyPattern.test(key);

Copilot uses AI. Check for mistakes.
Comment thread www/js/ionicUtils.js
Comment on lines 19 to 23
set: function (key, value) {
if (!canStoreKey(key)) {
return;
}
$window.localStorage[key] = value;
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

Blocking writes by returning early is silent and can leave an existing sensitive value in localStorage untouched (if it was previously stored), increasing retention. Consider (1) removing any existing value for blocked keys (e.g., removeItem) and (2) surfacing the rejection to callers (throw, return a boolean, or log) so failures aren’t masked.

Copilot uses AI. Check for mistakes.
Comment thread www/js/ionicUtils.js
angular.module('ionic.utils', [])

.factory('$localstorage', ['$window', function ($window) {
var sensitiveKeyPattern = /(pass(word)?|secret|token|auth|api[_-]?key|session|cookie|credential|jwt)/i;
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

The regex matches substrings like auth anywhere in the key, which can block unrelated keys such as authorName or oauthRedirect. Consider adding word/segment boundaries (e.g., start/end, _/- separators) or matching against a list of exact forbidden keys to reduce false positives.

Suggested change
var sensitiveKeyPattern = /(pass(word)?|secret|token|auth|api[_-]?key|session|cookie|credential|jwt)/i;
var sensitiveKeyPattern = /(pass(word)?|secret|token|(^|[_-])auth([_-]|$)|api[_-]?key|session|cookie|credential|jwt)/i;

Copilot uses AI. Check for mistakes.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants