cap-js / audit-logging

CDS plugin providing integration to the SAP Audit Log service as well as out-of-the-box personal data-related audit logging based on annotations.
https://cap.cloud.sap/docs/guides/data-privacy
Apache License 2.0
4 stars 1 forks source link

Sensitive data is not audit-logged if read via calculated element #103

Open patricebender opened 2 weeks ago

patricebender commented 2 weeks ago

it is possible to circumvent audit-logging of sensitive data, if the data is read via a calculated element.

I have created a sample which illustrates the problem. In the incidents-app, the credit card number of the customer is exposed in Incidents via calculated element.. In the sample, audit-logging has been added as well as the data-privacy annotations.

Steps to reproduce


→ Logs for direct read [odata] - GET /odata/v4/processor/Customers:

[audit-log] - SensitiveDataRead: {
  data_subject: {
    id: { ID: '1004100' },
    role: 'Customer',
    type: 'ProcessorService.Customers'
  },
  object: { type: 'ProcessorService.Customers', id: { ID: '1004100' } },
  attributes: [ { name: 'creditCardNo' } ],
  uuid: '6c05ad60-7dc8-41d0-bc1b-bd5fa7f549ba',
  tenant: 't1',
  user: 'alice',
  time: 2024-06-20T09:26:51.333Z
}
…

→ No logs for indirect read [odata] - GET /odata/v4/processor/Incidents, which exposes the credit card number of the customer:

{
  "@odata.context": "$metadata#Incidents",
  "value": [
    {
      "ID": "3583f982-d7df-4aad-ab26-301d4a157cd7",
      "createdAt": "2024-06-20T09:33:09.664Z",
      "createdBy": "anonymous",
      "modifiedAt": "2024-06-20T09:33:09.664Z",
      "modifiedBy": "anonymous",
      "customerCreditCardNo": "3456789012345678", // 😱
      "customer_ID": "1004100",
      "title": "Solar panel broken",
      "urgency_code": "H",
      "status_code": "I",
      "HasActiveEntity": false,
      "HasDraftEntity": false,
      "IsActiveEntity": true
    },
    …
  ]
}
sjvans commented 2 weeks ago

hi @patricebender

you'd need to annotate such calculated properties (and their carrying entities) explicitly

patricebender commented 2 weeks ago

Okay, do you think it would make sense to document this somewhere? I was not aware of this and had expected it to work out of the box.

Also, the annotation is propagated to the calculated element, why not leverage this?

entity Authors {
    key ID         : Integer;
        books      : Association to many Books
                         on books.author = $self;
        creditCard : Int16 @PersonalData.IsPotentiallySensitive;
}

entity Books {
    key ID     : Integer;
        author : Association to Authors;
        title  : String;
        authorCreditCardNumber = author.creditCard;
}
❯ bin/cdsc.js e.cds
Debugger attached.
{
  "definitions": {
    "Authors": {
      "kind": "entity",
      "elements": {
        …
        "creditCard": {
          "@PersonalData.IsPotentiallySensitive": true,
          "type": "cds.Int16"
        }
      }
    },
    "Books": {
      "kind": "entity",
      "elements": {
       …
        "authorCreditCardNumber": {
          "@PersonalData.IsPotentiallySensitive": true, // ⬅️
          "type": "cds.Int16",
          "value": {
            "ref": [
              "author",
              "creditCard"
            ]
          }
        }
      }
    }
  },
  "meta": {
    "creator": "CDS Compiler v5.0.1"
  },
  "$version": "2.0"
}