Broken Object Property Level Authorization

Broken Object Property Level Authorization Node.js (Express) [CVE-1999-0967]

[Updated March 2026] Updated CVE-1999-0967

Overview

Broken Object Property Level Authorization vulnerabilities occur when an API returns object graphs with sensitive properties without checking the caller's rights. Historically, CVE-1999-0967 described a buffer overflow in the HTML library used by Internet Explorer, Outlook Express, and Windows Explorer via the res: local resource protocol, illustrating how improper handling of untrusted resources can lead to privilege escalation or data corruption. While that CVE targets a different technology stack, it demonstrates the broader risk of mishandling input and resource access. In Node.js/Express, this class of vulnerability manifests when endpoints emit entire entity objects or nested fields to clients without enforcing per-property access control. The risk is that a regular user could receive properties they are not authorized to see, such as private emails, SSNs, internal notes, or admin-only flags.

Code Fix Example

Node.js (Express) API Security Remediation
// Vulnerable pattern (no per-property authorization)
const express = require('express');
const app = express();

// Pretend this is your data store
const db = {
  getUserById: async (id) => ({
    id,
    username: 'user' + id,
    email: 'user' + id + '@example.com',
    ssn: '123-45-6789',
    adminNotes: 'internal data',
  })
};

// Simulated middleware that attaches a user to req
app.use((req, res, next) => {
  req.user = { id: 1, role: 'user' }; // normal user
  next();
});

app.get('/api/users/:id', async (req, res) => {
  const user = await db.getUserById(req.params.id);
  // Vulnerable: returns entire object including sensitive fields
  res.json(user);
});

// Fixed: per-property level authorization (whitelist + role-based access)
app.get('/api/users/:id/fixed', async (req, res) => {
  const user = await db.getUserById(req.params.id);
  const allowedBase = ['id', 'username'];
  const sanitized = {};
  allowedBase.forEach((k) => {
    if (Object.prototype.hasOwnProperty.call(user, k)) {
      sanitized[k] = user[k];
    }
  });
  // Admins get extra fields
  if (req.user && req.user.role === 'admin') {
    sanitized.email = user.email;
    sanitized.ssn = user.ssn;
  }
  res.json(sanitized);
});

app.listen(3000, () => console.log('Server started'));

CVE References

Choose which optional cookies to allow. You can change this any time.