Skip to content

Conversation

@cardoso
Copy link
Member

@cardoso cardoso commented Oct 28, 2025

Proposed changes (including videos or screenshots)

Issue(s)

https://rocketchat.atlassian.net/browse/ESH-43

Steps to test or reproduce

Further comments

Summary by CodeRabbit

  • New Features

    • Added Change and Reset passphrase screens enforcing strong (30+ char, mixed) passphrases, with inline verifier list, contextual hints, and success/error toasts.
  • UI

    • Password verifier updated for clearer success/error labeling and improved accessibility.
  • Refactor

    • Simplified end-to-end encryption settings by splitting change/reset flows and centralizing validation.
  • Tests

    • E2E test updated to use a 30-character compliant passphrase.

@cardoso cardoso added this to the 7.13.0 milestone Oct 28, 2025
@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Oct 28, 2025

Looks like this PR is ready to merge! 🎉
If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Oct 28, 2025

🦋 Changeset detected

Latest commit: 612a1a4

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 42 packages
Name Type
@rocket.chat/meteor Minor
@rocket.chat/password-policies Minor
@rocket.chat/ui-client Major
@rocket.chat/ui-contexts Major
@rocket.chat/gazzodown Major
@rocket.chat/ui-voip Major
@rocket.chat/web-ui-registration Major
@rocket.chat/uikit-playground Patch
@rocket.chat/fuselage-ui-kit Major
@rocket.chat/livechat Patch
@rocket.chat/mock-providers Patch
@rocket.chat/ui-avatar Major
@rocket.chat/ui-video-conf Major
@rocket.chat/core-typings Minor
@rocket.chat/rest-typings Minor
@rocket.chat/api-client Patch
@rocket.chat/apps Patch
@rocket.chat/core-services Patch
@rocket.chat/cron Patch
@rocket.chat/ddp-client Patch
@rocket.chat/freeswitch Patch
@rocket.chat/http-router Patch
@rocket.chat/model-typings Patch
@rocket.chat/account-service Patch
@rocket.chat/authorization-service Patch
@rocket.chat/ddp-streamer Patch
@rocket.chat/omnichannel-transcript Patch
@rocket.chat/presence-service Patch
@rocket.chat/queue-worker Patch
@rocket.chat/stream-hub-service Patch
@rocket.chat/federation-matrix Patch
@rocket.chat/license Patch
@rocket.chat/media-calls Patch
@rocket.chat/omnichannel-services Patch
@rocket.chat/pdf-worker Patch
@rocket.chat/presence Patch
rocketchat-services Patch
@rocket.chat/models Patch
@rocket.chat/network-broker Patch
@rocket.chat/omni-core-ee Patch
@rocket.chat/instance-status Patch
@rocket.chat/omni-core Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 28, 2025

Walkthrough

Extracts E2EE passphrase UI into two components (ChangePassphrase, ResetPassphrase), enforces a 30+ char strong-passphrase policy with validation, adds typed password-policy scaffolding and a usePasswordPolicy hook, moves password verification UI into PasswordVerifierList/PasswordVerifierItem, refactors verification hooks, and updates an E2EE test to generate a 30‑char structured password.

Changes

Cohort / File(s) Summary
E2EE Security Components
apps/meteor/client/views/account/security/ChangePassphrase.tsx, apps/meteor/client/views/account/security/EndToEnd.tsx, apps/meteor/client/views/account/security/ResetPassphrase.tsx
Add ChangePassphrase and ResetPassphrase; simplify EndToEnd to compose those components and a divider. ChangePassphrase implements a 30+ char strong-passphrase form with react-hook-form, policy validation, PasswordVerifierList integration, DOMPurify-rendered explanation, and e2e.changePassword mutation with toast feedback.
Password Policy Types
packages/password-policies/src/PasswordPolicy.ts, packages/password-policies/src/index.ts
Add TypeScript scaffolding and new public types (PasswordPolicyOptions, PasswordPolicyValidation); generalize policy typing, change sendValidationMessage/getPasswordPolicy signatures, and export new types.
Password Policy Hooks
packages/ui-contexts/src/hooks/usePasswordPolicy.ts, packages/ui-contexts/src/hooks/useVerifyPassword.ts, packages/ui-contexts/src/index.ts
Add usePasswordPolicy hook returning validations and valid flag; refactor useVerifyPassword to use it and return the new shape; re-export hook/types from contexts index.
Password Verification UI
packages/ui-client/src/components/PasswordVerifier/PasswordVerifier.tsx, packages/ui-client/src/components/PasswordVerifier/PasswordVerifierList.tsx, packages/ui-client/src/components/PasswordVerifier/PasswordVerifierItem.tsx, packages/ui-client/src/components/index.ts
Add PasswordVerifierList and re-export; make PasswordVerifier delegate to it; update PasswordVerifierItem to accept PasswordPolicyValidation, generate accessible IDs, use translated labels and getIconProps, and adjust layout/ARIA semantics.
Validation/Utility Hooks
packages/ui-client/src/hooks/useValidatePassword.ts
Consume useVerifyPassword return shape and read .valid instead of recomputing validity; remove unnecessary memoization.
E2EE Tests
apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts
Update test to generate a 30-character password with required composition (lowercase, uppercase, digit, symbol) instead of a UUID-based password.
Misc / Changeset
.changeset/beige-experts-applaud.md
New changeset bumping minor versions and documenting the passphrase complexity requirement change.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ChangePassphrase
    participant PasswordVerifierList
    participant E2EE_API
    Note right of PasswordVerifierList `#D7F9E0`: validations from usePasswordPolicy

    User->>ChangePassphrase: Type new passphrase
    ChangePassphrase->>PasswordVerifierList: Request validations
    PasswordVerifierList-->>ChangePassphrase: Return validations

    alt all validations valid
        User->>ChangePassphrase: Submit
        ChangePassphrase->>E2EE_API: e2e.changePassword(mutation)
        E2EE_API-->>ChangePassphrase: Success
        ChangePassphrase->>User: Success toast + reset form
    else validations fail
        ChangePassphrase->>User: Show requirement failures
    end
Loading
sequenceDiagram
    participant User
    participant EndToEnd
    participant ChangePassphrase
    participant ResetPassphrase
    participant E2EE_API

    User->>EndToEnd: Open E2E settings
    EndToEnd->>ChangePassphrase: Render
    EndToEnd->>ResetPassphrase: Render

    alt Change passphrase flow
        User->>ChangePassphrase: Input & submit
        ChangePassphrase->>E2EE_API: e2e.changePassword
        E2EE_API-->>ChangePassphrase: Result
        ChangePassphrase-->>User: Feedback
    else Reset passphrase flow
        User->>ResetPassphrase: Click reset
        ResetPassphrase->>E2EE_API: trigger reset mutation
        ResetPassphrase-->>User: Feedback
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25–35 minutes

  • Pay extra attention to:
    • apps/meteor/client/views/account/security/ChangePassphrase.tsx — form validation rules, Controller usage, DOMPurify rendering, mutation side effects and toast/reset behavior.
    • packages/password-policies/src/PasswordPolicy.ts — new public types and changed method return shapes.
    • Hook interplay and memoization in usePasswordPolicy / useVerifyPassword.
    • Accessibility and translation changes in PasswordVerifierList / PasswordVerifierItem.
    • Tests updating to ensure generated password meets the new policy.

Suggested labels

stat: QA assured

Poem

🐇 I hopped through code with careful cheer,
I stitched new rules for passphrases here.
Lists of checks in tidy rows,
A safer key where secret grows.
🥕✨

Pre-merge checks and finishing touches

✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(e2ee): passphrase requirements' accurately summarizes the main change: adding complexity requirements to end-to-end encryption passphrases.
Linked Issues check ✅ Passed The PR implements all core requirements from ESH-43: user-provided passwords require 30+ chars with uppercase, lowercase, number, and symbol; strong password validation enforced; complexity requirements integrated into passphrase change UI.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing password complexity requirements: new components (ChangePassphrase, ResetPassphrase), password policy type enhancements, verifier UI updates, and hook refactoring—no unrelated modifications detected.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/ESH-43

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 578a672 and 612a1a4.

📒 Files selected for processing (1)
  • .changeset/beige-experts-applaud.md (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, the team has decided to use Latin-1 encoding (via Binary.toArrayBuffer and Binary.toString) for password encoding and decrypt output instead of UTF-8 encoding. This is a deliberate choice for E2EE password/key material handling.
📚 Learning: 2025-10-16T21:09:51.816Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/keychain.ts:148-156
Timestamp: 2025-10-16T21:09:51.816Z
Learning: In the RocketChat/Rocket.Chat repository, only platforms with native crypto.randomUUID() support are targeted, so fallback implementations for crypto.randomUUID() are not required in E2EE or cryptographic code.

Applied to files:

  • .changeset/beige-experts-applaud.md
📚 Learning: 2025-10-07T15:08:37.419Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, the team has decided to use Latin-1 encoding (via Binary.toArrayBuffer and Binary.toString) for password encoding and decrypt output instead of UTF-8 encoding. This is a deliberate choice for E2EE password/key material handling.

Applied to files:

  • .changeset/beige-experts-applaud.md
📚 Learning: 2025-10-07T15:08:37.419Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, PBKDF2 iteration count validation is not enforced because the iterations parameter is outside the user's control and is system-managed.

Applied to files:

  • .changeset/beige-experts-applaud.md
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (1)
.changeset/beige-experts-applaud.md (1)

1-8: Changeset structure and version bumps look good.

The changeset correctly documents all affected packages—@rocket.chat/meteor, @rocket.chat/password-policies, @rocket.chat/ui-client, and @rocket.chat/ui-contexts—with appropriate minor version bumps (additive, backward-compatible features). The description accurately reflects the PR objective of adding E2EE passphrase complexity requirements.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Oct 28, 2025

Codecov Report

❌ Patch coverage is 85.27132% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.02%. Comparing base (6e128f3) to head (612a1a4).
⚠️ Report is 1 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #37327      +/-   ##
===========================================
+ Coverage    66.94%   67.02%   +0.08%     
===========================================
  Files         3415     3418       +3     
  Lines       117705   117751      +46     
  Branches     21515    21533      +18     
===========================================
+ Hits         78801    78928     +127     
+ Misses       36227    36141      -86     
- Partials      2677     2682       +5     
Flag Coverage Δ
e2e 57.47% <87.87%> (+0.01%) ⬆️
unit 72.15% <82.53%> (+0.11%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cardoso cardoso marked this pull request as ready for review November 3, 2025 12:04
@cardoso cardoso requested a review from a team as a code owner November 3, 2025 12:04
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
apps/meteor/client/views/account/security/ResetPassphrase.tsx (1)

17-19: Consider adding loading state and disabling the button during mutation.

The button can be clicked multiple times while the mutation is in progress, potentially triggering multiple concurrent reset operations.

Apply this diff to disable the button during mutation and show loading state:

-		<Button onClick={() => resetE2EPassword.mutate()} data-qa-type='e2e-encryption-reset-key-button'>
+		<Button 
+			onClick={() => resetE2EPassword.mutate()} 
+			disabled={resetE2EPassword.isPending}
+			loading={resetE2EPassword.isPending}
+			data-qa-type='e2e-encryption-reset-key-button'
+		>
 			{t('Reset_E2EE_password')}
 		</Button>
packages/ui-contexts/src/hooks/useVerifyPassword.ts (1)

18-29: Memoize the policy options to avoid unnecessary re-instantiation

Because we build a fresh object literal on every render, usePasswordPolicy ends up creating a brand-new PasswordPolicy instance each time settings or the password param rerender. Wrapping the options in useMemo keeps the policy stable and saves some churn, especially when this hook is called in high-frequency inputs.

-const validate = usePasswordPolicy({
-	enabled,
-	minLength,
-	maxLength,
-	forbidRepeatingCharacters,
-	forbidRepeatingCharactersCount,
-	mustContainAtLeastOneLowercase,
-	mustContainAtLeastOneUppercase,
-	mustContainAtLeastOneNumber,
-	mustContainAtLeastOneSpecialCharacter,
-	throwError: false,
-});
+const options = useMemo(
+	() => ({
+		enabled,
+		minLength,
+		maxLength,
+		forbidRepeatingCharacters,
+		forbidRepeatingCharactersCount,
+		mustContainAtLeastOneLowercase,
+		mustContainAtLeastOneUppercase,
+		mustContainAtLeastOneNumber,
+		mustContainAtLeastOneSpecialCharacter,
+		throwError: false,
+	}),
+	[
+		enabled,
+		minLength,
+		maxLength,
+		forbidRepeatingCharacters,
+		forbidRepeatingCharactersCount,
+		mustContainAtLeastOneLowercase,
+		mustContainAtLeastOneUppercase,
+		mustContainAtLeastOneNumber,
+		mustContainAtLeastOneSpecialCharacter,
+	],
+);
+
+const validate = usePasswordPolicy(options);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9a18288 and cb5572a.

📒 Files selected for processing (12)
  • apps/meteor/client/views/account/security/ChangePassphrase.tsx (1 hunks)
  • apps/meteor/client/views/account/security/EndToEnd.tsx (1 hunks)
  • apps/meteor/client/views/account/security/ResetPassphrase.tsx (1 hunks)
  • apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts (1 hunks)
  • packages/password-policies/src/PasswordPolicy.ts (3 hunks)
  • packages/password-policies/src/index.ts (1 hunks)
  • packages/ui-client/src/components/PasswordVerifier/PasswordVerifier.tsx (1 hunks)
  • packages/ui-client/src/components/PasswordVerifier/PasswordVerifierList.tsx (1 hunks)
  • packages/ui-client/src/components/index.ts (1 hunks)
  • packages/ui-contexts/src/hooks/usePasswordPolicy.ts (1 hunks)
  • packages/ui-contexts/src/hooks/useVerifyPassword.ts (2 hunks)
  • packages/ui-contexts/src/index.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
apps/meteor/tests/e2e/**/*.spec.ts

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

apps/meteor/tests/e2e/**/*.spec.ts: All Playwright test files must be located under apps/meteor/tests/e2e/ and use the .spec.ts extension (e.g., login.spec.ts)
Use descriptive test names that clearly communicate expected behavior
Use test.beforeAll() and test.afterAll() for setup and teardown
Use test.step() to organize complex test scenarios
Group related tests in the same file
Utilize Playwright fixtures (test, page, expect) consistently
Prefer web-first assertions (e.g., toBeVisible, toHaveText)
Use expect matchers (toEqual, toContain, toBeTruthy, toHaveLength, etc.) instead of assert statements
Maintain test isolation between test cases
Ensure a clean state for each test execution
Ensure tests run reliably in parallel without shared state conflicts

Files:

  • apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts
apps/meteor/tests/e2e/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

apps/meteor/tests/e2e/**/*.{ts,tsx,js,jsx}: Write concise, technical TypeScript/JavaScript with accurate typing
Follow DRY by extracting reusable logic into helper functions or page objects
Avoid code comments in the implementation

Files:

  • apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts
apps/meteor/tests/e2e/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

apps/meteor/tests/e2e/**/*.{ts,tsx}: Avoid using page.locator(); prefer semantic locators like page.getByRole, page.getByLabel, page.getByText, and page.getByTitle
Store commonly used locators in variables/constants for reuse
Use page.waitFor() with specific conditions and avoid hardcoded timeouts
Implement proper wait strategies for dynamic content
Follow the Page Object Model pattern consistently

Files:

  • apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts
🧠 Learnings (12)
📚 Learning: 2025-10-07T15:08:37.419Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, the team has decided to use Latin-1 encoding (via Binary.toArrayBuffer and Binary.toString) for password encoding and decrypt output instead of UTF-8 encoding. This is a deliberate choice for E2EE password/key material handling.

Applied to files:

  • apps/meteor/client/views/account/security/ChangePassphrase.tsx
  • apps/meteor/client/views/account/security/EndToEnd.tsx
  • apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,tsx,js,jsx} : Avoid code comments in the implementation

Applied to files:

  • apps/meteor/client/views/account/security/EndToEnd.tsx
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,tsx,js,jsx} : Write concise, technical TypeScript/JavaScript with accurate typing

Applied to files:

  • apps/meteor/client/views/account/security/EndToEnd.tsx
  • apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use descriptive test names that clearly communicate expected behavior

Applied to files:

  • apps/meteor/client/views/account/security/EndToEnd.tsx
  • apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,tsx,js,jsx} : Follow DRY by extracting reusable logic into helper functions or page objects

Applied to files:

  • apps/meteor/client/views/account/security/EndToEnd.tsx
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases

Applied to files:

  • apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (test, page, expect) consistently

Applied to files:

  • apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use expect matchers (toEqual, toContain, toBeTruthy, toHaveLength, etc.) instead of assert statements

Applied to files:

  • apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure a clean state for each test execution

Applied to files:

  • apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : All Playwright test files must be located under apps/meteor/tests/e2e/ and use the .spec.ts extension (e.g., login.spec.ts)

Applied to files:

  • apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use test.step() to organize complex test scenarios

Applied to files:

  • apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts
🧬 Code graph analysis (7)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (3)
apps/meteor/client/views/room/hooks/useE2EEState.ts (1)
  • useE2EEState (9-9)
packages/ui-contexts/src/hooks/usePasswordPolicy.ts (1)
  • usePasswordPolicy (11-24)
apps/meteor/client/lib/e2ee/rocketchat.e2e.ts (1)
  • e2e (851-851)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierList.tsx (1)
packages/ui-client/src/components/index.ts (1)
  • PasswordVerifierList (6-6)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifier.tsx (2)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierList.tsx (1)
  • PasswordVerifierList (19-50)
packages/ui-client/src/components/index.ts (1)
  • PasswordVerifierList (6-6)
apps/meteor/client/views/account/security/ResetPassphrase.tsx (1)
apps/meteor/client/views/hooks/useResetE2EPasswordMutation.ts (1)
  • useResetE2EPasswordMutation (6-24)
packages/ui-contexts/src/hooks/usePasswordPolicy.ts (1)
packages/ui-contexts/src/index.ts (1)
  • usePasswordPolicy (88-88)
apps/meteor/client/views/account/security/EndToEnd.tsx (2)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (1)
  • ChangePassphrase (46-187)
apps/meteor/client/views/account/security/ResetPassphrase.tsx (1)
  • ResetPassphrase (6-22)
packages/ui-contexts/src/hooks/useVerifyPassword.ts (1)
packages/ui-contexts/src/hooks/usePasswordPolicy.ts (1)
  • usePasswordPolicy (11-24)
🪛 ast-grep (0.39.6)
apps/meteor/client/views/account/security/ChangePassphrase.tsx

[warning] 93-93: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

🪛 Biome (2.1.2)
apps/meteor/client/views/account/security/ChangePassphrase.tsx

[error] 94-94: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🔇 Additional comments (7)
packages/password-policies/src/PasswordPolicy.ts (1)

3-25: LGTM! Clean type extraction.

The introduction of PasswordPolicyOptions and PasswordPolicyValidation as exported types formalizes the previously inline type definitions, improving type safety and reusability across the codebase.

apps/meteor/client/views/account/security/EndToEnd.tsx (1)

1-17: LGTM! Clean refactor.

The extraction of inline form logic into dedicated ChangePassphrase and ResetPassphrase components improves code organization and maintainability. The type signature update to ComponentPropsWithoutRef<typeof Box> is appropriate.

packages/ui-contexts/src/index.ts (1)

88-88: LGTM!

The addition of the usePasswordPolicy export is consistent with other hook exports in this module.

packages/ui-client/src/components/index.ts (1)

6-6: LGTM!

The addition of the PasswordVerifierList export is consistent with other component exports in this module.

packages/password-policies/src/index.ts (1)

1-1: LGTM!

Re-exporting PasswordPolicyOptions and PasswordPolicyValidation from the package entry point enables consumers to import these types directly from @rocket.chat/password-policies, which is good API design.

packages/ui-client/src/components/PasswordVerifier/PasswordVerifier.tsx (1)

11-15: LGTM! Clean separation of concerns.

The refactor properly separates validation computation (via useVerifyPassword) from presentation logic (delegated to PasswordVerifierList), improving code maintainability.

packages/ui-client/src/components/PasswordVerifier/PasswordVerifierList.tsx (1)

19-50: LGTM! Good accessibility implementation.

The component properly handles empty validations and implements good accessibility practices with ARIA attributes (aria-labelledby, aria-invalid, role='list').

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (1)

68-81: Confirmation validator still skips re-run on valid passphrase edits

Editing the primary passphrase to another policy-compliant value leaves valid === true, so this effect never re-runs and the confirmation field keeps its stale value. isValid stays true, the “Save changes” button remains enabled, and only on submit do we surface the mismatch. Please make the effect depend on passphrase (or otherwise re-trigger confirmation validation on any primary passphrase change) so mismatches are caught immediately.

Apply this diff:

-	useEffect(() => {
+	useEffect(() => {
 		if (!valid) {
 			resetField('confirmationPassphrase');
 			return;
 		}
 		if (confirmationPassphrase) {
 			const validateConfirmation = async () => {
 				await trigger('confirmationPassphrase');
 			};
 			void validateConfirmation();
 		}
-	}, [valid, confirmationPassphrase, resetField, trigger]);
+	}, [passphrase, valid, confirmationPassphrase, resetField, trigger]);
🧹 Nitpick comments (2)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierItem.tsx (2)

27-28: Consider adding a fallback for translation keys.

The translation key is constructed dynamically from props.name, but no fallback value is provided to t(). If the translation key doesn't exist, users might see the raw key (e.g., "minLength-label") displayed in the UI.

Consider providing a fallback:

-	const requirementText = t(name, 'limit' in props ? { limit: props.limit } : undefined);
+	const requirementText = t(name, { 
+		...'limit' in props ? { limit: props.limit } : {},
+		defaultValue: props.name 
+	});

Alternatively, ensure all translation keys are present at build time through type-checking or validation.


38-41: Remove redundant aria-hidden='false' attributes.

Setting aria-hidden='false' is unnecessary since elements are not hidden by default. The proper aria labels (aria-labelledby and aria-label) are already in place.

Apply this diff:

 		role='listitem'
-		aria-hidden='false'
 		aria-labelledby={`${id}-icon ${id}-text`}
 	>
-		<Icon id={`${id}-icon`} aria-label={t(icon.label)} aria-hidden='false' name={icon.name} color={icon.color} size='x16' mie={4} />
+		<Icon id={`${id}-icon`} aria-label={t(icon.label)} name={icon.name} color={icon.color} size='x16' mie={4} />
 		<span id={`${id}-text`}>{requirementText}</span>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b72382b and 3540a40.

📒 Files selected for processing (6)
  • apps/meteor/client/views/account/security/ChangePassphrase.tsx (1 hunks)
  • packages/password-policies/src/PasswordPolicy.ts (3 hunks)
  • packages/ui-client/src/components/PasswordVerifier/PasswordVerifier.tsx (1 hunks)
  • packages/ui-client/src/components/PasswordVerifier/PasswordVerifierItem.tsx (1 hunks)
  • packages/ui-client/src/components/PasswordVerifier/PasswordVerifierList.tsx (1 hunks)
  • packages/ui-client/src/components/PasswordVerifier/PasswordVerifiers.spec.tsx (3 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, the team has decided to use Latin-1 encoding (via Binary.toArrayBuffer and Binary.toString) for password encoding and decrypt output instead of UTF-8 encoding. This is a deliberate choice for E2EE password/key material handling.
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use descriptive test names that clearly communicate expected behavior

Applied to files:

  • packages/ui-client/src/components/PasswordVerifier/PasswordVerifiers.spec.tsx
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use expect matchers (toEqual, toContain, toBeTruthy, toHaveLength, etc.) instead of assert statements

Applied to files:

  • packages/ui-client/src/components/PasswordVerifier/PasswordVerifiers.spec.tsx
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Prefer web-first assertions (e.g., toBeVisible, toHaveText)

Applied to files:

  • packages/ui-client/src/components/PasswordVerifier/PasswordVerifiers.spec.tsx
📚 Learning: 2025-09-23T19:22:59.217Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 36987
File: apps/meteor/tests/e2e/page-objects/fragments/room-toolbar.ts:10-20
Timestamp: 2025-09-23T19:22:59.217Z
Learning: In Playwright e2e tests, prefer stable selectors like data-qa-id attributes over localized text in getByRole() or getByText() calls to prevent test failures when UI language changes. Test translations separately by validating actual text content after ensuring UI interactions work with stable selectors.

Applied to files:

  • packages/ui-client/src/components/PasswordVerifier/PasswordVerifiers.spec.tsx
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,tsx} : Use page.waitFor() with specific conditions and avoid hardcoded timeouts

Applied to files:

  • packages/ui-client/src/components/PasswordVerifier/PasswordVerifiers.spec.tsx
📚 Learning: 2025-10-07T15:08:37.419Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, the team has decided to use Latin-1 encoding (via Binary.toArrayBuffer and Binary.toString) for password encoding and decrypt output instead of UTF-8 encoding. This is a deliberate choice for E2EE password/key material handling.

Applied to files:

  • apps/meteor/client/views/account/security/ChangePassphrase.tsx
🧬 Code graph analysis (5)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifier.tsx (2)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierList.tsx (2)
  • PasswordVerifierListProps (8-12)
  • PasswordVerifierList (14-39)
packages/ui-contexts/src/hooks/useVerifyPassword.ts (1)
  • useVerifyPassword (6-31)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierList.tsx (2)
packages/password-policies/src/PasswordPolicy.ts (1)
  • PasswordPolicyValidation (35-39)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierItem.tsx (1)
  • PasswordVerifierItem (23-45)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierItem.tsx (1)
packages/password-policies/src/PasswordPolicy.ts (1)
  • PasswordPolicyValidation (35-39)
packages/password-policies/src/PasswordPolicy.ts (2)
packages/password-policies/src/index.ts (2)
  • PasswordPolicyOptions (1-1)
  • PasswordPolicyValidation (1-1)
packages/ui-contexts/src/hooks/usePasswordPolicy.ts (1)
  • PasswordPolicyValidation (4-4)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (5)
apps/meteor/client/views/room/hooks/useE2EEState.ts (1)
  • useE2EEState (9-9)
packages/password-policies/src/PasswordPolicy.ts (2)
  • validate (179-247)
  • error (102-115)
packages/ui-contexts/src/hooks/usePasswordPolicy.ts (1)
  • usePasswordPolicy (15-28)
apps/meteor/client/lib/e2ee/rocketchat.e2e.ts (1)
  • e2e (851-851)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierList.tsx (1)
  • PasswordVerifierList (14-39)
🪛 ast-grep (0.39.7)
apps/meteor/client/views/account/security/ChangePassphrase.tsx

[warning] 101-101: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

🪛 Biome (2.1.2)
apps/meteor/client/views/account/security/ChangePassphrase.tsx

[error] 102-102: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (1)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierItem.tsx (1)

2-2: ****

The import of PasswordPolicyValidation from @rocket.chat/ui-contexts is correct. The type is properly re-exported through the ui-contexts package: it originates in packages/password-policies/src/PasswordPolicy.ts, is re-exported from packages/password-policies/src/index.ts, then through packages/ui-contexts/src/hooks/usePasswordPolicy.ts, and finally exposed at packages/ui-contexts/src/index.ts (line 88). Using @rocket.chat/ui-contexts as the import source follows the intended public API boundary—no changes are needed.

Likely an incorrect or invalid review comment.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/password-policies/src/PasswordPolicy.ts (1)

249-249: Avoid widening the return type — use the specific PasswordPolicyParametersEntry union.

The explicit generic <[name: string, params?: Record<string, number | boolean>]> permits any string as a policy name and any object as params, which discards the type safety provided by PasswordPolicyParametersEntry. Consumers lose IDE autocomplete for policy names and cannot narrow types to specific policies.

Apply this diff to use the default (or explicit specific) type parameter:

-	getPasswordPolicy(): PasswordPolicyType<[name: string, params?: Record<string, number | boolean>]> {
+	getPasswordPolicy(): PasswordPolicyType {

Alternatively, if you prefer being explicit:

-	getPasswordPolicy(): PasswordPolicyType<[name: string, params?: Record<string, number | boolean>]> {
+	getPasswordPolicy(): PasswordPolicyType<PasswordPolicyParametersEntry> {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3540a40 and 71bce62.

📒 Files selected for processing (1)
  • packages/password-policies/src/PasswordPolicy.ts (4 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, the team has decided to use Latin-1 encoding (via Binary.toArrayBuffer and Binary.toString) for password encoding and decrypt output instead of UTF-8 encoding. This is a deliberate choice for E2EE password/key material handling.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (1)
packages/password-policies/src/PasswordPolicy.ts (1)

3-40: Well-structured type definitions.

The type system correctly uses mapped types, conditional types, and template literal types to create a strongly-typed password policy API. The discriminated union in PasswordPolicyParametersEntry (lines 17-21) appropriately handles the difference between number-based policies (which include a params object) and boolean-based policies (which don't).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierItem.tsx (1)

38-38: Remove redundant aria-hidden='false' attributes.

Elements are not aria-hidden by default, so explicitly setting aria-hidden='false' is unnecessary. You can safely remove these attributes without affecting accessibility.

-			aria-hidden='false'

Also applies to: 41-41

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 71bce62 and 0649230.

📒 Files selected for processing (1)
  • packages/ui-client/src/components/PasswordVerifier/PasswordVerifierItem.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, the team has decided to use Latin-1 encoding (via Binary.toArrayBuffer and Binary.toString) for password encoding and decrypt output instead of UTF-8 encoding. This is a deliberate choice for E2EE password/key material handling.
🧬 Code graph analysis (1)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierItem.tsx (1)
packages/password-policies/src/PasswordPolicy.ts (1)
  • PasswordPolicyValidation (35-39)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (1)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierItem.tsx (1)

6-17: Previous type constraint issue resolved.

The incorrect satisfies Record<string, IconProps> constraint has been properly removed. The as const assertion is now appropriate for the variants object structure.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (1)

125-125: Make aria-describedby conditional to reference only rendered elements.

The aria-describedby attribute includes ${passphraseId}-hint unconditionally, but the hint element (line 132) is only rendered when !keysExist. Referencing non-existent IDs can confuse screen readers.

As per coding guidelines
Apply this diff to conditionally include the hint ID:

-										aria-describedby={`${e2ePasswordExplanationId} ${passphraseId}-hint ${passphraseId}-error`}
+										aria-describedby={`${e2ePasswordExplanationId}${!keysExist ? ` ${passphraseId}-hint` : ''}${errors.passphrase ? ` ${passphraseId}-error` : ''}`}
🧹 Nitpick comments (1)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (1)

76-79: Simplify the async invocation.

The async wrapper function can be eliminated by directly using void trigger(...).

Apply this diff:

-		if (confirmationPassphrase) {
-			const validateConfirmation = async () => {
-				await trigger('confirmationPassphrase');
-			};
-			void validateConfirmation();
-		}
+		if (confirmationPassphrase) {
+			void trigger('confirmationPassphrase');
+		}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 323039c and afca159.

📒 Files selected for processing (1)
  • apps/meteor/client/views/account/security/ChangePassphrase.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, the team has decided to use Latin-1 encoding (via Binary.toArrayBuffer and Binary.toString) for password encoding and decrypt output instead of UTF-8 encoding. This is a deliberate choice for E2EE password/key material handling.
📚 Learning: 2025-10-07T15:08:37.419Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, the team has decided to use Latin-1 encoding (via Binary.toArrayBuffer and Binary.toString) for password encoding and decrypt output instead of UTF-8 encoding. This is a deliberate choice for E2EE password/key material handling.

Applied to files:

  • apps/meteor/client/views/account/security/ChangePassphrase.tsx
🧬 Code graph analysis (1)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (5)
apps/meteor/client/views/room/hooks/useE2EEState.ts (1)
  • useE2EEState (9-9)
packages/password-policies/src/PasswordPolicy.ts (2)
  • validate (179-247)
  • error (102-115)
packages/ui-contexts/src/hooks/usePasswordPolicy.ts (1)
  • usePasswordPolicy (15-28)
apps/meteor/client/lib/e2ee/rocketchat.e2e.ts (1)
  • e2e (851-851)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierList.tsx (1)
  • PasswordVerifierList (14-39)
🪛 ast-grep (0.39.7)
apps/meteor/client/views/account/security/ChangePassphrase.tsx

[warning] 101-101: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

🪛 Biome (2.1.2)
apps/meteor/client/views/account/security/ChangePassphrase.tsx

[error] 102-102: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (6)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (6)

1-11: LGTM!

All imports are properly organized and utilized in the component.


13-21: LGTM!

The strong passphrase policy (30-character minimum with mixed character classes) aligns with E2EE security requirements. The frozen object prevents accidental mutations.


23-31: LGTM!

Both hooks provide clean abstractions for E2EE state checking and passphrase validation.


33-44: LGTM!

The mutation setup and default values are correctly configured.


98-103: LGTM!

The usage of dangerouslySetInnerHTML with DOMPurify.sanitize is the correct approach for safely rendering HTML content. The static analysis warning can be safely ignored here.


150-191: LGTM!

The confirmation field has proper conditional rendering and accessibility attributes. The save button's disabled logic correctly validates all required conditions.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (1)

155-158: Verify error handling for async operation.

A previous review flagged that e2e.decodePrivateKeyFlow() can throw errors and recommended wrapping it in a try-catch block. The comment was marked as addressed in commit 2297bea, but the current code still shows no error handling. Please verify this concern has been properly addressed.

#!/bin/bash
# Verify if decodePrivateKeyFlow has error handling or if it's wrapped elsewhere
rg -n -A10 'decodePrivateKeyFlow\(\)' --type=ts --type=tsx
🧹 Nitpick comments (1)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (1)

108-208: Consider using a semantic form element.

While the current implementation works, wrapping the fields in a <form> element with onSubmit={handleSubmit(handleSave)} would provide better semantics, native keyboard submission (Enter key), and improved accessibility. As per the previous review comment.

Example refactor:

-			<Box mbs={36} w='full'>
+			<Box is='form' mbs={36} w='full' onSubmit={handleSubmit(handleSave)}>
 				<Box is='h3' fontScale='h4' mbe={12}>
 					{t('Change_E2EE_password')}
 				</Box>
 				<FieldGroup w='full'>
 					{/* ... fields ... */}
 				</FieldGroup>
 				<Button
 					primary
+					type='submit'
 					disabled={!(keysExist && valid && isValid)}
-					onClick={handleSubmit(handleSave)}
 					mbs={12}
 					data-qa-type='e2e-encryption-save-password-button'
 				>
 					{t('Save_changes')}
 				</Button>
 			</Box>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between afca159 and 3772dc9.

📒 Files selected for processing (3)
  • apps/meteor/client/views/account/security/ChangePassphrase.tsx (1 hunks)
  • apps/meteor/client/views/account/security/EndToEnd.tsx (1 hunks)
  • apps/meteor/client/views/account/security/ResetPassphrase.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/meteor/client/views/account/security/ResetPassphrase.tsx
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, the team has decided to use Latin-1 encoding (via Binary.toArrayBuffer and Binary.toString) for password encoding and decrypt output instead of UTF-8 encoding. This is a deliberate choice for E2EE password/key material handling.
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,tsx,js,jsx} : Avoid code comments in the implementation

Applied to files:

  • apps/meteor/client/views/account/security/EndToEnd.tsx
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,tsx,js,jsx} : Write concise, technical TypeScript/JavaScript with accurate typing

Applied to files:

  • apps/meteor/client/views/account/security/EndToEnd.tsx
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use descriptive test names that clearly communicate expected behavior

Applied to files:

  • apps/meteor/client/views/account/security/EndToEnd.tsx
📚 Learning: 2025-10-07T15:08:37.419Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, the team has decided to use Latin-1 encoding (via Binary.toArrayBuffer and Binary.toString) for password encoding and decrypt output instead of UTF-8 encoding. This is a deliberate choice for E2EE password/key material handling.

Applied to files:

  • apps/meteor/client/views/account/security/EndToEnd.tsx
  • apps/meteor/client/views/account/security/ChangePassphrase.tsx
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,tsx,js,jsx} : Follow DRY by extracting reusable logic into helper functions or page objects

Applied to files:

  • apps/meteor/client/views/account/security/EndToEnd.tsx
📚 Learning: 2025-10-07T15:08:37.419Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, PBKDF2 iteration count validation is not enforced because the iterations parameter is outside the user's control and is system-managed.

Applied to files:

  • apps/meteor/client/views/account/security/ChangePassphrase.tsx
🧬 Code graph analysis (2)
apps/meteor/client/views/account/security/EndToEnd.tsx (2)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (1)
  • ChangePassphrase (46-211)
apps/meteor/client/views/account/security/ResetPassphrase.tsx (1)
  • ResetPassphrase (6-22)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (5)
apps/meteor/client/views/room/hooks/useE2EEState.ts (1)
  • useE2EEState (9-9)
packages/password-policies/src/PasswordPolicy.ts (2)
  • validate (179-247)
  • error (102-115)
packages/ui-contexts/src/hooks/usePasswordPolicy.ts (1)
  • usePasswordPolicy (15-28)
apps/meteor/client/lib/e2ee/rocketchat.e2e.ts (1)
  • e2e (851-851)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierList.tsx (1)
  • PasswordVerifierList (14-39)
🪛 ast-grep (0.39.7)
apps/meteor/client/views/account/security/ChangePassphrase.tsx

[warning] 105-105: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

🪛 Biome (2.1.2)
apps/meteor/client/views/account/security/ChangePassphrase.tsx

[error] 106-106: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: 🔨 Test Unit / Unit Tests
  • GitHub Check: 🔨 Test Storybook / Test Storybook
  • GitHub Check: 🔎 Code Check / TypeScript
  • GitHub Check: 🔎 Code Check / Code Lint
  • GitHub Check: 📦 Meteor Build - coverage
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (7)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (6)

1-11: Imports look good.

All dependencies are appropriate for the component's functionality: form handling, password policy validation, E2EE integration, and accessibility.


13-21: Strong E2EE passphrase policy implemented correctly.

The 30-character minimum with character class requirements provides robust protection for E2EE keys. Object.freeze ensures the policy remains immutable.


23-44: Clean hook abstractions.

The custom hooks (useKeysExist, useValidatePassphrase, useChangeE2EPasswordMutation) provide good separation of concerns and will be easy to test independently.


59-85: Confirmation revalidation properly implemented.

The effect now correctly revalidates the confirmation field when the primary passphrase changes to a valid value, addressing the previous review feedback. The inclusion of trigger ensures immediate validation feedback.


90-98: Save handler looks good.

The mutation and toast handling is clean. As confirmed by the author, the error formatting is handled automatically by the dispatchToastMessage infrastructure.


102-107: Sanitized HTML rendering is secure.

The use of DOMPurify.sanitize before setting dangerouslySetInnerHTML is the correct approach to prevent XSS attacks while allowing formatted translation content. The static analysis warning can be safely ignored here.

apps/meteor/client/views/account/security/EndToEnd.tsx (1)

1-16: Excellent refactoring.

The extraction of E2EE password management into ChangePassphrase and ResetPassphrase components makes EndToEnd a clean, focused container. This improves maintainability, testability, and follows the single responsibility principle.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (2)

184-184: Fix aria-required to be static.

The confirmation field is always required per the validation rules (line 174), so aria-required should be 'true' instead of toggling based on the passphrase value.

Apply this diff:

-											aria-required={passphrase ? 'true' : 'false'}
+											aria-required='true'

155-158: Add error handling for the async operation.

The e2e.decodePrivateKeyFlow() call can throw errors on invalid passwords or decryption failures. Wrap it in a try-catch to handle errors gracefully and provide user feedback.

Apply this diff:

 									<Box
 										is='a'
 										href='#'
-										onClick={async (e) => {
-											e.preventDefault();
-											await e2e.decodePrivateKeyFlow();
-										}}
+										onClick={async (e) => {
+											e.preventDefault();
+											try {
+												await e2e.decodePrivateKeyFlow();
+											} catch (error) {
+												dispatchToastMessage({ type: 'error', message: error });
+											}
+										}}
 									>
🧹 Nitpick comments (1)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (1)

100-208: Consider wrapping in a semantic <form> element.

Using a <form> element instead of fragments would improve semantics, enable Enter key submission, and better integrate with react-hook-form's handleSubmit. Move handleSubmit(handleSave) to the form's onSubmit handler.

Example structure:

<form onSubmit={handleSubmit(handleSave)}>
  {/* existing Box and Field content */}
  <Button
    type='submit'
    primary
    disabled={!(keysExist && valid && isValid)}
    mbs={12}
    data-qa-type='e2e-encryption-save-password-button'
  >
    {t('Save_changes')}
  </Button>
</form>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3772dc9 and f262d1e.

📒 Files selected for processing (1)
  • apps/meteor/client/views/account/security/ChangePassphrase.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, the team has decided to use Latin-1 encoding (via Binary.toArrayBuffer and Binary.toString) for password encoding and decrypt output instead of UTF-8 encoding. This is a deliberate choice for E2EE password/key material handling.
📚 Learning: 2025-10-07T15:08:37.419Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, the team has decided to use Latin-1 encoding (via Binary.toArrayBuffer and Binary.toString) for password encoding and decrypt output instead of UTF-8 encoding. This is a deliberate choice for E2EE password/key material handling.

Applied to files:

  • apps/meteor/client/views/account/security/ChangePassphrase.tsx
📚 Learning: 2025-10-07T15:08:37.419Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, PBKDF2 iteration count validation is not enforced because the iterations parameter is outside the user's control and is system-managed.

Applied to files:

  • apps/meteor/client/views/account/security/ChangePassphrase.tsx
📚 Learning: 2025-09-18T17:32:33.969Z
Learnt from: aleksandernsilva
Repo: RocketChat/Rocket.Chat PR: 36974
File: apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/MessageForm.tsx:124-129
Timestamp: 2025-09-18T17:32:33.969Z
Learning: The ARIA mismatch issue in MessageForm's template field (where FieldError id used templateId instead of messageFormId) was addressed in PR #36972 through refactoring the template field into a separate TemplateField component, which uses consistent templateFieldId for both aria-describedby and FieldError id.

Applied to files:

  • apps/meteor/client/views/account/security/ChangePassphrase.tsx
🧬 Code graph analysis (1)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (5)
apps/meteor/client/views/room/hooks/useE2EEState.ts (1)
  • useE2EEState (9-9)
packages/password-policies/src/PasswordPolicy.ts (2)
  • validate (179-247)
  • error (102-115)
packages/ui-contexts/src/hooks/usePasswordPolicy.ts (1)
  • usePasswordPolicy (15-28)
apps/meteor/client/lib/e2ee/rocketchat.e2e.ts (1)
  • e2e (851-851)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierList.tsx (1)
  • PasswordVerifierList (14-39)
🪛 ast-grep (0.39.7)
apps/meteor/client/views/account/security/ChangePassphrase.tsx

[warning] 105-105: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

🪛 Biome (2.1.2)
apps/meteor/client/views/account/security/ChangePassphrase.tsx

[error] 106-106: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🔇 Additional comments (3)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (3)

13-21: LGTM! Password policy correctly implements requirements.

The policy definition correctly matches the PR objectives from ESH-43 for user-provided passwords: 30-character minimum with lowercase, uppercase, digit, and special character requirements.


106-106: Properly sanitized - static analysis false positive.

The use of DOMPurify.sanitize() correctly neutralizes XSS risks before rendering HTML. The static analysis warnings can be safely ignored.


129-135: LGTM! Conditional aria-describedby is correctly implemented.

The aria-describedby construction properly matches the conditionally rendered elements: the verifier/hint IDs correspond to what keysExist renders, and the error ID is only included when the error exists. The .filter(Boolean) pattern correctly removes undefined values.

Copy link
Member

@gabriellsh gabriellsh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise all looks good.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (3)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (3)

155-158: Add error handling for the async operation.

The e2e.decodePrivateKeyFlow() call can throw errors (invalid password, decryption failure), but there's no try-catch block. This can result in unhandled promise rejections.

Apply this diff to handle errors gracefully:

 <Box
   is='a'
   href='#'
-  onClick={async (e) => {
-    e.preventDefault();
-    await e2e.decodePrivateKeyFlow();
-  }}
+  onClick={async (e) => {
+    e.preventDefault();
+    try {
+      await e2e.decodePrivateKeyFlow();
+    } catch (error) {
+      dispatchToastMessage({ type: 'error', message: error });
+    }
+  }}
 >

184-184: Use static aria-required value.

The confirmation field is only rendered when valid is true (line 166), which requires a non-empty passphrase that meets the policy. Therefore, passphrase is always truthy when this field exists, making aria-required always evaluate to 'true'. The dynamic expression is confusing.

Apply this diff:

-											aria-required={passphrase ? 'true' : 'false'}
+											aria-required='true'

74-85: Add passphrase to the useEffect dependency array to catch password mismatches.

The confirmation field validation rule (line 175) compares against passphrase via closure: (value) => (passphrase !== value ? t('Passwords_do_not_match') : true). However, when passphrase changes after confirmationPassphrase is already filled and valid, the effect does not run (since valid remains true and confirmationPassphrase is unchanged). This leaves the form reporting isValid even though the passwords no longer match.

The form's mode: 'all' setting validates individual fields on interaction, but does not automatically re-validate one field when a different field's value changes. You must explicitly call trigger() to force revalidation.

Add passphrase to the dependency array:

-}, [valid, confirmationPassphrase, resetField, trigger]);
+}, [passphrase, valid, confirmationPassphrase, resetField, trigger]);

This ensures trigger('confirmationPassphrase') is called whenever passphrase changes and confirmationPassphrase is populated, catching mismatches immediately.

🧹 Nitpick comments (1)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (1)

100-210: Consider wrapping fields in a <form> element for better semantics and accessibility.

The current implementation uses a Fragment with button onClick handling. Using a <form> element with an onSubmit handler would provide:

  • Semantic HTML structure for assistive technologies
  • Native keyboard support (Enter key submission)
  • Standard form behavior
-	return (
-		<>
+	return (
+		<>
 			<Box
 				is='p'
 				fontScale='p1'
 				id={e2ePasswordExplanationId}
 				dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(t('E2E_Encryption_Password_Explanation')) }}
 			/>
-			<Box mbs={36} w='full'>
+			<Box is='form' mbs={36} w='full' onSubmit={handleSubmit(handleSave)}>
 				<Box is='h3' fontScale='h4' mbe={12}>
 					{t('Change_E2EE_password')}
 				</Box>
 				{/* ... fields ... */}
 				<Button
+					type='submit'
 					primary
 					disabled={!(keysExist && valid && isValid)}
-					onClick={handleSubmit(handleSave)}
 					mbs={12}
 					data-qa-type='e2e-encryption-save-password-button'
 				>
 					{t('Save_changes')}
 				</Button>
 			</Box>
+		</>
-	);
+	);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f262d1e and 578a672.

📒 Files selected for processing (2)
  • apps/meteor/client/views/account/security/ChangePassphrase.tsx (1 hunks)
  • packages/ui-client/src/components/PasswordVerifier/PasswordVerifierItem.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, the team has decided to use Latin-1 encoding (via Binary.toArrayBuffer and Binary.toString) for password encoding and decrypt output instead of UTF-8 encoding. This is a deliberate choice for E2EE password/key material handling.
📚 Learning: 2025-10-07T15:08:37.419Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, the team has decided to use Latin-1 encoding (via Binary.toArrayBuffer and Binary.toString) for password encoding and decrypt output instead of UTF-8 encoding. This is a deliberate choice for E2EE password/key material handling.

Applied to files:

  • apps/meteor/client/views/account/security/ChangePassphrase.tsx
📚 Learning: 2025-10-07T15:08:37.419Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/pbkdf2.ts:13-45
Timestamp: 2025-10-07T15:08:37.419Z
Learning: In apps/meteor/client/lib/e2ee/pbkdf2.ts, PBKDF2 iteration count validation is not enforced because the iterations parameter is outside the user's control and is system-managed.

Applied to files:

  • apps/meteor/client/views/account/security/ChangePassphrase.tsx
📚 Learning: 2025-09-18T17:32:33.969Z
Learnt from: aleksandernsilva
Repo: RocketChat/Rocket.Chat PR: 36974
File: apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/MessageForm.tsx:124-129
Timestamp: 2025-09-18T17:32:33.969Z
Learning: The ARIA mismatch issue in MessageForm's template field (where FieldError id used templateId instead of messageFormId) was addressed in PR #36972 through refactoring the template field into a separate TemplateField component, which uses consistent templateFieldId for both aria-describedby and FieldError id.

Applied to files:

  • apps/meteor/client/views/account/security/ChangePassphrase.tsx
📚 Learning: 2025-09-23T19:22:59.217Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 36987
File: apps/meteor/tests/e2e/page-objects/fragments/room-toolbar.ts:10-20
Timestamp: 2025-09-23T19:22:59.217Z
Learning: In Playwright e2e tests, prefer stable selectors like data-qa-id attributes over localized text in getByRole() or getByText() calls to prevent test failures when UI language changes. Test translations separately by validating actual text content after ensuring UI interactions work with stable selectors.

Applied to files:

  • packages/ui-client/src/components/PasswordVerifier/PasswordVerifierItem.tsx
🧬 Code graph analysis (2)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (5)
apps/meteor/client/views/room/hooks/useE2EEState.ts (1)
  • useE2EEState (9-9)
packages/password-policies/src/PasswordPolicy.ts (2)
  • validate (179-247)
  • error (102-115)
packages/ui-contexts/src/hooks/usePasswordPolicy.ts (1)
  • usePasswordPolicy (15-28)
apps/meteor/client/lib/e2ee/rocketchat.e2e.ts (1)
  • e2e (851-851)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierList.tsx (1)
  • PasswordVerifierList (14-39)
packages/ui-client/src/components/PasswordVerifier/PasswordVerifierItem.tsx (1)
packages/password-policies/src/PasswordPolicy.ts (1)
  • PasswordPolicyValidation (35-39)
🪛 ast-grep (0.39.7)
apps/meteor/client/views/account/security/ChangePassphrase.tsx

[warning] 105-105: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

🪛 Biome (2.1.2)
apps/meteor/client/views/account/security/ChangePassphrase.tsx

[error] 106-106: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (2)
apps/meteor/client/views/account/security/ChangePassphrase.tsx (2)

13-21: LGTM! Password policy aligns with requirements.

The passphrase policy correctly enforces the 30-character minimum with mandatory character classes (uppercase, lowercase, number, special character) as specified in the linked issue ESH-43.


106-106: LGTM! DOMPurify sanitization is correctly applied.

Static analysis flags the use of dangerouslySetInnerHTML, but the code properly mitigates XSS risk by sanitizing the content with DOMPurify.sanitize() before rendering.

Adds complexity requirements to end-to-end encryption passphrase
Copy link
Member

@gabriellsh gabriellsh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@cardoso cardoso added the stat: QA assured Means it has been tested and approved by a company insider label Nov 4, 2025
@dionisio-bot dionisio-bot bot added the stat: ready to merge PR tested and approved waiting for merge label Nov 4, 2025
@kodiakhq kodiakhq bot merged commit 31ab78f into develop Nov 4, 2025
87 of 89 checks passed
@kodiakhq kodiakhq bot deleted the feat/ESH-43 branch November 4, 2025 19:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stat: QA assured Means it has been tested and approved by a company insider stat: ready to merge PR tested and approved waiting for merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants