[PM-32424] Send Access Enumeration protection (#19422)

* feat: remove reference to otp_invalid response since it is not used anymore

* remove usage of otpInvalid in CLI receive command

* fix: remove vestigial error types.

* chore: update sdk

* chore: fix failing test

---------

Co-authored-by: John Harrington <84741727+harr1424@users.noreply.github.com>
This commit is contained in:
Ike 2026-03-11 11:37:07 -04:00 committed by GitHub
parent 5707b0064c
commit c8c66a8bf1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 10 additions and 48 deletions

View File

@ -10,7 +10,6 @@ import {
SendAccessToken,
emailRequired,
emailAndOtpRequired,
otpInvalid,
passwordHashB64Required,
passwordHashB64Invalid,
sendIdInvalid,
@ -331,18 +330,6 @@ export class SendReceiveCommand extends DownloadCommand {
if (otpResponse.kind === "expected_server") {
const error = otpResponse.error;
if (otpInvalid(error)) {
return Response.badRequest("Invalid email or verification code");
}
/*
If the following evaluates to true, it means that the email address provided was not
configured to be used for email OTP for this Send.
To avoid leaking information that would allow email enumeration, instead return an
error indicating that some component of the email OTP challenge was invalid.
*/
if (emailAndOtpRequired(error)) {
return Response.badRequest("Invalid email or verification code");
}

View File

@ -7,7 +7,6 @@ import { firstValueFrom } from "rxjs";
import {
emailAndOtpRequired,
emailRequired,
otpInvalid,
passwordHashB64Invalid,
passwordHashB64Required,
SendAccessDomainCredentials,
@ -205,12 +204,6 @@ export class SendAuthComponent implements OnInit {
}
this.otpSubmitted = true;
this.updatePageTitle();
} else if (otpInvalid(response.error)) {
this.toastService.showToast({
variant: "error",
title: this.i18nService.t("errorOccurred"),
message: this.i18nService.t("invalidEmailOrVerificationCode"),
});
} else if (passwordHashB64Required(response.error)) {
this.sendAuthType.set(AuthType.Password);
this.updatePageTitle();

View File

@ -71,8 +71,6 @@ describe("SendTokenService", () => {
const INVALID_GRANT_CODES: SendAccessTokenInvalidGrantError[] = [
"send_id_invalid",
"password_hash_b64_invalid",
"otp_invalid",
"otp_generation_failed",
"unknown",
];

View File

@ -31,20 +31,6 @@ export function passwordHashB64Invalid(
return e.error === "invalid_grant" && e.send_access_error_type === "password_hash_b64_invalid";
}
export type OtpInvalid = InvalidGrant & {
send_access_error_type: "otp_invalid";
};
export function otpInvalid(e: SendAccessTokenApiErrorResponse): e is OtpInvalid {
return e.error === "invalid_grant" && e.send_access_error_type === "otp_invalid";
}
export type OtpGenerationFailed = InvalidGrant & {
send_access_error_type: "otp_generation_failed";
};
export function otpGenerationFailed(e: SendAccessTokenApiErrorResponse): e is OtpGenerationFailed {
return e.error === "invalid_grant" && e.send_access_error_type === "otp_generation_failed";
}
export type UnknownInvalidGrant = InvalidGrant & {
send_access_error_type: "unknown";
};

18
package-lock.json generated
View File

@ -23,8 +23,8 @@
"@angular/platform-browser": "20.3.17",
"@angular/platform-browser-dynamic": "20.3.17",
"@angular/router": "20.3.17",
"@bitwarden/commercial-sdk-internal": "0.2.0-main.589",
"@bitwarden/sdk-internal": "0.2.0-main.589",
"@bitwarden/commercial-sdk-internal": "0.2.0-main.590",
"@bitwarden/sdk-internal": "0.2.0-main.590",
"@electron/fuses": "1.8.0",
"@emotion/css": "11.13.5",
"@koa/multer": "4.0.0",
@ -4946,10 +4946,9 @@
"link": true
},
"node_modules/@bitwarden/commercial-sdk-internal": {
"version": "0.2.0-main.589",
"resolved": "https://registry.npmjs.org/@bitwarden/commercial-sdk-internal/-/commercial-sdk-internal-0.2.0-main.589.tgz",
"integrity": "sha512-+4qZ0gj71jOFepD0hIwhcuM/Eegf+JP1IbQmYA5YIA1Q5TBpms6sULcQZRTkJEokH8PiGH5xxvUk4k/XQAL2tQ==",
"license": "BITWARDEN SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT",
"version": "0.2.0-main.590",
"resolved": "https://registry.npmjs.org/@bitwarden/commercial-sdk-internal/-/commercial-sdk-internal-0.2.0-main.590.tgz",
"integrity": "sha512-rihF/X2s6eYu2HhOOZAyfnqzTa+qsK16xdg7fjwMJKGD314BjfYHE3OdgnWmDkys0/oNSOi7XIJBbtZ4MnyIww==",
"dependencies": {
"type-fest": "^5.0.0"
}
@ -5054,10 +5053,9 @@
"link": true
},
"node_modules/@bitwarden/sdk-internal": {
"version": "0.2.0-main.589",
"resolved": "https://registry.npmjs.org/@bitwarden/sdk-internal/-/sdk-internal-0.2.0-main.589.tgz",
"integrity": "sha512-PDygPFmu+t/GHHLZjKjWOnpFjck4pYRZArB4ZBuyh7rwWK1tX5brBWtZu38+pJPVTiBHy1D1TUwIHbWfeiS0Uw==",
"license": "GPL-3.0",
"version": "0.2.0-main.590",
"resolved": "https://registry.npmjs.org/@bitwarden/sdk-internal/-/sdk-internal-0.2.0-main.590.tgz",
"integrity": "sha512-tcgbjlir4sHRU5L2c4TgA9H8iRgxpWVRBqoseOzjQFbsDVeIhrEn5/b2AnbCDdQeFAQp+QeOyokN53nS/34eUw==",
"dependencies": {
"type-fest": "^5.0.0"
}

View File

@ -165,8 +165,8 @@
"@angular/platform-browser": "20.3.17",
"@angular/platform-browser-dynamic": "20.3.17",
"@angular/router": "20.3.17",
"@bitwarden/commercial-sdk-internal": "0.2.0-main.589",
"@bitwarden/sdk-internal": "0.2.0-main.589",
"@bitwarden/commercial-sdk-internal": "0.2.0-main.590",
"@bitwarden/sdk-internal": "0.2.0-main.590",
"@electron/fuses": "1.8.0",
"@emotion/css": "11.13.5",
"@koa/multer": "4.0.0",