fix: security audit — patch vulnerabilities V-02 through V-16

- V-02: XSS via innerHTML in profile.js — wrap err.message in escapeHtml()
- V-03: IDOR upload to other users' folders — add folder ownership check
- V-04: IDOR create folders in other users' trees — add parent ownership check
- V-06: Content-Disposition header injection — RFC 5987 percent-encoding
- V-08: WebDAV MOVE/COPY destination without ownership — add assert_owner checks
- V-09: .gitignore missing cert/key patterns — add *.pem, *.key, *.p12, etc.
- V-11: Username accepts XSS payloads — restrict to [a-zA-Z0-9._-]
- V-12: Minimal email validation — reject forbidden chars, require domain dot
- V-13: admin_reset_password doesn't invalidate sessions — revoke all sessions
- V-14: Rate limiting bypassable via X-Forwarded-For — gate behind OXICLOUD_TRUST_PROXY_HEADERS
- V-15: Cookie Secure flag off by default — default to true (safe-by-default)
- V-16: LIKE wildcard injection in searches — add like_escape() helper across 9 sites
This commit is contained in:
Dionisio
2026-03-05 14:52:11 +01:00
parent b503e08384
commit 33cfb0faef
14 changed files with 265 additions and 58 deletions
@@ -731,7 +731,16 @@ impl AuthApplicationService {
));
}
let hash = self.password_hasher.hash_password(new_password).await?;
self.user_storage.change_password(user_id, &hash).await
self.user_storage.change_password(user_id, &hash).await?;
// Invalidate all existing sessions so the user must re-login
// with the new password. Mirrors the behaviour of change_password().
self.session_storage
.revoke_all_user_sessions(user_id)
.await?;
tracing::info!(user_id = %user_id, "Admin reset password — all sessions revoked");
Ok(())
}
/// Get a single user by ID (for admin panel)