Skip to content

[SITES-40889] [Core Components] Add support in Fragment component for CFVT#3015

Open
alexandru-stancioiu wants to merge 17 commits intomainfrom
sites_40889
Open

[SITES-40889] [Core Components] Add support in Fragment component for CFVT#3015
alexandru-stancioiu wants to merge 17 commits intomainfrom
sites_40889

Conversation

@alexandru-stancioiu
Copy link
Copy Markdown
Contributor

Q                       A
Fixed Issues? Fixes #1, Fixes #2
Patch: Bug Fix?
Minor: New Feature?
Major: Breaking Change?
Tests Added + Pass? Yes
Documentation Provided Yes (code comments and or markdown)
Any Dependency Changes?
License Apache License, Version 2.0

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 9, 2026

Codecov Report

❌ Patch coverage is 89.65517% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...models/v1/contentfragment/ContentFragmentImpl.java 88.00% 2 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

String templateId = request.getParameter("templateId");
String variation = request.getParameter("variation");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(buildVcfHtml(fragmentId, templateId, variation));

Check warning

Code scanning / CodeQL

Cross-site scripting

Cross-site scripting vulnerability due to a [user-provided value](1). Cross-site scripting vulnerability due to a [user-provided value](2). Cross-site scripting vulnerability due to a [user-provided value](3).

Copilot Autofix

AI 20 days ago

In general, to fix cross-site scripting in servlets, all user-controlled data that is written into HTML should be encoded using a well-established, context-appropriate escaping library (for example, OWASP Java Encoder or Apache Commons Text) rather than handcrafted string replacement. This ensures correct and complete escaping for the specific HTML context and makes static analysis tools recognize the data as properly sanitized.

For this file, the best fix is to replace the custom escapeHtml implementation with one that delegates to a standard encoding routine from a known library, without changing the public behavior of the servlet. We should also keep the method signature so the rest of the code remains unchanged. A practical choice, without modifying other imports, is to add an import for org.apache.commons.text.StringEscapeUtils and implement escapeHtml by calling StringEscapeUtils.escapeHtml4(input). That encoder correctly escapes characters necessary for safe inclusion in HTML, including both single and double quotes, and is widely recognized. The changes are limited to:

  • Adding an import at the top of MockVCFServlet.java for org.apache.commons.text.StringEscapeUtils.
  • Replacing the body of escapeHtml (lines 131–138) with a call to StringEscapeUtils.escapeHtml4(input) while preserving the null check and method signature.

No other methods or call sites need to change, since appendRow and buildVcfHtml already use escapeHtml consistently.


Suggested changeset 2
testing/it/it.core/src/main/java/com/adobe/cq/wcm/core/components/it/support/MockVCFServlet.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/testing/it/it.core/src/main/java/com/adobe/cq/wcm/core/components/it/support/MockVCFServlet.java b/testing/it/it.core/src/main/java/com/adobe/cq/wcm/core/components/it/support/MockVCFServlet.java
--- a/testing/it/it.core/src/main/java/com/adobe/cq/wcm/core/components/it/support/MockVCFServlet.java
+++ b/testing/it/it.core/src/main/java/com/adobe/cq/wcm/core/components/it/support/MockVCFServlet.java
@@ -24,6 +24,7 @@
 import org.apache.sling.api.servlets.SlingAllMethodsServlet;
 import org.apache.sling.servlets.annotations.SlingServletPaths;
 import org.osgi.service.component.annotations.Component;
+import org.apache.commons.text.StringEscapeUtils;
 
 /**
  * Local-development mock for the Content Fragment Visualization API.
@@ -132,10 +133,7 @@
         if (input == null) {
             return "";
         }
-        return input.replace("&", "&amp;")
-                     .replace("<", "&lt;")
-                     .replace(">", "&gt;")
-                     .replace("\"", "&quot;");
+        return StringEscapeUtils.escapeHtml4(input);
     }
 
     private static String escapeJson(String input) {
EOF
@@ -24,6 +24,7 @@
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.servlets.annotations.SlingServletPaths;
import org.osgi.service.component.annotations.Component;
import org.apache.commons.text.StringEscapeUtils;

/**
* Local-development mock for the Content Fragment Visualization API.
@@ -132,10 +133,7 @@
if (input == null) {
return "";
}
return input.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
.replace("\"", "&quot;");
return StringEscapeUtils.escapeHtml4(input);
}

private static String escapeJson(String input) {
testing/it/it.core/pom.xml
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/testing/it/it.core/pom.xml b/testing/it/it.core/pom.xml
--- a/testing/it/it.core/pom.xml
+++ b/testing/it/it.core/pom.xml
@@ -202,6 +202,11 @@
             <artifactId>org.apache.sling.servlets.annotations</artifactId>
             <version>1.2.6</version>
         </dependency>
-    </dependencies>
+        <dependency>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-text</artifactId>
+        <version>1.15.0</version>
+    </dependency>
+</dependencies>
 
 </project>
EOF
@@ -202,6 +202,11 @@
<artifactId>org.apache.sling.servlets.annotations</artifactId>
<version>1.2.6</version>
</dependency>
</dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.15.0</version>
</dependency>
</dependencies>

</project>
This fix introduces these dependencies
Package Version Security advisories
org.apache.commons:commons-text (maven) 1.15.0 None
Copilot is powered by AI and may make mistakes. Always verify output.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexandru-stancioiu , this may need to be fixed because it's likely getting deployed to AEM CS instances.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a mock servlet used for ITs

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, since it is a mock servlet used for ITs, it won't get deployed to AEMaaCS

@LSantha
Copy link
Copy Markdown
Contributor

LSantha commented Mar 11, 2026

@alexandru-stancioiu , it would be nice to add an example if possible for this cool new feature in the examples subproject so that it would show up here https://www.aemcomponents.dev/content/core-components-examples/library/core-content/content-fragment.html . Then people can see it already shortly after the new release.
@vladbailescu , wdyt?

…ialog

The dynamically-populated Coral Select for VCF templates has no
server-side items, so Coral loses the stored JCR value on dialog load.
Read the stored vcfTemplate from the component resource via an async
fetch and use it as fallback when populating the dropdown.

Added Karma/Jasmine tests for VCF template retention scenarios.

Made-with: Cursor
@alexandru-stancioiu alexandru-stancioiu force-pushed the sites_40889 branch 3 times, most recently from 13cfd81 to 86df6e9 Compare March 13, 2026 06:55
Alexandru Marian Stancioiu and others added 2 commits March 13, 2026 08:55
Add a VCF display mode example to the Content Fragment examples page,
showing the component configured with displayMode=vcf and a template.
The visual preview requires AEM as a Cloud Service.

Made-with: Cursor
@alexandru-stancioiu
Copy link
Copy Markdown
Contributor Author

Unfortunately we cannot make the visual preview on the aemcomponents.dev website work because we cannot serve any template client-side, it works only on AEMaaCS.
MockVCFServlet doesn't help either because it handles author-side dialog requests only.

Alexandru Marian Stancioiu and others added 6 commits March 25, 2026 23:37
- Rename getVcfPublishUrl to getVcfRenderUrl
- Author: use preview API /sites/cf/fragments/{id}/preview
- Publish: use delivery URL /contentFragments/{templateId}/{id}/{variation}.html
- HTL uses model-generated URL via data-vcf-url attribute instead of hardcoding

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Use shadow DOM to isolate VCF template HTML and CSS from the host page,
preventing style leakage in both directions.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Cover the buildAuthorPreviewUrl() code path with tests that set
the run mode to "author", verifying the preview API URL format
with template, variation, master variation, and without template.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
- Add site clientlib (vcf.js) for View as Published / publish rendering
  with shadow DOM isolation and IMS Bearer token for author preview API
- Add vcfTemplatesApiBase and isVcfAuthRequired to ContentFragment model
  to expose templates API URL and auth flag via data attributes in HTL
- Refactor editDialog.js to read templates API from DOM/HTML fallback
  instead of hardcoding; use $.when() for deferred coordination
- Refactor vcfRenderer.js to read URL from data-cmp-contentfragment-vcf-url
  attribute (model-generated) instead of constructing it client-side
- Add hidden div with vcfTemplatesApiBase for unconfigured components
  so dialog can discover the templates API on pages with no VCF elements
- Refactor mockvcf.js: extract rewriteUrlIfNeeded(), separate templates
  API base collection from VCF URL scan, add XHR interceptor for
  Granite HTTP layer, guard duplicate MutationObservers
- Extract VCF_DISPLAY_MODE constant and isVcfMode() helper in Java model
- Clear LOADING_ATTR on success and error in vcfRenderer.js
- Guard attachShadow against double-call in vcf.js

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Replace hardcoded VCF URL constants in ContentFragmentImpl with injected
VcfUrlProvider OSGi service from cq-dam-cfm-api. The service returns
URLs based on the FT_CFVS_GA feature toggle state.

- Add cq-dam-cfm-api 1.4.61-SNAPSHOT dependency and vcf package import
- Inject VcfUrlProvider in ContentFragmentImpl
- Add GA URL tests (FT enabled) alongside existing legacy URL tests
- Register mock VcfUrlProvider in AbstractContentFragmentTest

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants