fix(manager-core): F-S-003 require authenticated principal for users::find_by_email
find_by_email gated on AppUsersRead via `require`, which short-circuits when cx.principal == None. An anonymous public-HTTP script could iterate emails to enumerate registered users, then pivot to login or request_password_reset. Tighten: explicitly return Forbidden when cx.principal is None — scripts that need a "does this email exist" probe from a public route must wrap the call in their own auth gate. AUDIT.md anchor: F-S-003. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -496,6 +496,14 @@ impl UsersService for UsersServiceImpl {
|
||||
cx: &SdkCallCx,
|
||||
email: &str,
|
||||
) -> Result<Option<AppUser>, UsersError> {
|
||||
// F-S-003: an anonymous public-HTTP script could iterate emails
|
||||
// via find_by_email to enumerate registered users (the `require`
|
||||
// helper short-circuits on principal == None). Tighten: require
|
||||
// an authenticated principal — scripts that need a "does this
|
||||
// email exist?" probe must wrap it in their own auth gate.
|
||||
if cx.principal.is_none() {
|
||||
return Err(UsersError::Forbidden);
|
||||
}
|
||||
self.require(cx.principal.as_ref(), Capability::AppUsersRead(cx.app_id))
|
||||
.await?;
|
||||
let normalized = validate_email(email)?;
|
||||
|
||||
Reference in New Issue
Block a user