mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-08-05 06:50:10 +00:00
fix(security): harden auth and request limits
This commit is contained in:
@@ -94,6 +94,14 @@ export function loadSession(): SessionState | null {
|
||||
const raw = localStorage.getItem(SESSION_KEY);
|
||||
if (!raw) return null;
|
||||
const parsed = JSON.parse(raw) as Partial<SessionState> & Partial<PersistedSessionState>;
|
||||
if (parsed.email && (parsed.accessToken || parsed.refreshToken)) {
|
||||
const authMode = parsed.authMode === 'web-cookie' ? 'web-cookie' : 'token';
|
||||
saveSession({ email: parsed.email, authMode });
|
||||
return {
|
||||
email: parsed.email,
|
||||
authMode,
|
||||
};
|
||||
}
|
||||
if (parsed.authMode === 'web-cookie' && parsed.email) {
|
||||
return {
|
||||
email: parsed.email,
|
||||
@@ -106,13 +114,7 @@ export function loadSession(): SessionState | null {
|
||||
authMode: 'token',
|
||||
};
|
||||
}
|
||||
if (!parsed.accessToken || !parsed.refreshToken || !parsed.email) return null;
|
||||
return {
|
||||
accessToken: parsed.accessToken,
|
||||
refreshToken: parsed.refreshToken,
|
||||
email: parsed.email,
|
||||
authMode: 'token',
|
||||
};
|
||||
return null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,28 @@ const VAULT_CORE_STORE = 'vault-core';
|
||||
|
||||
let dbPromise: Promise<IDBDatabase | null> | null = null;
|
||||
|
||||
function stripDecryptedCacheFields<T>(value: T): T {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((item) => stripDecryptedCacheFields(item)) as T;
|
||||
}
|
||||
if (!value || typeof value !== 'object') return value;
|
||||
const source = value as Record<string, unknown>;
|
||||
const out: Record<string, unknown> = {};
|
||||
for (const [key, item] of Object.entries(source)) {
|
||||
if (/^dec[A-Z]/.test(key) || key === 'shareUrl') continue;
|
||||
out[key] = stripDecryptedCacheFields(item);
|
||||
}
|
||||
return out as T;
|
||||
}
|
||||
|
||||
function sanitizeSnapshotForCache(snapshot: VaultCoreSnapshot): VaultCoreSnapshot {
|
||||
return {
|
||||
ciphers: stripDecryptedCacheFields(Array.isArray(snapshot.ciphers) ? snapshot.ciphers : []),
|
||||
folders: stripDecryptedCacheFields(Array.isArray(snapshot.folders) ? snapshot.folders : []),
|
||||
sends: stripDecryptedCacheFields(Array.isArray(snapshot.sends) ? snapshot.sends : []),
|
||||
};
|
||||
}
|
||||
|
||||
function supportsIndexedDb(): boolean {
|
||||
return typeof indexedDB !== 'undefined';
|
||||
}
|
||||
@@ -72,7 +94,7 @@ export async function loadCachedVaultCoreSnapshot(cacheKey: string): Promise<Vau
|
||||
const request = store.get(normalized);
|
||||
request.onsuccess = () => {
|
||||
const record = request.result as VaultCoreCacheRecord | undefined;
|
||||
resolve(record || null);
|
||||
resolve(record ? { ...record, snapshot: sanitizeSnapshotForCache(record.snapshot) } : null);
|
||||
};
|
||||
request.onerror = () => resolve(null);
|
||||
}));
|
||||
@@ -90,7 +112,7 @@ export async function saveCachedVaultCoreSnapshot(
|
||||
cacheKey: normalized,
|
||||
revisionStamp,
|
||||
savedAt: Date.now(),
|
||||
snapshot,
|
||||
snapshot: sanitizeSnapshotForCache(snapshot),
|
||||
};
|
||||
const request = store.put(record);
|
||||
request.onsuccess = () => resolve();
|
||||
|
||||
Reference in New Issue
Block a user