fix(server): rotate the stored service key with ENCRYPTION_KEY and pin every encrypted app setting

This commit is contained in:
Maurice
2026-10-29 09:09:00 +01:00
committed by Maurice
parent 44add57109
commit 01c0f8b64c
2 changed files with 14 additions and 0 deletions
+5
View File
@@ -295,6 +295,10 @@ async function main() {
// web_push_vapid_private_key is the Web Push signing key VapidKeysService
// generates. Missed here it would no longer decrypt under the new key, and
// push would stay off on every device until the old key came back.
//
// service_key is the installation's key towards the liketrek services.
// Missed here it reads back as unusable, the installation registers anew and
// loses its id, and a revoked key would come back as a fresh one.
for (const key of [
'oidc_client_secret',
'smtp_pass',
@@ -304,6 +308,7 @@ async function main() {
'unsplash_api_key',
'amap_api_key',
'web_push_vapid_private_key',
'service_key',
]) {
const row = db.prepare('SELECT value FROM app_settings WHERE key = ?').get(key) as { value: string } | undefined;
if (!row?.value) continue;
@@ -10,6 +10,7 @@
* key, decrypt_api_key returns null on the next read, and the instance quietly
* behaves as if no key were configured. This pins the copy instead.
*/
import { ENCRYPTED_APP_SETTING_KEYS } from '../../../src/nest/common/app-settings.registry';
import { INSTANCE_API_KEY_NAMES } from '../../../src/nest/settings/instance-api-keys';
import { storageSecretFields } from '@trek/shared';
@@ -110,6 +111,14 @@ describe('migrate-encryption.ts app_settings parity', () => {
expect(INSTANCE_API_KEY_NAMES.length).toBeGreaterThan(0);
});
// The register marks every app setting stored encrypted, the service key among them.
it('ROTPAR-015: rotates every app setting the register stores encrypted', () => {
expect(ENCRYPTED_APP_SETTING_KEYS.size).toBeGreaterThan(0);
for (const key of ENCRYPTED_APP_SETTING_KEYS) {
expect(appSettingsLoop).toContain(`'${key}'`);
}
});
it('ROTPAR-004: rotates every storage.backends secret field for s3', () => {
const fields = storageSecretFields('s3');
expect(fields.length).toBeGreaterThan(0);