dotCMS / dotCMS/core

Derived Contentlet map properties can silently overwrite declared fields (shortyId, titleImage, hasTitleImage, urlMap)

Open
#37,606 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Type : Defect
Dominant language
Java
Stars
970
Forks
486
Avg merge
3d 33m
Merged PRs (30d)
170

Description

Problem Statement

The Contentlet map is one flat namespace holding both stored field values and derived
properties
computed at read time. FieldFactoryImpl.RESERVED_FIELD_VARS stops a Content Type
declaring a field whose variable collides with a derived key — but it does not cover all of them.

Measured against the current list (34 reserved keys):

Derived key written by DefaultTransformStrategy.addCommonProperties Reserved?
host, modUserName, ownerUserName, creationDate, publishUser, publishUserName
shortyId collidable
titleImage collidable
hasTitleImage collidable
urlMap collidable
hostName ❌ — fixed in #37589

For any unreserved key, a customer can legally declare a field with that variable and every
transform will silently overwrite the stored value with the derived one
. That is exactly the
defect reported in #37584, where hostName collided with the Host Content Type's own "Site Key"
field and every Site reported System Host.

Severity / Impact: silent data misreporting on the REST read path for any Content Type that
declares one of these variables. Unlike #37584 there is no shipped Content Type that does so today,
so this is latent rather than active — which is why it was kept out of #37589's scope.

Suggested Fix

Two options, not mutually exclusive:

  1. Extend the guard. DefaultTransformStrategy.declaresField(type, key) (added in #37589)
    already expresses the rule "a declared field beats a derived property". Apply it to the
    remaining keys, with the same sentinel fallback so the map keeps its non-null guarantee.
  2. Close the hole at the source. Add the unreserved derived keys to RESERVED_FIELD_VARS so
    new Content Types cannot declare them. This does not help Content Types that already have
    such a field — and would make them unsaveable — so it complements (1) rather than replacing it.

Worth recording the precedence rule as an ADR in dotCMS/platform-adrs: stored field values take
precedence over derived properties in the Contentlet map.
Proposed, not written, in #37589's plan.

Notes

Follow-up to #37584 / #37589, which fixed the one active instance (hostName) and deliberately
left the general rule for a separate change. The legacy ContentletToMapTransformer carries the
same writes and needs the same treatment.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with DefaultTransformStrategy.addCommonProperties and declaresField, then compare the corresponding writes in the legacy ContentletToMapTransformer. Review FieldFactoryImpl.RESERVED_FIELD_VARS and the follow-up issues for the intended precedence rule; done means declared stored values are not overwritten for shortyId, titleImage, hasTitleImage, or urlMap, while the map retains its non-null guarantee.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.