Skip to content

Bug: Complex::add() lacks schema URN handling, causing null pointer exception #155

@atymic

Description

@atymic

Description

The Complex::add() method is missing schema URN handling logic that exists in the replace() method. When processing PATCH add operations with schema URN keys (e.g.,
urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:employeeNumber), the method fails to recognize them as schema attributes and attempts to resolve them as regular attributes, resulting in a null
pointer exception.

Error

Error: Call to a member function add() on null
Location: vendor/arietimmerman/laravel-scim-server/src/Attribute/Complex.php:306

Root Cause

The replace() method (line 232) has special logic to detect schema URNs by checking for : in the key:

  // replace() method - line 232
  if (strpos($key, ':') !== false) {
      $subNode = $this->getSubNode($key);  // Passes full URN
  }

  However, the add() method (lines 286-307) lacks this check and always parses the key, extracting just the attribute name:

  // add() method - line 291-296
  $path = Parser::parse($key);  // Parses URN, extracts just "employeeNumber"

  if ($path->isNotEmpty()) {
      $attributeNames = $path->getAttributePathAttributes();  // ["employeeNumber"]
      $path = $path->shiftAttributePathAttributes();
      $subNode = $this->getSubNode($attributeNames[0]);  // Looks for "employeeNumber" at root - returns NULL
      // ...
      $subNode->add($newValue, $object);  // ❌ Crashes
  }

When getSubNode("employeeNumber") is called on the root complex, it returns null because employeeNumber exists inside the enterprise schema, not at the root level.

Steps to Reproduce

Send a PATCH request with Azure AD's format that includes enterprise schema attributes:

  curl -X PATCH 'https://scim-endpoint/scim/v2/Users/123' \
    -H 'Content-Type: application/scim+json' \
    -d '{
      "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
      "Operations": [{
        "op": "add",
        "value": {
          "name.formatted": "Test User",
          "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:employeeNumber": "12345",
          "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:department": "Engineering"
        }
      }]
    }'

Expected Behavior

The add() method should handle schema URNs the same way the replace() method does - by detecting the : character and treating the full URN as a schema node reference.

Proposed Fix

Add the same schema URN detection logic from replace() to add():

Environment

  • Laravel SCIM Server: v7.x
  • PHP: 8.4
  • Laravel: 11.0
  • Integration: Azure AD SCIM provisioning

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions