fix: multiple backup import issues found in code review
- Single atomic write instead of two-phase (prevents split state on crash) - Timestamped pre-import backup (multiple imports don't overwrite safety net) - Fix UI refresh: correct function names + refresh globalSettings/alwaysOnTop - Zero sensitive buffers (key, plaintext, decrypted) after use Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
fb4dd94827
commit
60498fecc4
@ -27,6 +27,8 @@ function encrypt(config, password) {
|
|||||||
const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
||||||
const tag = cipher.getAuthTag();
|
const tag = cipher.getAuthTag();
|
||||||
|
|
||||||
|
plaintext.fill(0);
|
||||||
|
key.fill(0);
|
||||||
return Buffer.concat([MAGIC, salt, iv, tag, encrypted]);
|
return Buffer.concat([MAGIC, salt, iv, tag, encrypted]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,6 +67,9 @@ function decrypt(buffer, password) {
|
|||||||
return JSON.parse(decrypted.toString('utf-8'));
|
return JSON.parse(decrypted.toString('utf-8'));
|
||||||
} catch {
|
} catch {
|
||||||
throw new Error('Entschlüsselte Daten sind kein gültiges JSON');
|
throw new Error('Entschlüsselte Daten sind kein gültiges JSON');
|
||||||
|
} finally {
|
||||||
|
decrypted.fill(0);
|
||||||
|
key.fill(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
22
main.js
22
main.js
@ -649,17 +649,19 @@ ipcMain.handle('import-backup', async (_event, password) => {
|
|||||||
});
|
});
|
||||||
if (canceled || !filePaths.length) return { ok: false, canceled: true };
|
if (canceled || !filePaths.length) return { ok: false, canceled: true };
|
||||||
const buffer = fs.readFileSync(filePaths[0]);
|
const buffer = fs.readFileSync(filePaths[0]);
|
||||||
const config = backupCrypto.decrypt(buffer, password);
|
const imported = backupCrypto.decrypt(buffer, password);
|
||||||
// Safety net: save current config before overwriting
|
// Safety net: timestamped backup so multiple imports don't overwrite each other
|
||||||
const preImportPath = configStore.filePath + '.pre-import.json';
|
const ts = new Date().toISOString().replace(/[:.]/g, '-');
|
||||||
|
const preImportPath = configStore.filePath.replace('.json', `.pre-import-${ts}.json`);
|
||||||
try { fs.copyFileSync(configStore.filePath, preImportPath); } catch {}
|
try { fs.copyFileSync(configStore.filePath, preImportPath); } catch {}
|
||||||
await configStore.save(config);
|
// Single atomic write — no split state, no TOCTOU race
|
||||||
if (config.history) {
|
const merged = {
|
||||||
// Overwrite history too (save() doesn't touch history)
|
hosters: imported.hosters,
|
||||||
const full = configStore.load();
|
hosterSettings: imported.hosterSettings,
|
||||||
full.history = config.history;
|
globalSettings: imported.globalSettings,
|
||||||
await configStore._atomicWrite(JSON.stringify(full, null, 2));
|
history: imported.history || []
|
||||||
}
|
};
|
||||||
|
await configStore._atomicWrite(JSON.stringify(merged, null, 2));
|
||||||
return { ok: true, config: configStore.load() };
|
return { ok: true, config: configStore.load() };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -857,9 +857,14 @@ async function confirmBackupAction() {
|
|||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
config = result.config;
|
config = result.config;
|
||||||
hosterSettings = config.hosterSettings || {};
|
hosterSettings = config.hosterSettings || {};
|
||||||
|
// Refresh global settings state (always-on-top, etc.)
|
||||||
|
alwaysOnTopState = !!(config.globalSettings && config.globalSettings.alwaysOnTop);
|
||||||
|
window.api.setAlwaysOnTop(alwaysOnTopState);
|
||||||
closeBackupModal();
|
closeBackupModal();
|
||||||
renderSettingsPanel();
|
renderSettings();
|
||||||
renderAccountsList();
|
renderAccounts();
|
||||||
|
renderHosterSummary();
|
||||||
|
renderHosterModal();
|
||||||
loadHistory();
|
loadHistory();
|
||||||
showCopyToast('Backup importiert');
|
showCopyToast('Backup importiert');
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user