Viewing or adding a reply on a Team Calendars Event macro fails to render with ForbiddenClassException: eventmacro.Reply

XMLWordPrintable

    • Type: Bug
    • Resolution: Unresolved
    • Priority: Low
    • None
    • Affects Version/s: 10.2.13, 10.2.15
    • Component/s: Apps - Team Calendar
    • None
    • 1
    • Severity 3 - Minor

      Issue Summary

      Viewing or adding a reply on a Team Calendars Event macro fails to render with ForbiddenClassException: eventmacro.Reply

      Steps to Reproduce

      On Confluence Data Center 10.2.14 with Team Calendars 20.2.15, create a page containing an Event macro:

      <ac:structured-macro ac:name="event" ac:schema-version="1">
        <ac:parameter ac:name="title">Test Event</ac:parameter>
      </ac:structured-macro>
      

      Note the macro occurrence id assigned on render (in testing, 3041).

      Add one RSVP reply, either through the macro UI or directly:

      curl -u <admin>:<pass> -X POST -H 'Content-Type: application/json' \
        -d '{"name":"Test User","email":"test@example.invalid","guests":1,"comment":"test"}' \
        'https://<confluence>/rest/calendar-services/1.0/eventmacro/page/<pageId>/macroid/<occurrence>'
      

       Read the replies back, or simply reload the page containing the macro:

      curl -s -o /dev/null -w '%{http_code}\n' -u <admin>:<pass> \
        'https://<confluence>/rest/calendar-services/1.0/eventmacro/page/<pageId>/macroid/<occurrence>'
      

      No configuration change is required to reproduce this — xstream-allowed was enabled=true throughout. In the environment used for testing, the event macro module itself ships disabled and was enabled before step 1; that affects only whether the macro is available, not the XStream lifecycle described above.

      Expected Results

      The Event macro renders and lists the RSVP replies. The read request returns HTTP 200 with the stored replies, since Reply is declared as an allowed XStream type by the plugin and the declaring module is enabled.

      Actual Results

      The macro fails to render:

      Error rendering macro 'event'
      com.atlassian.confluence.extra.calendar3.eventmacro.Reply
      

      The read request returns HTTP 500. The reply just accepted is written to os_propertyentry (key event:<occurrence>) but can no longer be deserialized:

      <list>
        <com.atlassian.confluence.extra.calendar3.eventmacro.Reply>
          <id>1788541818988</id>
          <name>Test User</name>
          <guests>1</guests>
          <comment>test</comment>
          <email>test@example.invalid</email>
          <confirm>false</confirm>
          <userName>admin</userName>
          <inWaitingList>false</inWaitingList>
        </com.atlassian.confluence.extra.calendar3.eventmacro.Reply>
      </list>
      

      The following exception is thrown in the atlassian-confluence.log file:

      com.thoughtworks.xstream.security.ForbiddenClassException: com.atlassian.confluence.extra.calendar3.eventmacro.Reply
      	at com.thoughtworks.xstream.security.NoTypePermission.allows(NoTypePermission.java:26)
      	at com.thoughtworks.xstream.mapper.SecurityMapper.realClass(SecurityMapper.java:74)
      	...
      	at com.atlassian.confluence.impl.xstream.ConfluenceXStreamImpl.fromXML(ConfluenceXStreamImpl.java:49)
      	at com.atlassian.confluence.extra.calendar3.eventmacro.EventMacroManager.getReplyList(EventMacroManager.java:113)
      	at com.atlassian.confluence.extra.calendar3.eventmacro.EventMacroManager.getNumResponders(EventMacroManager.java:479)
      	at com.atlassian.confluence.extra.calendar3.eventmacro.rest.EventResource.createResponse(EventResource.java:152)
      

      NoTypePermission.allows confirms the XStream instance in use permits nothing by default — an allow-list rejection, not a blocklist match. On the test instance, all 17 logged occurrences named this same single class, so the allow-list is otherwise functioning: one plugin-contributed type is failing to reach the instance that needs it.

      Workaround

      Add the affected class to the XStream allow-list using the xstream.allowlist.extra system property, then restart Confluence:

      -Dxstream.allowlist.extra=com.atlassian.confluence.extra.calendar3.eventmacro.Reply
      

      This works because XStreamSecurityConfigurator captures the property in its own field initialiser and merges it into every XStream it configures — including per-plugin instances created later — so it cannot be missed by an early snapshot.

      Verify after restart:

      curl -s -o /dev/null -w '%{http_code}\n' -u <admin>:<pass> \
        'https://<confluence>/rest/calendar-services/1.0/eventmacro/page/<pageId>/macroid/<occurrence>'
      # 200 = resolved, 500 = still failing
      
      grep -c 'ForbiddenClassException: com.atlassian.confluence.extra.calendar3.eventmacro.Reply' \
        <confluence-home>/logs/atlassian-confluence.log
      # the count must not increase after the restart
      

      Existing replies are not lost — they become readable again once the allow-list is correct. To list events that already hold reply data (PostgreSQL):

      SELECT entity_id AS page_id, entity_key
      FROM   os_propertyentry
      WHERE  entity_name = 'confluence_ContentEntityObject'
        AND  entity_key LIKE 'event:%';
      

      Two things that do not work:

      • Restarting Confluence, or disabling and re-enabling the Team Calendars plugin. Both were tested; the failure persisted.
      • -Dxstream.allowlist.enable=false has no effect. On 10.2.14 the return value of isAllowListEnabled() is not consumed; the instance logs Ignoring attempt to disable allowlist via sys prop - this is no longer supported. and the allow-list stays active.

      Scope of testing. Confluence Data Center 10.2.14 (build 9422) with Team Calendars 20.2.15 on PostgreSQL 17.9, single node. Not tested: earlier 10.x releases, any 9.x release, other database engines, or clustered topologies. No bisection was performed, so this should not be assumed to be a 10.2.14 regression — the introducing version is unknown.

      Disclosure. This workaround was derived from the product code and verified in a local lab — 500 -> 200, with the previously unreadable reply returned intact and no further exceptions logged. It is not a vendor-published remedy, and it mitigates the symptom rather than fixing the initialisation ordering.

              Assignee:
              Unassigned
              Reporter:
              Derek Howell
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated: