Fix Logic Flow Bypass in Sails
Logic flow bypasses in Sails.js typically occur when developers trust client-side state or fail to enforce strict state transitions in controllers. In a 'hacker-style' context, this is a 'state-smuggling' attack where an adversary manipulates the request parameters to skip critical steps like payment verification or authorization checks. To fix this, you must move the 'source of truth' from the request body to the server-side database and session store.
The Vulnerable Pattern
// api/controllers/UserController.js module.exports = { promoteToAdmin: async function(req, res) { // VULNERABILITY: The action trusts the 'secretKey' provided in the request body. // An attacker can brute-force this or find it in client-side JS bundles. const { userId, secretKey } = req.allParams();if (secretKey === 'SUPER_SECRET_BACKDOOR') { await User.updateOne({ id: userId }).set({ isAdmin: true }); return res.ok({ message: 'Promoted successfully' }); } return res.forbidden();
} };
The Secure Implementation
The vulnerable code relies on a static 'secret' passed via the client, which is a classic logic flaw. The secure version removes the bypass potential by: 1. Disregarding client-supplied authorization flags. 2. Using the session-stored userId to fetch the user's actual permissions from the database. 3. Implementing a strict role-based access control (RBAC) check that cannot be manipulated by modifying the request body. Always validate the 'current state' of the object in the database before allowing a transition to a 'privileged state'.
// api/controllers/UserController.js module.exports = { promoteToAdmin: async function(req, res) { // FIX 1: Use req.session for identity, not params. // FIX 2: Implement strict RBAC via Sails Policies. const targetUserId = req.param('id');// Verify the actor is actually a Super Admin in the DB, not just the session const actor = await User.findOne({ id: req.session.userId }); if (!actor || actor.role !== 'super-admin') { return res.forbidden('Unauthorized state transition attempt.'); } const updatedUser = await User.updateOne({ id: targetUserId }).set({ role: 'admin' }); if (!updatedUser) return res.notFound(); return res.ok({ message: 'Role updated by authorized admin.' });
} };
Your Sails API
might be exposed to Logic Flow Bypass
74% of Sails apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.
Free Tier • No Credit Card • Instant Report
Verified by Ghost Labs Security Team
This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.