Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/tech-dipesh/yeti-Jobs/llms.txt

Use this file to discover all available pages before exploring further.

Yeti Jobs layers several security measures on top of its JWT authentication system. Rate limiting prevents brute-force and abuse at the IP level. Helmet sets hardened HTTP response headers on every response. CORS locks the API down to a single trusted front-end origin. Zod schema validation and UUID pre-screening reject malformed input before it ever reaches business logic or the database.

Rate Limiting

Global Rate Limit

A single express-rate-limit instance is created in src/app.js and applied globally with app.use. Every IP address is allowed a maximum of 200 requests per 60-second window across all endpoints.
import rateLimit from "express-rate-limit";

const limitUser = rateLimit({
  windowMs: 1000 * 60, // 60 seconds
  limit: 200,
});

app.set('trust proxy', 1);
app.use(limitUser);
app.set('trust proxy', 1) is required because the API is deployed on Render, which sits behind a reverse proxy. Without this setting, express-rate-limit would see every request as coming from the proxy’s IP address and rate-limit all users as one. Setting trust proxy to 1 tells Express to read the real client IP from the X-Forwarded-For header.
When the limit is exceeded, express-rate-limit returns a 429 Too Many Requests response with the default error body.

Password Reset and Verification Rate Limit

A separate, stricter rateLimit instance is defined in src/routes/users.routes.js and applied individually to the four most abuse-prone endpoints:
const limitUser = rateLimit({
  windowMs: 1000 * 60, // 60 seconds
  limit: 2,
  message: { message: "You only can send resend request twice per minute" },
});

router.post("/forget-password",         limitUser, forgetEmailPassword);
router.post("/forget-password/verify",  limitUser, verifyForgetPassword);
router.post("/verify",                  limitUser, isUnverifiedUser, verifyEmailConfirmation);
router.post("/verify/resend",           limitUser, isUnverifiedUser, resendVerificationCode);
EndpointWindowMax requestsPurpose of limit
POST /api/v1/users/forget-password60 s2Stops email flooding and account enumeration
POST /api/v1/users/forget-password/verify60 s2Limits brute-force guessing of 6-digit reset codes
POST /api/v1/users/verify60 s2Prevents rapid-fire verification code guessing
POST /api/v1/users/verify/resend60 s2Prevents abuse of the Nodemailer sending quota
In a distributed deployment (multiple API instances behind a load balancer), the in-memory store used by express-rate-limit tracks state per process. To share rate limit counters across instances, swap the default store for a Redis-backed one using the rate-limit-redis package:
import { RedisStore } from "rate-limit-redis";
import { createClient } from "redis";

const redisClient = createClient({ url: process.env.REDIS_URL });
await redisClient.connect();

const limitUser = rateLimit({
  windowMs: 1000 * 60,
  limit: 200,
  store: new RedisStore({ sendCommand: (...args) => redisClient.sendCommand(args) }),
});

Helmet — Security Response Headers

helmet() is applied as global middleware immediately after the rate limiter:
import helmet from "helmet";

app.use(limitUser);
app.use(helmet());
Helmet bundles a set of smaller middleware functions, each of which sets or removes a specific HTTP header. With the default configuration, calling helmet() activates all of them.
Header set / removed by HelmetEffect
X-Powered-By removedHides the fact that the server runs Express, reducing fingerprinting surface
Content-Security-PolicyRestricts the sources from which scripts, styles, and other resources can be loaded
Cross-Origin-Embedder-PolicyControls cross-origin resource embedding (COEP)
Cross-Origin-Opener-PolicyIsolates browsing context to prevent cross-origin attacks
Cross-Origin-Resource-PolicyPrevents other origins from reading the API responses
Origin-Agent-ClusterRequests a dedicated process for the origin to improve isolation
Referrer-PolicyControls how much referrer information is included in requests
Strict-Transport-Security (HSTS)Tells browsers to only access the site over HTTPS for the configured duration
X-Content-Type-OptionsPrevents MIME-type sniffing (nosniff)
X-DNS-Prefetch-ControlDisables DNS prefetching to avoid information leakage
X-Download-OptionsPrevents IE from executing downloads in the site’s context
X-Frame-OptionsBlocks the API responses from being embedded in <iframe> elements (clickjacking)
X-Permitted-Cross-Domain-PoliciesRestricts Adobe Flash and PDF cross-domain access
X-XSS-ProtectionEnables the browser’s built-in XSS filter (legacy browsers)

CORS

CORS is configured in src/app.js to allow requests only from the single trusted front-end origin defined by CLIENT_BASE_URL:
app.use(cors({
  origin: process.env.CLIENT_BASE_URL,
  credentials: true,
  exposedHeaders: ['Content-Length'],
}));
OptionValuePurpose
originprocess.env.CLIENT_BASE_URLWhitelists one origin; all others receive a CORS error
credentialstrueRequired to allow the browser to send and receive the JWT cookie
exposedHeaders['Content-Length']Allows the client to read the Content-Length response header
Any request from an origin other than CLIENT_BASE_URL will be rejected by the browser’s CORS pre-flight check before it can interact with the API.

Input Validation with Zod

All major write endpoints parse and validate their request bodies using Zod schemas defined in src/Models/. Validation runs as the first step inside each controller, before any database query.
// Inside postSignupUserController
const validateuser = userSchema.safeParse(allUser);
if (!validateuser.success) {
  const message = validateuser.error.issues[0].message;
  return res.status(422).json({ message });
}
Validation schemas are applied on these endpoints:
EndpointZod Schema
POST /api/v1/users/signupuserSchema
POST /api/v1/users/loginloginUserSchema
PUT /api/v1/users/:idupdateUserSchema
POST /api/v1/users/add-educationEducationUserSchema
Validation failures return 422 Unprocessable Entity with the first Zod error message, never a raw stack trace. This gives Yeti Jobs a three-layer validation model:
Client-side validation

Server-side Zod schema (422 on failure)

PostgreSQL column constraints (500 on unhandled edge cases)

UUID Validation

The validateCorrectUid middleware (src/Middleware/validateCorrectUid.js) is placed before isLoggedIn and isOwner on every route containing an :id path parameter. It validates the value against the standard UUID format regex before the request proceeds any further.
export default function validateCorrectUid(req, res, next) {
  const { id } = req.params;
  if (!id) {
    return res.status(404).json({ message: "Please Enter a Id" });
  }
  const regex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/;
  if (!regex.test(id)) {
    return res.status(400).json({ message: "Please Enter Correct Id:" });
  }
  next();
}
This ensures that malformed or deliberately crafted :id values (SQL injection attempts, oversized strings, non-UUID formats) are rejected with 400 Bad Request before any database query or ownership check runs. Routes that use validateCorrectUid include:
  • GET / PUT / PATCH /api/v1/users/:id
  • POST /api/v1/users/:id/skills
  • Any route on the jobs, companies, and applications routers that accept a UUID :id param

Security Measures at a Glance

LayerMechanismScope
Rate limiting (global)express-rate-limit 200 req/minAll endpoints
Rate limiting (strict)express-rate-limit 2 req/min/verify, /forget-password routes
Security headershelmet() (default config)All responses
Origin restrictionCORS CLIENT_BASE_URL allowlistAll cross-origin requests
Body validationZod schemasSignup, login, update, education
Param validationvalidateCorrectUid UUID regexAll :id route params
Auth enforcementisLoggedIn JWT middlewareCompanies, applications, admin, notifications
Cookie hardeninghttpOnly, secure, sameSiteJWT cookie on every auth response

Build docs developers (and LLMs) love