dotAI Security Hardening: RAG permissions, output safety, abuse controls
@fmontes is already working on this.
Since Aug 27, 2026.
- 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.debugLoggerprompt/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_CACHEkeys 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, andcountEmbeddingsByIndexunchanged. - 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.