Interlace ESLint
ESLint Interlace
Secure CodingRules

no-client-side-auth-logic

Detects authentication logic in client-side code that can be easily bypassed.

Keywords: client-side auth, CWE-602, localStorage auth, security bypass, authentication, JavaScript security

Detects authentication logic in client-side code that can be easily bypassed.

⚠️ This rule errors by default in the recommended config.

Quick Summary

AspectDetails
CWE ReferenceCWE-602 (Client-Side Enforcement of Server-Side Security)
OWASPA01:2021 Broken Access Control
SeverityCritical
CategorySecurity

Rule Details

Authentication and authorization checks in client-side JavaScript can be trivially bypassed using browser developer tools. This rule detects common patterns like:

  • Role/permission checks using localStorage
  • Password comparisons in client code
  • Authentication state checks without server validation

All authentication must be enforced server-side.

Examples

❌ Incorrect

// Role check from localStorage - EASILY BYPASSED
if (localStorage.getItem('isAdmin')) {
  showAdminPanel();
}

// Authentication check from localStorage
if (localStorage.getItem('authenticated')) {
  allowAccess();
}

// Password comparison in client code
if (userInput.password === storedPassword) {
  loginUser();
}

// Token validation client-side only
if (user.token === validToken) {
  grantAccess();
}

✅ Correct

// Server-side authentication
async function checkAuth() {
  const response = await fetch('/api/auth/verify', {
    headers: { Authorization: `Bearer ${token}` },
  });
  if (!response.ok) {
    throw new Error('Unauthorized');
  }
  return response.json();
}

// Server validates and returns permissions
const { isAdmin, permissions } = await checkAuth();
if (isAdmin) {
  showAdminPanel(); // Server already validated
}

// localStorage only for UI hints, not security
const cachedRole = localStorage.getItem('role');
// But always verify with server before sensitive operations
await verifyPermission('admin:read');

Error Message Format

The rule provides LLM-optimized error messages (Compact 2-line format) with actionable security guidance:

⚠️ CWE-602 OWASP:A06 CVSS:6.5 | Client-Side Enforcement of Server-Side Security detected | MEDIUM
   Fix: Review and apply the recommended fix | https://owasp.org/Top10/A06_2021/

Message Components

ComponentPurposeExample
Risk StandardsSecurity benchmarksCWE-602 OWASP:A06 CVSS:6.5
Issue DescriptionSpecific vulnerabilityClient-Side Enforcement of Server-Side Security detected
Severity & ComplianceImpact assessmentMEDIUM
Fix InstructionActionable remediationFollow the remediation steps below
Technical TruthOfficial referenceOWASP Top 10

Known False Negatives

The following patterns are not detected due to static analysis limitations:

Custom Storage Wrappers

Why: Wrappers around localStorage not traced.

// ❌ NOT DETECTED - Custom wrapper
const isAdmin = authStorage.get('isAdmin');
if (isAdmin) {
}

Mitigation: Apply rule to wrapper implementations.

State Management Stores

Why: Redux/Vuex/Zustand stores not analyzed.

// ❌ NOT DETECTED - State store
const isAuthenticated = useSelector((state) => state.auth.isAuthenticated);
if (isAuthenticated) {
} // Client-side only check

Mitigation: Ensure all state store values are server-validated.

Obfuscated Checks

Why: Indirect property access not detected.

// ❌ NOT DETECTED - Dynamic key
const key = 'is' + 'Admin';
if (localStorage.getItem(key)) {
}

Mitigation: Avoid dynamic key construction.

When Not To Use It

  • When the client-side check is purely for UX (hiding UI elements)
  • In test files mocking authentication flows
  • When server-side validation is verified to exist for all protected operations

Further Reading


Category: Security
Type: Problem
Recommended: Yes

On this page