diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b5c41be1..10da312cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Docs: https://docs.openclaw.ai ### Fixes - Security/Canvas: serve A2UI assets via the shared safe-open path (`openFileWithinRoot`) to close traversal/TOCTOU gaps, with traversal and symlink regression coverage. (#10525) Thanks @abdelsfane. +- Security/WhatsApp: enforce `0o600` on `creds.json` and `creds.json.bak` on save/backup/restore paths to reduce credential file exposure. (#10529) Thanks @abdelsfane. - Security/Gateway + ACP: block high-risk tools (`sessions_spawn`, `sessions_send`, `gateway`, `whatsapp_login`) from HTTP `/tools/invoke` by default with `gateway.tools.{allow,deny}` overrides, and harden ACP permission selection to fail closed when tool identity/options are ambiguous while supporting `allow_always`/`reject_always`. (#15390) Thanks @aether-ai-agent. - MS Teams: preserve parsed mention entities/text when appending OneDrive fallback file links, and accept broader real-world Teams mention ID formats (`29:...`, `8:orgid:...`) while still rejecting placeholder patterns. (#15436) Thanks @hyojin. - Security/Audit: distinguish external webhooks (`hooks.enabled`) from internal hooks (`hooks.internal.enabled`) in attack-surface summaries to avoid false exposure signals when only internal hooks are enabled. (#13474) Thanks @mcaxtr. diff --git a/src/web/auth-store.ts b/src/web/auth-store.ts index 3b535eb82..e98e48b67 100644 --- a/src/web/auth-store.ts +++ b/src/web/auth-store.ts @@ -68,6 +68,11 @@ export function maybeRestoreCredsFromBackup(authDir: string): void { // Ensure backup is parseable before restoring. JSON.parse(backupRaw); fsSync.copyFileSync(backupPath, credsPath); + try { + fsSync.chmodSync(credsPath, 0o600); + } catch { + // best-effort on platforms that support it + } logger.warn({ credsPath }, "restored corrupted WhatsApp creds.json from backup"); } catch { // ignore diff --git a/src/web/session.ts b/src/web/session.ts index c25d6d793..c02f59388 100644 --- a/src/web/session.ts +++ b/src/web/session.ts @@ -73,6 +73,11 @@ async function safeSaveCreds( try { JSON.parse(raw); fsSync.copyFileSync(credsPath, backupPath); + try { + fsSync.chmodSync(backupPath, 0o600); + } catch { + // best-effort on platforms that support it + } } catch { // keep existing backup } @@ -82,6 +87,11 @@ async function safeSaveCreds( } try { await Promise.resolve(saveCreds()); + try { + fsSync.chmodSync(resolveWebCredsPath(authDir), 0o600); + } catch { + // best-effort on platforms that support it + } } catch (err) { logger.warn({ error: String(err) }, "failed saving WhatsApp creds"); }