HIGH insufficient loggingsailsbasic auth

Insufficient Logging in Sails with Basic Auth

Insufficient Logging in Sails with Basic Auth — how this specific combination creates or exposes the vulnerability

Sails is a Node.js MVC framework that often relies on policy-based authorization and explicit action logic. When Basic Authentication is used without structured, auditable logs, security-critical events are not recorded in a way that supports detection or incident response. This creates an insufficient logging posture where authentication successes and failures, as well as downstream authorization decisions, are effectively invisible to monitoring tools.

With Basic Auth, credentials are transmitted on every request (albeit base64-encoded). If Sails does not log key details—such as the parsed user identity, the outcome of authentication, timestamp, source IP, requested route, and relevant authorization context—an attacker can probe endpoints with stolen or guessed credentials and leave minimal forensic evidence. For example, repeated 401 responses may indicate credential spraying, while 403 or 500 responses can reveal path traversal or authorization logic flaws, but without logs these patterns remain undetected.

Inadequate log coverage also hampers compliance mapping for frameworks such as OWASP API Top 10 (broken object level authorization), PCI-DSS, and SOC2, where audit trails for authentication and authorization are required. middleBrick’s checks for BOLA/IDOR and Authentication include verifying that sufficient context is captured in logs to reconstruct access decisions. In a Sails application, this means ensuring each authenticated action writes a structured log entry that ties the request to a user identity and outcome, enabling correlation with runtime behavior observed during scanning.

Basic Auth-Specific Remediation in Sails — concrete code fixes

To address insufficient logging while retaining Basic Auth in Sails, instrument authentication and authorization paths to emit structured logs with consistent fields. Avoid logging raw credentials; instead log identifiers and outcomes. Below are concrete examples that integrate with a typical Sails controller and policy setup.

Example 1: Basic Auth parsing helper with safe logging

// api/helpers/basic-auth-helper.js
'use strict';
const crypto = require('crypto');

/**
 * Parses and validates Basic Auth header.
 * Returns { username, credentialsValid } or null.
 * Never logs the password.
 */
module.exports.parseBasicAuth = (req) => {
  const authHeader = req.headers.authorization || '';
  const match = authHeader.match(/^Basic\s+(\S+)$/i);
  if (!match) return null;
  const decoded = Buffer.from(match[1], 'base64').toString('utf8');
  const separatorIndex = decoded.indexOf(':');
  if (separatorIndex === -1) return null;
  const username = decoded.slice(0, separatorIndex);
  const password = decoded.slice(separatorIndex + 1);
  // In real usage, validate credentials against a secure store
  const credentialsValid = validateCredentials(username, password);
  // Structured log entry without sensitive data
  sails.log.info({
    timestamp: new Date().toISOString(),
    event: 'basic_auth_attempt',
    username,
    credentialsValid,
    ip: req.ip,
    method: req.method,
    url: req.originalUrl,
  });
  return credentialsValid ? { username } : null;
};

function validateCredentials(username, password) {
  // Replace with secure lookup and constant-time comparison
  const users = {
    alice: '$2a$10$abc123...', // stored hash
  };
  const hash = users[username];
  if (!hash) return false;
  const testHash = crypto.pbkdf2Sync(password, username, 100000, 64, 'sha512').toString('base64');
  return testHash === hash;
}

Example 2: Controller using the helper with outcome logging

// api/controllers/AccountController.js
'use strict';
module.exports = {
  viewProfile: async function (req, res) {
    const auth = sails.helpers.basicAuthHelper(req);
    if (!auth) {
      sails.log.warn({
        timestamp: new Date().toISOString(),
        event: 'auth_failure',
        reason: 'missing_or_invalid_basic_auth',
        ip: req.ip,
        method: req.method,
        url: req.originalUrl,
      });
      return res.unauthorized('Invalid credentials');
    }
    try {
      const data = await UserService.getProfile(auth.username);
      sails.log.info({
        timestamp: new Date().toISOString(),
        event: 'profile_accessed',
        username: auth.username,
        ip: req.ip,
        method: req.method,
        url: req.originalUrl,
        profileId: data.id,
      });
      return res.ok(data);
    } catch (err) {
      sails.log.error({
        timestamp: new Date().toISOString(),
        event: 'profile_access_error',
        username: auth.username,
        ip: req.ip,
        method: req.method,
        url: req.originalUrl,
        error: err.message,
      });
      return res.serverError('Unable to load profile');
    }
  },
};

Example 3: Policy enforcement with audit logging

// api/policies/authenticated-and-logged.js
'use strict';
module.exports = async function (req, res, proceed) {
  const auth = sails.helpers.basicAuthHelper(req);
  if (!auth) {
    sails.log.warn({
      timestamp: new Date().toISOString(),
      event: 'policy_block_unauthenticated',
      path: req.path,
      ip: req.ip,
      method: req.method,
    });
    return res.unauthorized('Authentication required');
  }
  // Proceed to action; action itself should log outcomes as shown above
  return proceed();
};

Remediation checklist for Sails + Basic Auth

  • Log authentication attempts (success/failure) with username, IP, timestamp, and outcome; never log passwords or full credentials.
  • Log authorization decisions at the action or policy level, including the requested resource and result.
  • Ensure logs are centralized and retained according to compliance requirements to support detection of BOLA/IDOR or abuse patterns.

Frequently Asked Questions

Why is logging credentials—even hashed—unsafe in Sails with Basic Auth?
Logging any form of credential material, including hashes, can expand the attack surface if logs are exposed. Instead, log non-sensitive metadata such as username (if not considered sensitive in context), outcome, IP, and timestamp to support detection without risking credential leakage.
How does middleBrick relate to insufficient logging in scanned APIs?
middleBrick scans for insufficient logging by checking whether authentication and authorization events are recorded with sufficient context. Its findings include severity and remediation guidance to help teams improve auditability in frameworks such as Sails.