-
Notifications
You must be signed in to change notification settings - Fork 30
fix: add try-catch around JSON.parse(userData) in auth services #88
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?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -120,7 +120,13 @@ export class AuthService { | |||||||||||||||||||||||||
| throw ApiError.badRequest("Invalid or expired otp"); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const { name, email: userEmail, role, password } = JSON.parse(userData); | ||||||||||||||||||||||||||
| let parsedData; | ||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||
| parsedData = JSON.parse(userData); | ||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
| } catch { | |
| } catch (parseError) { | |
| // Best-effort cleanup to avoid leaving the user stuck with a pending signup | |
| try { | |
| await redisClient.del(`user:${email}:${hashCode}`); | |
| await redisClient.del(`user:pending:${email}`); | |
| } catch (cleanupError) { | |
| logger.error( | |
| cleanupError, | |
| "Failed to clean up pending signup keys after JSON parse error" | |
| ); | |
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -124,7 +124,13 @@ export class AuthService { | |
| throw ApiError.badRequest("Invalid or expired otp"); | ||
| } | ||
|
|
||
| const { name, email: userEmail, role, password } = JSON.parse(userData); | ||
| let parsedData; | ||
| try { | ||
| parsedData = JSON.parse(userData); | ||
| } catch { | ||
| throw ApiError.badRequest("Invalid user data format"); | ||
| } | ||
|
Comment on lines
+127
to
+132
|
||
| const { name, email: userEmail, role, password } = parsedData; | ||
|
Comment on lines
+127
to
+133
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: find . -type f -name "auth.service.ts" | grep -E "auth/auth.service.ts"Repository: AkkalDhami/servercn Length of output: 753 🏁 Script executed: cat -n "packages/templates/node/express/blueprint/hybrid-auth/postgresql/drizzle/feature/src/modules/auth/auth.service.ts" | sed -n '115,145p'Repository: AkkalDhami/servercn Length of output: 1128 Validate parsed JSON shape before destructuring.
Add a type guard to ensure Proposed fix- let parsedData;
+ let parsedData: unknown;
try {
parsedData = JSON.parse(userData);
} catch {
throw ApiError.badRequest("Invalid user data format");
}
- const { name, email: userEmail, role, password } = parsedData;
+ if (!parsedData || typeof parsedData !== "object") {
+ throw ApiError.badRequest("Invalid user data format");
+ }
+
+ const {
+ name,
+ email: userEmail,
+ role,
+ password
+ } = parsedData as Partial<{
+ name: string;
+ email: string;
+ role: string;
+ password: string;
+ }>;
+
+ if (
+ typeof name !== "string" ||
+ typeof userEmail !== "string" ||
+ typeof password !== "string"
+ ) {
+ throw ApiError.badRequest("Invalid user data format");
+ }🤖 Prompt for AI Agents |
||
| const enforcedRole = "user" as const; | ||
|
|
||
| if (role && role !== enforcedRole) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -134,7 +134,13 @@ export class AuthService { | |||||||||||||
| throw ApiError.badRequest("Invalid or expired otp"); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| const { name, email: userEmail, role, password } = JSON.parse(userData); | ||||||||||||||
| let parsedData; | ||||||||||||||
| try { | ||||||||||||||
| parsedData = JSON.parse(userData); | ||||||||||||||
| } catch { | ||||||||||||||
|
||||||||||||||
| } catch { | |
| } catch (error) { | |
| await Promise.allSettled([ | |
| redisClient.del(`user:${email}:${hashCode}`), | |
| redisClient.del(`user:pending:${email}`) | |
| ]); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -93,7 +93,13 @@ export class AuthService { | |
| throw ApiError.badRequest("Invalid or expired otp"); | ||
| } | ||
|
|
||
| const { name, email: userEmail, role, password } = JSON.parse(userData); | ||
| let parsedData; | ||
| try { | ||
| parsedData = JSON.parse(userData); | ||
| } catch { | ||
| throw ApiError.badRequest("Invalid user data format"); | ||
| } | ||
|
Comment on lines
+96
to
+101
|
||
| const { name, email: userEmail, role, password } = parsedData; | ||
|
|
||
| const [existingUser] = await db | ||
| .insert(users) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -90,7 +90,13 @@ export class AuthService { | |
| throw ApiError.badRequest("Invalid or expired otp"); | ||
| } | ||
|
|
||
| const { name, email: userEmail, role, password } = JSON.parse(userData); | ||
| let parsedData; | ||
| try { | ||
| parsedData = JSON.parse(userData); | ||
| } catch { | ||
| throw ApiError.badRequest("Invalid user data format"); | ||
| } | ||
|
Comment on lines
+93
to
+98
|
||
| const { name, email: userEmail, role, password } = parsedData; | ||
|
|
||
| const [existingUser] = await db | ||
| .insert(users) | ||
|
|
||
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.
On JSON.parse failure, OTP has already been consumed, but the pending-signup keys remain (
user:${email}:${hashCode}anduser:pending:${email}) until TTL. That can leave a user stuck in “signup already in progress” with no usable OTP; consider best-effort deleting both keys in this catch before throwing.