Skip to content

Conversation

@akshayutture-augment
Copy link

Co-authored-by: Peer Richelsen <[email protected]>
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@akshayutture-augment
Copy link
Author

@greptileai

@greptile-apps
Copy link

greptile-apps bot commented Nov 14, 2025

Greptile Overview

Confidence Score: 2/5

  • This PR contains a critical authentication security flaw that must be fixed before merging
  • Score reflects a critical security vulnerability in backup code validation (packages/features/auth/lib/next-auth-options.ts:148) where used codes are set to null instead of removed, allowing potential reuse. Also has incorrect component export name causing confusion. Feature implementation is otherwise solid with proper encryption and UI flows.
  • packages/features/auth/lib/next-auth-options.ts requires immediate attention to fix the backup code invalidation logic. apps/web/components/auth/BackupCode.tsx needs component name correction.

Important Files Changed

File Analysis

Filename Score Overview
apps/web/components/auth/BackupCode.tsx 2/5 New component with incorrect export name - exports TwoFactor instead of BackupCode, causing potential confusion
packages/features/auth/lib/next-auth-options.ts 3/5 Added backup code authentication flow with null-based invalidation that could match null values via indexOf
apps/web/pages/api/auth/two-factor/totp/setup.ts 5/5 Generates 10 backup codes using crypto.randomBytes and returns them encrypted, implementation looks secure
apps/web/components/settings/EnableTwoFactorModal.tsx 4/5 Added backup code display step with download/copy functionality, properly manages memory cleanup for blob URLs
apps/web/pages/auth/login.tsx 4/5 Added backup code UI toggle for lost access during login, conditional rendering is nested but functional

Sequence Diagram

sequenceDiagram
    participant User
    participant Frontend
    participant API
    participant DB
    
    Note over User,DB: 2FA Setup with Backup Codes
    User->>Frontend: Enable 2FA
    Frontend->>API: POST /api/auth/two-factor/totp/setup
    API->>API: Generate TOTP secret (32 chars)
    API->>API: Generate 10 backup codes (crypto.randomBytes)
    API->>DB: Save encrypted backupCodes & twoFactorSecret
    API-->>Frontend: Return QR code, secret, backupCodes
    Frontend->>User: Display QR code
    User->>Frontend: Enter TOTP code
    Frontend->>API: Verify TOTP & enable 2FA
    API-->>Frontend: Success
    Frontend->>User: Display backup codes (download/copy)
    
    Note over User,DB: Login with Backup Code
    User->>Frontend: Enter email/password
    Frontend->>API: POST /api/auth/callback/credentials
    API-->>Frontend: SecondFactorRequired
    Frontend->>User: Show 2FA input with "Lost access" option
    User->>Frontend: Click "Lost access" → Enter backup code
    Frontend->>API: Submit credentials with backupCode
    API->>DB: Fetch encrypted backupCodes
    API->>API: Decrypt & check if code matches
    API->>API: Set matching code to null
    API->>DB: Re-encrypt & save backupCodes array
    API-->>Frontend: Authentication success
    Frontend->>User: Redirect to app
    
    Note over User,DB: Disable 2FA with Backup Code
    User->>Frontend: Toggle 2FA off
    Frontend->>User: Show password + 2FA/backup code input
    User->>Frontend: Click "Lost access" → Enter backup code
    Frontend->>API: POST /api/auth/two-factor/totp/disable
    API->>DB: Verify backup code exists & matches
    API->>DB: Set backupCodes=null, twoFactorEnabled=false
    API-->>Frontend: Success
    Frontend->>User: 2FA disabled
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

16 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Label, TextField } from "@calcom/ui";

export default function TwoFactor({ center = true }) {
Copy link

Choose a reason for hiding this comment

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

syntax: component is named TwoFactor but file is BackupCode.tsx

Suggested change
export default function TwoFactor({ center = true }) {
export default function BackupCode({ center = true }) {
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/web/components/auth/BackupCode.tsx
Line: 7:7

Comment:
**syntax:** component is named `TwoFactor` but file is `BackupCode.tsx`

```suggestion
export default function BackupCode({ center = true }) {
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +144 to +148
const index = backupCodes.indexOf(credentials.backupCode.replaceAll("-", ""));
if (index === -1) throw new Error(ErrorCode.IncorrectBackupCode);

// delete verified backup code and re-encrypt remaining
backupCodes[index] = null;
Copy link

Choose a reason for hiding this comment

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

logic: setting used codes to null creates a security issue - indexOf will match null values if user submits "null" as string after JSON parsing, allowing reuse of invalidated codes

Suggested change
const index = backupCodes.indexOf(credentials.backupCode.replaceAll("-", ""));
if (index === -1) throw new Error(ErrorCode.IncorrectBackupCode);
// delete verified backup code and re-encrypt remaining
backupCodes[index] = null;
const index = backupCodes.indexOf(credentials.backupCode.replaceAll("-", ""));
if (index === -1) throw new Error(ErrorCode.IncorrectBackupCode);
// delete verified backup code and re-encrypt remaining
backupCodes.splice(index, 1);
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/features/auth/lib/next-auth-options.ts
Line: 144:148

Comment:
**logic:** setting used codes to `null` creates a security issue - `indexOf` will match `null` values if user submits "null" as string after JSON parsing, allowing reuse of invalidated codes

```suggestion
        const index = backupCodes.indexOf(credentials.backupCode.replaceAll("-", ""));
        if (index === -1) throw new Error(ErrorCode.IncorrectBackupCode);

        // delete verified backup code and re-encrypt remaining
        backupCodes.splice(index, 1);
```

How can I resolve this? If you propose a fix, please make it concise.

{t("forgot")}
</Link>
</div>
</div>
Copy link

Choose a reason for hiding this comment

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

style: triple ternary nesting hurts readability

Suggested change
</div>
{twoFactorRequired && (
twoFactorLostAccess ? <BackupCode center /> : <TwoFactor center />
)}
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/web/pages/auth/login.tsx
Line: 218:218

Comment:
**style:** triple ternary nesting hurts readability

```suggestion
              {twoFactorRequired && (
                twoFactorLostAccess ? <BackupCode center /> : <TwoFactor center />
              )}
```

How can I resolve this? If you propose a fix, please make it concise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants