Skip to content

Object Access Control Analyzer

Configuration Name: ObjectAccessControlPolicy

The ObjectAccessControlPolicy analyzer verifies user-defined, declarative object-level authorization policies by automatically generating and executing test cases that validate every scenario the policy defines.

Background

An object is any discrete, uniquely identifiable resource an application manages, such as a database record, file, user profile, or API resource. Each object is represented in code by a unique identifier (e.g., an ID or UUID), allowing the application to distinguish one instance from another.

Object-level authorization is a fine-grained access control mechanism implemented in an application’s business logic. It evaluates, at runtime, whether a given user has permission to perform a specific action (read, write, delete, etc.) on an individual object instance. By checking permissions against each object’s unique identifier, it ensures that users can only interact with the exact resources they’re authorized to access.

Broken Object-Level Authorization (BOLA), or Insecure Direct Object Reference (IDOR), occurs when an application fails to enforce proper access controls on object identifiers. An attacker can tamper with IDs or references (for example, changing /orders/123 to /orders/124) to view, modify, or delete resources they shouldn’t have access to. Such failures lead to unauthorized data exposure, alteration, or destruction. OWASP ranks BOLA as the #1 risk in its OWASP API Security Top 10 - 2023 (API1:2023).

Declarative Authorization Policy

The input to the ObjectAccessControlPolicy analyzer is the representation of an access control policy in a declarative format. A policy specifies:

  • The resource types (e.g., event, user)
  • The owner of each resource
  • The roles and identities of actors
  • The permitted actions (e.g., read, update, delete)

This policy model abstracts the logic from the application code, enabling consistent and reusable validation across services.

Example: Calendar API

Consider an API for a calendar application. It exposes RESTful endpoints to manage events on a calendar. One resource type is an Event with three actions that may be performed on instances of the resource.

  • Read Event: GET /api/v1/events/{eventId}
  • Update Event: PUT /api/v1/events/{eventId}
  • Delete Event: DELETE /api/v1/events/{eventId}

The access policy requires:

  • Only the creator of the event can update or delete it.
  • Admins can read any event within their own organization.
  • Users from other organizations must be denied access entirely.

Imagine the product owner providing the simple authorization policy as a table of permissions by role.

Action Event Owner Org Admin Org User Other Org User
Read Yes Yes No No
Update Yes No No No
Delete Yes No No No

This authorization policy is expressed to the ObjectAccessControlPolicy analyzer in its policy parameter, as shown in the following configuration snippet.

    - kind: ObjectAccessControlPolicy
      policy:
        - resources:
            - event
          owner: Org1UserA
          permissions:
            - user: Org1UserA
              access: ["read", "update", "delete"]
            - user: Org1Admin
              access: ["read"]
            - user: Org1UserB
              access: []
        - resources:
            - event
          owner: Org2UserA
          permissions:
            - user: Org2UserA
              access: ["read", "update", "delete"]
            - user: Org2Admin
              access: ["read"]
            - user: Org2UserB
              access: []

Note that users that are not explicitly mentioned in a policy are assumed to have no permissions to perform any actions. In conjunction with configuring ObjectAccessControlPolicy with the above configuration, Sift must be configured with 6 user identities: Org1Admin, Org1UserA, Org2UserB, Org2Admin, Org2UserA, Org2UserB.

This seemingly simple policy requires 72 test cases to fully validate the authorization policy. Given the authorization policy and the API definition, Sift autonomously generates and executes all 72 test cases.

  • 2 creators create an event: Org1UserA, Org2UserA
  • 6 actors attempt actions on the created event
  • 3 actions performed by each actor: Read, Update, Delete

Hence, 2 creators * 6 actors * 3 actions = 72 test cases.

Configuration Parameters

The ObjectAccessControlPolicy analyzer requires a policy and accepts an optional policy name.

    - kind: ObjectAccessControlPolicy
      name: "MyAuthzPolicy"     # optional
      policy:
        - resources:
            - event
          owner: Org1UserA
          permissions:
            - user: Org1UserA
              access: ["read", "update", "delete"]
            - user: Org1Admin
              access: ["read"]

The policy parameter is an array of rules. Each rule specifies:

  • resources contains an array of resource types. A resource is kind of object exposed by an API.
  • owner is a user identity and specifies that this rule applies to objects created by that user.
  • permissions is an array of user access permissions
    • user is the user identity with the specified access permissions.
    • access contains an array of actions (create, read, update, delete, list) that may be performed by user.

Faults Reported

Fault Identifier Title Summary Solution Severity
CWE-639 Authorization Bypass Through User-Controlled Key An application's authorization functionality does not prevent a client from performing actions on an object that the client is not authorized to access. Review the implementation of access control in the application. high, medium