fix: return unsupported for email and kdf flows

This commit is contained in:
shuaiplus
2026-07-06 01:35:12 +08:00
parent 1bad32fd90
commit cde4555add
6 changed files with 91 additions and 8 deletions
+22 -4
View File
@@ -35,6 +35,8 @@ import {
} from './sends-shared'; } from './sends-shared';
import { auditRequestMetadata, writeAuditEvent } from '../services/audit-events'; import { auditRequestMetadata, writeAuditEvent } from '../services/audit-events';
const SEND_EMAIL_AUTH_UNSUPPORTED_MESSAGE = 'Send email verification is not supported by this server.';
async function writeSendAudit( async function writeSendAudit(
storage: StorageService, storage: StorageService,
request: Request, request: Request,
@@ -216,11 +218,17 @@ export async function handleCreateSend(request: Request, env: Env, userId: strin
if (authTypeRaw.present && requestedAuthType === null) { if (authTypeRaw.present && requestedAuthType === null) {
return errorResponse('Invalid authType', 400); return errorResponse('Invalid authType', 400);
} }
if (requestedAuthType === SendAuthType.Email) {
return errorResponse(SEND_EMAIL_AUTH_UNSUPPORTED_MESSAGE, 501);
}
const normalizedEmails = normalizeEmails(emailsRaw.value); const normalizedEmails = normalizeEmails(emailsRaw.value);
if (emailsRaw.present && emailsRaw.value !== null && normalizedEmails === null) { if (emailsRaw.present && emailsRaw.value !== null && normalizedEmails === null) {
return errorResponse('Invalid emails', 400); return errorResponse('Invalid emails', 400);
} }
if (normalizedEmails) {
return errorResponse(SEND_EMAIL_AUTH_UNSUPPORTED_MESSAGE, 501);
}
const now = new Date().toISOString(); const now = new Date().toISOString();
const send: Send = { const send: Send = {
@@ -340,11 +348,17 @@ export async function handleCreateFileSendV2(request: Request, env: Env, userId:
if (authTypeRaw.present && requestedAuthType === null) { if (authTypeRaw.present && requestedAuthType === null) {
return errorResponse('Invalid authType', 400); return errorResponse('Invalid authType', 400);
} }
if (requestedAuthType === SendAuthType.Email) {
return errorResponse(SEND_EMAIL_AUTH_UNSUPPORTED_MESSAGE, 501);
}
const normalizedEmails = normalizeEmails(emailsRaw.value); const normalizedEmails = normalizeEmails(emailsRaw.value);
if (emailsRaw.present && emailsRaw.value !== null && normalizedEmails === null) { if (emailsRaw.present && emailsRaw.value !== null && normalizedEmails === null) {
return errorResponse('Invalid emails', 400); return errorResponse('Invalid emails', 400);
} }
if (normalizedEmails) {
return errorResponse(SEND_EMAIL_AUTH_UNSUPPORTED_MESSAGE, 501);
}
const now = new Date().toISOString(); const now = new Date().toISOString();
const send: Send = { const send: Send = {
@@ -598,10 +612,11 @@ export async function handleUpdateSend(request: Request, env: Env, userId: strin
if (parsedAuthType === null) { if (parsedAuthType === null) {
return errorResponse('Invalid authType', 400); return errorResponse('Invalid authType', 400);
} }
send.authType = parsedAuthType; if (parsedAuthType === SendAuthType.Email) {
if (parsedAuthType !== SendAuthType.Email) { return errorResponse(SEND_EMAIL_AUTH_UNSUPPORTED_MESSAGE, 501);
send.emails = null;
} }
send.authType = parsedAuthType;
send.emails = null;
} }
const emailsRaw = getAliasedProp(body, ['emails', 'Emails']); const emailsRaw = getAliasedProp(body, ['emails', 'Emails']);
@@ -610,10 +625,13 @@ export async function handleUpdateSend(request: Request, env: Env, userId: strin
if (emailsRaw.value !== null && normalizedEmails === null) { if (emailsRaw.value !== null && normalizedEmails === null) {
return errorResponse('Invalid emails', 400); return errorResponse('Invalid emails', 400);
} }
if (normalizedEmails) {
return errorResponse(SEND_EMAIL_AUTH_UNSUPPORTED_MESSAGE, 501);
}
send.emails = normalizedEmails; send.emails = normalizedEmails;
if (send.emails) { if (send.emails) {
send.authType = SendAuthType.Email; send.authType = SendAuthType.Email;
} else if (send.authType === SendAuthType.Email) { } else if (Number(send.authType) === SendAuthType.Email) {
send.authType = SendAuthType.None; send.authType = SendAuthType.None;
} }
} }
+1 -1
View File
@@ -368,7 +368,7 @@ export async function issueSendAccessToken(
Object: 'error', Object: 'error',
}, },
}, },
400 501
), ),
}; };
} }
+5 -1
View File
@@ -464,7 +464,11 @@ export function sendPasswordLockedOAuthResponse(retryAfterSeconds: number): Resp
export async function validatePublicSendAccess(send: Send, body: unknown): Promise<PublicSendAccessValidationResult> { export async function validatePublicSendAccess(send: Send, body: unknown): Promise<PublicSendAccessValidationResult> {
if (hasEmailAuth(send)) { if (hasEmailAuth(send)) {
return { ok: false, response: errorResponse(SEND_INACCESSIBLE_MSG, 404), reason: 'email_auth_unsupported' }; return {
ok: false,
response: errorResponse('Send email verification is not supported by this server.', 501),
reason: 'email_auth_unsupported',
};
} }
if (!send.passwordHash) return { ok: true }; if (!send.passwordHash) return { ok: true };
+35 -1
View File
@@ -1,5 +1,5 @@
import type { Env, User } from './types'; import type { Env, User } from './types';
import { errorResponse, jsonResponse } from './utils/response'; import { errorResponse, jsonResponse, unsupportedResponse } from './utils/response';
import { import {
handleGetProfile, handleGetProfile,
handleUpdateProfile, handleUpdateProfile,
@@ -116,6 +116,40 @@ export async function handleAuthenticatedRoute(
} }
} }
if ((path === '/api/accounts/kdf' || path === '/accounts/kdf') && (method === 'POST' || method === 'PUT')) {
return unsupportedResponse('KDF changes are not supported by this server.');
}
const mailBackedAccountPaths = new Set([
'/api/accounts/email-token',
'/accounts/email-token',
'/api/accounts/verify-email',
'/accounts/verify-email',
'/api/accounts/verify-email-token',
'/accounts/verify-email-token',
'/api/accounts/request-otp',
'/accounts/request-otp',
'/api/accounts/verify-otp',
'/accounts/verify-otp',
]);
if (mailBackedAccountPaths.has(path) && (method === 'POST' || method === 'PUT')) {
return unsupportedResponse('Email delivery is not supported by this server.');
}
const emailTwoFactorPaths = new Set([
'/api/two-factor/get-email',
'/two-factor/get-email',
'/api/two-factor/send-email',
'/two-factor/send-email',
'/api/two-factor/send-email-login',
'/two-factor/send-email-login',
'/api/two-factor/email',
'/two-factor/email',
]);
if (emailTwoFactorPaths.has(path) && (method === 'POST' || method === 'PUT' || method === 'DELETE')) {
return unsupportedResponse('Email two-step login is not supported by this server.');
}
if (path === '/api/accounts/profile') { if (path === '/api/accounts/profile') {
if (method === 'GET') return handleGetProfile(request, env, userId); if (method === 'GET') return handleGetProfile(request, env, userId);
if (method === 'PUT') return handleUpdateProfile(request, env, userId); if (method === 'PUT') return handleUpdateProfile(request, env, userId);
+24 -1
View File
@@ -28,7 +28,7 @@ import {
} from './handlers/notifications'; } from './handlers/notifications';
import { handlePublicUploadSendFile } from './handlers/sends'; import { handlePublicUploadSendFile } from './handlers/sends';
import { isSafeWebsiteIconContentType } from './utils/content-type'; import { isSafeWebsiteIconContentType } from './utils/content-type';
import { jsonResponse } from './utils/response'; import { jsonResponse, unsupportedResponse } from './utils/response';
import { StorageService } from './services/storage'; import { StorageService } from './services/storage';
import type { Env } from './types'; import type { Env } from './types';
@@ -470,6 +470,29 @@ export async function handlePublicRoute(
return handleRecoverTwoFactor(request, env); return handleRecoverTwoFactor(request, env);
} }
const publicMailBackedPaths = new Set([
'/api/accounts/resend-new-device-otp',
'/accounts/resend-new-device-otp',
'/api/accounts/register/send-verification-email',
'/accounts/register/send-verification-email',
'/identity/accounts/register/send-verification-email',
'/api/accounts/register/verification-email-clicked',
'/accounts/register/verification-email-clicked',
'/identity/accounts/register/verification-email-clicked',
'/api/accounts/register/finish',
'/accounts/register/finish',
'/identity/accounts/register/finish',
'/api/accounts/verify-email-token',
'/accounts/verify-email-token',
'/api/two-factor/send-email-login',
'/two-factor/send-email-login',
]);
if (publicMailBackedPaths.has(path) && method === 'POST') {
const blocked = await enforcePublicRateLimit('public-sensitive', LIMITS.rateLimit.sensitivePublicRequestsPerMinute);
if (blocked) return blocked;
return unsupportedResponse('Email delivery is not supported by this server.');
}
if (path === '/api/accounts/password-hint' && method === 'POST') { if (path === '/api/accounts/password-hint' && method === 'POST') {
const blocked = await enforcePublicRateLimit('public-sensitive', LIMITS.rateLimit.sensitivePublicRequestsPerMinute); const blocked = await enforcePublicRateLimit('public-sensitive', LIMITS.rateLimit.sensitivePublicRequestsPerMinute);
if (blocked) return blocked; if (blocked) return blocked;
+4
View File
@@ -136,6 +136,10 @@ export function errorResponse(message: string, status: number = 400): Response {
); );
} }
export function unsupportedResponse(message: string = 'This feature is not supported by this server.'): Response {
return errorResponse(message, 501);
}
// Identity endpoint error response (for /identity/connect/token) // Identity endpoint error response (for /identity/connect/token)
export function identityErrorResponse(message: string, error: string = 'invalid_grant', status: number = 400): Response { export function identityErrorResponse(message: string, error: string = 'invalid_grant', status: number = 400): Response {
return jsonResponse( return jsonResponse(