This document outlines the security aspects of the application, including authentication, authorization, session handling, and data handling and storage.
The application is deployed to Vercel:
- URL: https://register-app-vert.vercel.app/
- Uses automatic HTTPS encryption
- Protected by Vercel's Edge Network
- Database hosted on MongoDB Atlas
- Vercell "pipeline" automately deploy the application after every commit to main branch
The application uses Twilio Verify API for phone number-based passwordless authentication via SMS. Check more from Twilio Verify API Documentation.
Process:
- Users provide their phone number, and the application checks that it exists in the invitation list database.
- The application requests Twilio to send a One-Time Password (OTP) via SMS to the provided phone number.
- After the user receives the OTP, it is sent to Twilio to be verified.
- Upon successful verification, the user gains access to the application.
Security:
- Twilio Verify API takes fully care of the authentication process from sending the OTPs via SMS to verifying them.
- Twilio ensures the security of OTPs by implementing critical measures such as expiration, API and SMS rate limiting, and monitoring for suspicious activity.
- Various security aspects of authentication, such as OTP expiration time, SMS rate limits, and service availability, can be configured based on application requirements.
- The application formats and validates phone numbers before sending requests to Twilio to minimize unnecessary API usage.
Risks:
- Unauthorized access is possible if someone gains access to the invited user's phone and retrieves the OTP.
- The OTP provides access to the application during its validity period, increasing the risk of unauthorized access if the OTP is leaked.
- Abuse of the OTP service can lead to increased costs, even with rate limiting in place.
After successful authentication, a new user session is created to verify the user's access to the application. The session is saved in the database and accessed via cookies on the client side.
Process:
- A new session is created upon successful authentication.
- Each session is identified by a unique token that is generated by the application using a cryptographically secure random number generator.
- The session is stored in the database and linked to the user's data to manage access and authorization within the application.
- The session is accessed in the application via cookies.
Security:
- Cookies are configured with the
HttpOnlyandSecureflags to prevent client-side access and ensure transmission over HTTPS. - The
SameSiteattribute is set to prevent cross-site request forgery (CSRF) attacks. - Sessions are automatically invalidated after a predefined expiration time and are also deleted from the database to prevent unauthorized access.
Risks:
- Users who fail to log out on shared devices may leave their sessions vulnerable to unauthorized access.
User's personal data and session information are stored in a MongoDB database and are accessible only to the respective user. Personal data is shared between the main guest and their additional guests (e.g., "avec").
Process:
- When a user is invited to an event, their data is stored in the database.
- Users can edit certain details about themselves and their additional guests, such as attendance status and preferences, and save these changes to the database.
Security:
- User inputs are sanitized and validated before being saved to the database to prevent injection attacks and ensure data integrity.
- Phone number validation uses the trusted and widely used libphonenumber-js library.
- Users can only access and edit their own data and the data of their additional guests.
- Access to the database is restricted to authorized services, ensuring that only authenticated and authorized operations are performed.
Risks:
- A guest can view and edit the data of additional guests, which may lead to privacy concerns.
- The additional guests' data can potentially be edited without their knowledge, leading to potential misuse or conflicts.
Evaluating Register App against the OWASP 2021 Top 10 security risks.
Findings:
- The application checks user authorization at the API level using session validation.
- Each user can only access/modify their own and their guests' data through API endpoint checks.
- Missing API level rate limiting on critical API endpoints:
- OTP request endpoint:
/api/otp/send/[phoneNumber] - OTP verification endpoint:
/api/otp/verify/[phoneNumber] - User data endpoint:
/api/users/[userId]
- OTP request endpoint:
Recommendations:
- Implement middleware for consistent access control.
- Implement rate limiter for critical API routes.
Reflection:
-
The application currently has only one secured route. While middleware for consistent access control is not immediately necessary, it would be beneficial for future application expansion.
-
OTP-related endpoints already have rate limiting through the Twilio API:
- Additional endpoint-level rate limiting would provide more control but is not critical.
- Implementing rate limiting for the user data endpoint would help prevent database abuse.
Findings:
-
Session management:
- Session IDs are generated using
crypto.randomBytes, which is cryptographically secure. - Session cookies use secure flags (HttpOnly, Secure, SameSite) with cookie expiration time.
- Sessions are stored and validated using database to exclude risk of session manipulation.
- Session IDs are generated using
-
Sensitive data such as API keys and connection strings are stored in environment variables.
-
There is no encryption for sensitive user data stored in the database.
Recommendations:
- Consider encrypting sensitive data in the database using a strong encryption algorithm.
Reflection:
- Current session handling implementation is cryptographically secure.
- The main risk is unencrypted sensitive data in the database.
Findings:
- API endpoints accept user input without comprehensive validation:
- Phone numbers are partially sanitized using regex.
- OTP codes are validated only for length.
- User data updates lack input validation.
- MongoDB queries use Mongoose schema which provides basic protection.
- Input validation implemented in both UI and API routes.
Recommendations:
Reflection:
- Current implementation has multiple layers of validation:
- Client-side validation in the UI.
- Server-side validation in API routes.
- Basic protection for data saving through Mongoose.
- Risk of injection attacks is minimal due to proper input validation.
Findings:
- Main user can edit their guests' data, which may lead to privacy concerns.
- No defined secure development lifecycle.
- Automated testing and a CI/CD pipeline are currently missing.
Recommendations:
- Establish secure development practices.
- Implement automated testing and a CI/CD pipeline.
Reflection:
- The current design prioritizes usability and the functional requirements of user data over security considerations.
- Implementing a CI/CD pipeline along with automated testing would strengthen secure development practices.
Findings:
- Sensitive credentials stored in environmental variables.
- No validation for required environment variables.
- Using Next.js and Vercel default security configurations.
Recommendations:
- Implement validation for all required environment variables.
- Remove or disable development features like console logs and detailed error messages in the production environment.
Reflection:
- Basic security is handled well by Next.js and Vercel defaults.
- There is a need for clearer separation between development and production configurations.
Findings:
- The application uses several third-party libraries.
- There is no automated process to monitor dependency versions and security vulnerabilities.
- Dependencies use caret versioning, which keeps them up to date by updating possible minor updates but may lead to unintended updates.
Recommendations:
- Use tools to monitor and address vulnerabilities in dependencies, for example as part of the CI/CD pipeline.
- Regularly update dependencies to their latest stable versions.
Reflection:
- Dependencies are relatively up to date, but lack automated monitoring.
- Implementing automated security scanning would help identify vulnerabilities early.
- Regular scheduling of dependency updates is recommended.
Findings:
- Authentication relies solely on SMS OTP through Twilio Verify API.
Recommendations:
- Make sure to use proper OTP and session timeouts.
- Check if Twilio Verify API security features fit for application needs.
Reflection:
- The simple authentication flow works well for the use case.
Findings:
- No integrity checks for npm packages during installation.
- No validation for user inputs and data rendering.
Recommendations:
- Enable npm package integrity checks.
- Sanitize user input before saving to database.
Reflection:
- The current setup lacks robust security practices for dependency management. While only a few well-known and trusted dependencies are used at the moment, stronger practices will be beneficial as the application grows.
Findings:
- No application-level logging.
- Twilio handles authentication-related logging.
- Vercel handles deployment-related logging.
Recommendations:
Reflection:
- Basic logging and monitoring features are handled by external services.
- Current logging setup is sufficient for the application's needs.
Findings:
- Application makes external HTTP requests to Twilio Verify API.
- Phone numbers are validated through invitation list before making the API request.
- User inputs have basic validation in both UI and API routes.
- Input sanitization is handled by React's TSX rendering.
Recommendations:
- The API routes are saving validated but unsanitized data to database, which is not a risk with MongoDB, but sanitization would be recommended for future development.
Reflection:
- Currently application has minimal risk for SSRF.
-
The application has undergone manual user testing.
-
API endpoints have been tested using Postman.
-
Testing focused on:
- Authentication
- Input/data validation
- Data updates
- Session handling
- User permissions
- UI functionality on Chrome (Windows and Android)
- Code quality is enforced using:
- ESLint for TypeScript linting
- Prettier for code formatting
- TypeScript for type checking
- The application's UI functions as intended.
- No errors, bugs or critical security risks were identified.
- More detailed unit testing is recommended in the future for the API routes.
- Unit testing
- Security scanning for dependecies
- Automate testing and scanning with CI/CD pipeline
- Logging for security-critical events
- Database encryption for sensitive data
- Proper validation for environment variables
- Cursor (AI Code Editor): Used at the start of development to help generating the initial UI, which was later mostly modified and fixed.
- GitHub Copilot: Used to review existing documentation, suggest improvements, and identify security risks that I missed.
- AI Used: Claude 3.5 Sonnet in both cases.