dotCMS / dotCMS/core

dotAI Security Hardening: RAG permissions, output safety, abuse controls

Open
#37,255 0 comments 0 reactions 1 assignee View on GitHub

@fmontes is already working on this.

Since Aug 27, 2026.

dotCMS : Security Team : Modernization
Dominant language
Java
Stars
970
Forks
486
Avg merge
3d 33m
Merged PRs (30d)
170

Description

Summary

Align the dotAI layer with the platform guarantees the rest of dotCMS already applies: per-user READ permission on retrieval, escaped output at the template boundary, and rate limiting at the REST boundary.

Fixes go at the boundaries, not the call sites, so current and future consumers inherit them.

Background

com.dotcms.ai was built as a feature layer on top of dotCMS and does not route through core enforcement. Retrieval filters on host / content-type / index / language only, viewtools return model output and error detail verbatim, and the REST resources have no rate control. Embedding a content type is an admin decision to make it available to the AI for permitted users, and the retrieval path should reflect that.

Scope

# Change Boundary
#37151 Per-user READ filter on retrieval; summarize uses the filtered list for both prompt and display EmbeddingsAPIImpl.getEmbeddingResults
#37153 Escape/sanitize by default; raw output behind an explicit opt-in accessor com.dotcms.ai.viewtool.*
#37154 Generic error payload to caller, full detail to Logger CompletionsTool.handleException
#37152 Labeled, delimiter-escaped data block + system-prompt guard; query stays in user role CompletionsAPIImpl.buildRequestJson
#37155 Per-user and per-IP rate limit + concurrency cap, config-overridable, 429 CompletionsResource, TextResource, ImageResource, SearchResource

Out of scope

  • AppConfig.debugLogger prompt/response logging. Explicit default-off flag, working as intended.
  • Eliminating prompt injection. #37152 is mitigation; the control for untrusted input stays operational.
  • Per-user result-set caching. EMBEDDING_CACHE keys on hashed query text to vector, so it is not a per-user leak vector; #37151 adds a comment so that does not regress.
  • Agent framework and MCP v2 surfaces. Separate review.
  • Provider-side spend caps and rate-limit policy numbers. Customer-owned.

Epic acceptance

  • Unauthorized user: 0 hits from /api/v1/ai/search, "no matching content" from /api/v1/ai/completions. Authorized user gets the content.
  • No dotAI code path returns a stack trace to a caller or template.
  • Default viewtool accessor escapes <script> / onerror= payloads; only the explicit opt-in returns raw.
  • Burst above the configured limit returns 429; normal usage unaffected.
  • Admin/system indexing, deleteByQuery, and countEmbeddingsByIndex unchanged.
  • Release note covers the two visible behavior changes (#37151 recall, #37153 output) ahead of the release, plus the trust-boundary guidance.

Sequencing

#37151, #37153, #37154 are the commit. #37152 and #37155 are stretch and can move to a later track. #37151 carries the design surface: pagination shortfall under a post-SQL filter, anonymous vs null-user semantics, and the cost of the added contentlet fetch on a large index.

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.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.