HIGH insufficient loggingfeathersjsbasic auth

Insufficient Logging in Feathersjs with Basic Auth

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

FeathersJS is a popular framework for building REST and real-time APIs with JavaScript and Node.js. When Basic Authentication is used for endpoint protection, developers often configure it at the transport layer (e.g., via an authentication middleware or a reverse proxy) and assume access is inherently secure. Insufficient logging in this context means events such as failed logins, token or credential validation errors, and abnormal request patterns are not recorded with sufficient detail or retained for analysis. This creates a blind spot: an attacker can probe Basic Auth protected endpoints with invalid credentials, and without logs there is no evidence of reconnaissance or brute-force activity. In a typical FeathersJS setup, if authentication is implemented via hooks or a custom authentication service, missing logs around hook execution and authentication failures prevent correlation of suspicious requests (for example, rapid requests to a /users endpoint with different passwords). Because the scan tests the unauthenticated attack surface, an endpoint that relies solely on Basic Auth without robust audit trails can be flagged; the scanner may detect that authorization checks are weak or inconsistent across resources, and insufficient logging exacerbates the risk by making post-incident investigation difficult. The combination of Basic Auth with missing observability also complicates detection of credential stuffing or password spraying, where attackers try leaked credentials against the API. Without structured logs that include timestamp, source IP, requested path, HTTP method, and authentication outcome, defenders cannot reliably trigger alerts or initiate incident response. FeathersJS services that expose OpenAPI specs and rely on Basic Auth must ensure logging captures both successful and failed authentication events, alongside input validation results, to support the Security checks run by middleBrick, such as Authentication, BOLA/IDOR, and Rate Limiting. This is especially important when endpoints also support unauthenticated LLM interfaces or client SDKs that may inadvertently expose tokens in logs if not handled carefully.

Basic Auth-Specific Remediation in Feathersjs — concrete code fixes

Remediation centers on implementing explicit authentication hooks and ensuring comprehensive logging within FeathersJS services. Below is a concrete example of a FeathersJS service configured with Basic Auth using the @feathersjs/authentication and @feathersjs/authentication-local packages, including structured logging for authentication events.

const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const authentication = require('@feathersjs/authentication');
const local = require('@feathersjs/authentication-local');
const { BasicAuthStrategy } = require('@feathersjs/authentication-local');

const app = express(feathers());

// Configure authentication with Local API (for username/password) and Basic strategy
app.configure(authentication({
  secret: 'your-super-secret',
  path: '/authentication',
  service: 'authentication',
  entity: 'user',
  multi: true,
  strategies: ['local', 'basic']
}));

app.configure(local({
  usernameField: 'email',
  passwordField: 'password',
  entity: 'user',
  service: 'users',
  verifyPassword: (inputPassword, hashedPassword, user) => {
    // Log each verification attempt with context
    console.info({
      timestamp: new Date().toISOString(),
      event: 'password_verification',
      entity: 'user',
      userId: user ? user.id : null,
      result: 'success'
    });
    return user && user.verifyPassword(inputPassword);
  }
}));

// Custom Basic Auth hook to add logging
app.hooks({
  before: {
    all: [],
    find: [contextLogger('find')],
    get: [contextLogger('get')],
    create: [contextLogger('create')],
    update: [contextLogger('update')],
    patch: [contextLogger('patch')],
    remove: [contextLogger('remove')]
  },
  after: {
    all: [authResultLogger()],
    find: [],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
  },
  error: {
    all: [errorLogger()],
    find: [],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
  }
});

function contextLogger(action) {
  return context => {
    const { params, path } = context;
    const authInfo = params.auth || { strategy: 'none' };
    console.info({
      timestamp: new Date().toISOString(),
      event: 'request',
      action,
      path,
      strategy: authInfo.strategy,
      user: authInfo.user ? authInfo.user.id : null,
      remoteIp: (params.connection || {}).remoteAddress || 'unknown'
    });
    return context;
  };
}

function authResultLogger() {
  return context => {
    const { result, params } = context;
    const authInfo = params.auth || { strategy: 'none' };
    // Log authentication outcome per request
    console.info({
      timestamp: new Date().toISOString(),
      event: 'auth_result',
      strategy: authInfo.strategy,
      authenticated: Boolean(result && result.user),
      path: params.path
    });
    return context;
  };
}

function errorLogger() {
  return context => {
    const { error, params } = context;
    console.warn({
      timestamp: new Date().toISOString(),
      event: 'authentication_error',
      message: error.message,
      code: error.code,
      strategy: (params.auth || {}).strategy || 'none',
      path: params.path
    });
    return context;
  };
}

// Example service route that requires authentication
app.use('/secure', {
  async find(params) {
    // Only reachable if authenticated via Basic Auth
    return [{ id: 'log-only', data: 'sensitive' }];
  }
});

app.listen(3030);

Key remediation practices:

  • Log both successful and failed authentication outcomes, including strategy (basic), user identifier (if available), source IP, and timestamp.
  • Include structured metadata in logs to support correlation with security tools and to detect patterns such as credential spraying against specific endpoints.
  • Ensure logs do not capture raw passwords or other sensitive fields; hash or omit them at the point of logging.
  • Combine logging with rate limiting and monitoring rules to detect anomalies; middleBrick’s Rate Limiting and Authentication checks can surface gaps when logs are insufficient.

Frequently Asked Questions

Does enabling logging in FeathersJS with Basic Auth impact performance?
Adding structured console or transport logging has minimal overhead, but ensure logs are written asynchronously and avoid synchronous I/O in hot paths. Sampling or adjusting log levels in production can reduce volume while preserving auditability.
How does middleBrick detect insufficient logging during a scan?
middleBrick evaluates whether authentication events and error conditions are observable through API behavior and, where spec and runtime data allow, infers gaps in auditability. It reports findings tied to Authentication and related checks, highlighting missing observability that could impede incident response.