1. HTTP Headers
We’ve used a helmet as a middleware that provides the security headers.
Headers:
- X-DNS-Prefetch-Control – Controls browser DNS prefetching to reduce attack surface.
- X-Frame-Options: SAMEORIGIN – Prevents clickjacking by disallowing iframe embedding from other domains.
- Strict-Transport-Security – Enforces HTTPS via HSTS (only works if served over HTTPS).
- X-Content-Type-Options: nosniff – Prevents MIME-type sniffing. Helps stop attacks based on content-type confusion.
- Referrer-Policy: no-referrer – Limits referrer header information sent with requests.
- Permissions-Policy – Controls access to browser features, including cameras, geolocation, microphones, etc.
- Content-Security-Policy – A powerful allow-list of what can happen on your page, which mitigates attacks.
- Cross-Origin-Embedder-Policy – Helps prevent cross-origin resource embedding vulnerabilities.
- Cross-Origin-Opener-Policy – Mitigates some side-channel attacks, including Spectre.
- Cross-Origin-Resource-Policy – Controls who can load resources from your domain.
2. XSS Filter Evasion
- We have added xss-clean, which sanitises user input coming from the POST body, GET queries, and URL parameters.
- Helmet also provides basic XSS protection.
3. SQL Injection Prevention
- We have added express-mongo-sanitize, which searches for any keys in objects that begin with a $ sign or contain a ., from req.body, req.query or req.params.
4. JSON Web Token for Authorization
- We have authenticated users using jsonwebtoken and verified via the x-token header.
- Token generated using JWT with an expiration time of 30 days.
5. Logging
- We have added Morgan for logs-only requests with statusCode >= 400.
6. Input Validation
- Body size limits (100mb) prevent DoS via payload overflow.
7. Cross-Site Request Forgery Prevention
- We have added CORS middleware that can be used to enable CORS with various options.
8. Session Management
- We have stored the JWT Token in the database to control the sessions.
- We also have cookie-parser, which parses the Cookie header and populates req.cookies with an object keyed by the cookie names.
9. Error Handling
- Removes internal error messages (like Sequelize or context errors).
- We have also handled the code blocks such as try…catch and then()…catch() blocks for error handling.
10. Forgot Password
- A user is allowed a maximum of three (3) password reset email requests.
- After the third request, no additional reset emails will be sent. The user must complete the password reset using one of the verification links already provided.
- If all three reset attempts expire or become invalid (e.g., due to timeouts or usage), the user will need to contact support or wait for a system-defined cooldown period before initiating a new password reset cycle.
11. File Upload
- We do have features like CSV import, but once the import is complete, we remove the file.
- We also have file type validation and input validation to validate the file and data.
12. GraphQL
- We have used xss-clean, and express-mongo-sanitize, which help against injection (XSS, NoSQL).
- We have also defined the Scalar types, such as Date, Number, JSON on schemas.
- We have sanitised error messages (removing internal DB errors in formatError), aligning with the advice to avoid leaking implementation details.
- We have also disabled GraphQL Playground in production, which prevents schema enumeration.
13. Password Storage
- We’re using bcrypt for password encryption, using a work factor of 10 or more, and with a password limit of 72 bytes.
14. Nodejs Security
- We’re using flat Promise chains and async/await, which prevent the callback hell situations.
- We have also limited the payload size for each request to prevent DoS via payload overflow.
- We also have express-mongo-sanitize to sanitise the input validations.
- We have implemented Winston to perform application activity logging which enables streaming and querying logs, and it provides a way to handle uncaught exceptions.
15. Multifactor Authentication
- We have implemented Multifactor authentication using the Google Authenticator.
- The user can enable it from their profile and save the key, which will be verified using the authenticator app.
16. Database Security
- We have implemented VPN based access using WireGuard.
17. Insecure Direct Object Reference Prevention
- Every user request has been authenticated using a token. If an attacker gets the ID of a user, they still need the user’s token. If the ID and token don’t match user will not get a response.