-
Notifications
You must be signed in to change notification settings - Fork 1.6k
feat: webauthn and PAM session mfa #4896
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 22397427 | Triggered | Generic Private Key | 382bd1a | backend/bdd/pebble/localhost/key.pem | View secret |
| 22397428 | Triggered | Generic Private Key | 382bd1a | backend/bdd/pebble/pebble.minica.key.pem | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secrets safely. Learn here the best practices.
- Revoke and rotate these secrets.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
Greptile OverviewGreptile SummaryThis PR implements WebAuthn (passkey) support and adds MFA session verification for PAM account access. The implementation adds WebAuthn as a third MFA method alongside email and TOTP, with proper challenge-based verification and replay protection. A new MFA session flow allows users to verify their identity before accessing sensitive PAM accounts. Key changes:
Critical security issues found:
Confidence Score: 2/5
Important Files ChangedFile Analysis
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
62 files reviewed, 3 comments
backend/src/db/migrations/20251119124200_add-require-mfa-to-pam-account.ts
Show resolved
Hide resolved
| // Determine which MFA method to use | ||
| // Priority: org-enforced > user-selected > email as fallback | ||
| const orgMfaMethod = org.enforceMfa | ||
| ? ((org.selectedMfaMethod as MfaMethod | null) ?? MfaMethod.EMAIL) | ||
| : undefined; | ||
| const userMfaMethod = actorUser.isMfaEnabled | ||
| ? ((actorUser.selectedMfaMethod as MfaMethod | null) ?? MfaMethod.EMAIL) | ||
| : undefined; | ||
| const mfaMethod = (orgMfaMethod ?? userMfaMethod ?? MfaMethod.EMAIL) as MfaMethod; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty sure this logic is flawed. The line:
((org.selectedMfaMethod as MfaMethod | null) ?? MfaMethod.EMAIL)will make it so that orgMfaMethod becomes MfaMethod.EMAIL even if org.selectedMfaMethod is null rather than falling back to userMfaMethod. Should probably be ((org.selectedMfaMethod as MfaMethod | null) ?? undefined) or something
| // Verify the session is for the same account | ||
| if (mfaSession.resourceId !== accountId) { | ||
| throw new BadRequestError({ | ||
| message: "MFA session is for a different resource" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the error should say its for a different account?
| handler: async (req) => { | ||
| return server.services.webAuthn.verifyRegistrationResponse({ | ||
| userId: req.permission.id, | ||
| registrationResponse: req.body.registrationResponse as unknown as RegistrationResponseJSON, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty sure you don't need this type assertion if you make clientExtensionResults have a default like:
clientExtensionResults: z.record(z.unknown()).default({})| handler: async (req) => { | ||
| return server.services.webAuthn.verifyAuthenticationResponse({ | ||
| userId: req.permission.id, | ||
| authenticationResponse: req.body.authenticationResponse as unknown as AuthenticationResponseJSON |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file should not have been edited. rotationCredentialsConfigured should still be passed, otherwise the tooltip functionality is useless. The idea is to grey it out if it's not configured
| <GenericAccountFields /> | ||
| <SqlAccountFields isUpdate={isUpdate} /> | ||
| <RotateAccountFields rotationCredentialsConfigured={rotationCredentialsConfigured} /> | ||
| {rotationCredentialsConfigured && <RotateAccountFields />} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rotationCredentialsConfigured should stay as a parameter. We just want to grey out the option rather than fully hide it.
| message: "MFA session not found or expired" | ||
| }); | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe adding a check like if (mfaMethod !== mfaSession.mfaMethod) ... may be beneficial to prevent possible exploit attempts?
| export const verifyCredentialOwnership = (userId: string, credentialUserId: string): boolean => { | ||
| return userId === credentialUserId; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function feels a little unnecessary... maybe we just use an inline === check?
| transports: cred.transports as AuthenticatorTransportFuture[] | ||
| })), | ||
| authenticatorSelection: { | ||
| authenticatorAttachment: "platform", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is using "platform" here the best choice? From my tiny bit of research I think this only works for platform-based methods like windows hello, touch id, etc. And not stuff like YubiKeys.
| export enum MfaSessionStatus { | ||
| PENDING = "PENDING", | ||
| ACTIVE = "ACTIVE" | ||
| } | ||
|
|
||
| export type TMfaSessionStatusResponse = { | ||
| status: MfaSessionStatus; | ||
| mfaMethod: MfaMethod; | ||
| }; | ||
|
|
||
| export type TVerifyMfaSessionRequest = { | ||
| mfaSessionId: string; | ||
| mfaToken: string; | ||
| mfaMethod: MfaMethod; | ||
| }; | ||
|
|
||
| export type TVerifyMfaSessionResponse = { | ||
| success: boolean; | ||
| message: string; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it'd be better to put the enum and types into dedicated file, and not queries.tsx? Maybe into types or helper file
Description 📣
This PR implements WebAuthn (passkey) support and adds MFA session verification for PAM account access. The implementation adds WebAuthn as a third MFA method alongside email and TOTP, with proper challenge-based verification and replay protection. A new MFA session flow allows users to verify their identity before accessing sensitive PAM accounts.
Type ✨
Tests 🛠️
# Here's some code block to paste some code snippets