fix: redact secrets in remaining error-log call sites

Security audit pass 1 (step 2/6): five console.warn/error sites and the
credential Test-button error path logged raw error objects that could
leak API keys embedded in provider error messages. Route them through
the existing redactError/redactSecrets helpers.

Co-Authored-By: Claude <bot@wafflenet.io>
This commit is contained in:
bot 2026-07-02 13:48:23 -07:00
parent 33a9a58db9
commit fd56a302c8
No known key found for this signature in database
3 changed files with 10 additions and 8 deletions

View file

@ -17,7 +17,7 @@ import { CommandRegistrar, auditCommands, listPaletteActions, REGISTRY_BY_ID } f
import { planFirstRun, WELCOME_MESSAGE, WELCOME_NOTICE_DURATION_MS } from './onboarding';
import { SynapseRunner } from './pipeline';
import type { PipelineModuleMap } from './pipeline';
import { openScanFolderPicker, NotificationManager, CheckpointManager, UpdateChecker, fireAndForget, migrateSettings, readSettingsVersion, CURRENT_SETTINGS_VERSION } from './shared';
import { openScanFolderPicker, NotificationManager, CheckpointManager, UpdateChecker, fireAndForget, migrateSettings, readSettingsVersion, CURRENT_SETTINGS_VERSION, redactError } from './shared';
import type { DeferredTask } from './shared';
import { UnifiedTranscriptionModal, NoteMediaModal } from './transcription';
import { findAudioEmbeds } from './audio';
@ -486,7 +486,7 @@ export default class SynapsePlugin extends Plugin {
} catch (error) {
// Resilient fallback — load must never break. migrateSettings clones
// before mutating, so `raw` is still the untouched original here.
console.warn('[Synapse] settings migration failed:', error);
console.warn('[Synapse] settings migration failed:', redactError(error));
migrated = raw;
}
}
@ -526,7 +526,7 @@ export default class SynapsePlugin extends Plugin {
this.notifications.info(WELCOME_MESSAGE, WELCOME_NOTICE_DURATION_MS);
}
} catch (error) {
console.warn('[Synapse] First-run onboarding failed:', error);
console.warn('[Synapse] First-run onboarding failed:', redactError(error));
}
}
@ -809,7 +809,7 @@ export default class SynapsePlugin extends Plugin {
// Clean up old completed/discarded checkpoints
await this.checkpointManager.cleanup();
} catch (error) {
console.warn('[Synapse] Failed to check for incomplete checkpoints:', error);
console.warn('[Synapse] Failed to check for incomplete checkpoints:', redactError(error));
}
}
@ -902,7 +902,7 @@ export default class SynapsePlugin extends Plugin {
`migrated data folder from ${OLD_FOLDER}/ to ${NEW_FOLDER}/`
);
} catch (error) {
console.error('[Synapse] Failed to migrate data folder:', error);
console.error('[Synapse] Failed to migrate data folder:', redactError(error));
// Persistent, copyable error toast (NotificationManager exists by now —
// it is constructed before migrateDataFolder() in onload).
this.notifications.error(

View file

@ -13,6 +13,7 @@ import { PROVIDER_METADATA } from './provider-metadata';
import type { CredentialProvider } from './provider-metadata';
import { validateCredentials } from './credential-validator';
import type { ValidationResult } from './credential-validator';
import { redactSecrets } from './redact';
export interface CredentialFieldOptions {
/** The key (or, for Ollama, endpoint) Setting row to decorate (gets the Test button). */
@ -114,7 +115,7 @@ export function decorateCredentialField(opts: CredentialFieldOptions): Credentia
settle({
status: 'error',
provider,
message: err instanceof Error ? err.message : String(err),
message: redactSecrets(err instanceof Error ? err.message : String(err)),
}),
);
}),

View file

@ -4,6 +4,7 @@ import type { SynapseSettings } from '../settings';
import type { NotificationManager } from './notifications';
import { withRetry, isTransientNetworkError, describeNetworkError } from './api-utils';
import { isRecord } from './json-utils';
import { redactError, redactSecrets } from './redact';
/**
* In-app "a newer Synapse is available" check (#365).
@ -133,7 +134,7 @@ export class UpdateChecker {
await this.deps.saveSettings();
} catch (error) {
// Defense in depth: the startup path must never see a throw from here.
console.warn('[Synapse] Update check encountered an unexpected error:', error);
console.warn('[Synapse] Update check encountered an unexpected error:', redactError(error));
}
}
@ -166,7 +167,7 @@ export class UpdateChecker {
const detail =
describeNetworkError(error, 'GitHub') ??
(error instanceof Error ? error.message : String(error));
console.warn('[Synapse] Update check failed:', detail);
console.warn('[Synapse] Update check failed:', redactSecrets(detail));
return null;
}
}