Skip to content

Commit 5e79df3

Browse files
committed
Backport of CSP-related changes
1 parent d55a7ba commit 5e79df3

44 files changed

Lines changed: 584 additions & 260 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

action/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<parent>
2323
<groupId>org.glassfish</groupId>
2424
<artifactId>mojarra-parent</artifactId>
25-
<version>4.0.14-SNAPSHOT</version>
25+
<version>4.0.15-SNAPSHOT</version>
2626
</parent>
2727

2828
<groupId>org.eclipse.mojarra</groupId>

cdi/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<parent>
2323
<groupId>org.glassfish</groupId>
2424
<artifactId>mojarra-parent</artifactId>
25-
<version>4.0.14-SNAPSHOT</version>
25+
<version>4.0.15-SNAPSHOT</version>
2626
</parent>
2727

2828
<groupId>org.eclipse.mojarra</groupId>

impl/pom.xml

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
<parent>
3030
<groupId>org.glassfish</groupId>
3131
<artifactId>mojarra-parent</artifactId>
32-
<version>4.0.14-SNAPSHOT</version>
32+
<version>4.0.15-SNAPSHOT</version>
3333
</parent>
3434

3535
<artifactId>jakarta.faces</artifactId>
@@ -280,40 +280,36 @@
280280
<plugins>
281281

282282
<!-- ### C O M P R E S S / M I N I F Y faces.js ### -->
283+
<!-- https://blutorange.github.io/closure-compiler-maven-plugin/minify-mojo.html -->
283284
<plugin>
284-
<groupId>net.alchim31.maven</groupId>
285-
<artifactId>yuicompressor-maven-plugin</artifactId>
286-
<version>1.5.1</version>
285+
<groupId>com.github.blutorange</groupId>
286+
<artifactId>closure-compiler-maven-plugin</artifactId>
287+
<version>2.30.0</version>
287288
<executions>
288289
<execution>
289290
<id>minify-faces-js</id>
290291
<phase>generate-sources</phase>
291292
<goals>
292-
<goal>compress</goal>
293+
<goal>minify</goal>
293294
</goals>
294295
<configuration>
295-
<nosuffix>true</nosuffix>
296-
<preProcessAggregates>true</preProcessAggregates>
297-
<aggregations>
298-
<aggregation>
299-
<includes>
300-
<include>${project.basedir}/src/main/resources/META-INF/resources/jakarta.faces/faces-uncompressed.js</include>
301-
</includes>
302-
<output>${project.build.directory}/generated-resources/yui/faces.js</output>
303-
</aggregation>
304-
</aggregations>
296+
<encoding>UTF-8</encoding>
297+
<baseSourceDir>${project.basedir}/src/main/resources/META-INF/resources/</baseSourceDir>
298+
<baseTargetDir>${project.build.directory}/classes/META-INF/resources/</baseTargetDir>
299+
<sourceDir>jakarta.faces</sourceDir>
300+
<targetDir>jakarta.faces</targetDir>
305301
<includes>
306-
<include>*.js</include>
302+
<include>faces-uncompressed.js</include>
307303
</includes>
308-
<sourceDirectory>${project.build.directory}/generated-resources/yui</sourceDirectory>
309-
<outputDirectory>${project.build.directory}/generated-resources/yui/META-INF/resources/jakarta.faces/</outputDirectory>
304+
<outputFilename>faces.js</outputFilename>
305+
<skipMerge>true</skipMerge>
306+
<closureLanguageOut>NO_TRANSPILE</closureLanguageOut>
310307
</configuration>
311308
</execution>
312309
</executions>
313310
</plugin>
314311

315-
316-
<!-- Adds the paths where the source and resources generated above was stored -->
312+
<!--&lt;!&ndash; Adds the paths where the source and resources generated above was stored &ndash;&gt;
317313
<plugin>
318314
<groupId>org.codehaus.mojo</groupId>
319315
<artifactId>build-helper-maven-plugin</artifactId>
@@ -334,7 +330,7 @@
334330
</configuration>
335331
</execution>
336332
</executions>
337-
</plugin>
333+
</plugin>-->
338334

339335
<plugin>
340336
<groupId>org.apache.maven.plugins</groupId>

impl/src/main/java/com/sun/faces/application/resource/ResourceHandlerImpl.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import static jakarta.servlet.http.HttpServletResponse.SC_NOT_MODIFIED;
3131
import static jakarta.servlet.http.MappingMatch.EXTENSION;
3232
import static java.lang.Boolean.FALSE;
33+
import static java.nio.charset.StandardCharsets.UTF_8;
3334
import static java.util.logging.Level.FINE;
3435
import static java.util.logging.Level.WARNING;
3536

@@ -40,15 +41,19 @@
4041
import java.nio.channels.ReadableByteChannel;
4142
import java.nio.channels.WritableByteChannel;
4243
import java.util.ArrayList;
44+
import java.util.Base64;
4345
import java.util.List;
4446
import java.util.Map;
47+
import java.util.UUID;
4548
import java.util.logging.Level;
4649
import java.util.logging.Logger;
4750
import java.util.regex.Pattern;
4851
import java.util.stream.Stream;
4952

5053
import com.sun.faces.application.ApplicationAssociate;
5154
import com.sun.faces.config.WebConfiguration;
55+
import com.sun.faces.renderkit.html_basic.ScriptRenderer;
56+
import com.sun.faces.renderkit.html_basic.StylesheetRenderer;
5257
import com.sun.faces.util.FacesLogger;
5358
import com.sun.faces.util.RequestStateManager;
5459
import com.sun.faces.util.Util;
@@ -67,10 +72,13 @@ public class ResourceHandlerImpl extends ResourceHandler {
6772
// Log instance for this class
6873
private static final Logger LOGGER = FacesLogger.APPLICATION.getLogger();
6974

75+
private static final String CURRENT_NONCE = ResourceHandlerImpl.class.getName() + ".currentNonce";
76+
7077
ResourceManager manager;
7178
List<Pattern> excludePatterns;
7279
private long creationTime;
7380
private long maxAge;
81+
private boolean cspEnabled;
7482
private WebConfiguration webconfig;
7583

7684
// ------------------------------------------------------------ Constructors
@@ -85,6 +93,7 @@ public ResourceHandlerImpl() {
8593
manager = ApplicationAssociate.getInstance(extContext).getResourceManager();
8694
initExclusions(extContext.getApplicationMap());
8795
initMaxAge();
96+
cspEnabled = webconfig.isSet(WebConfiguration.WebContextInitParameter.CspNonceEnabled);
8897
}
8998

9099
// ------------------------------------------- Methods from Resource Handler
@@ -231,6 +240,21 @@ public String getRendererTypeForResourceName(String resourceName) {
231240
return rendererType;
232241
}
233242

243+
private static String getResourceType(String contentType) {
244+
if (contentType == null) {
245+
return null;
246+
}
247+
248+
final String type = contentType.toLowerCase();
249+
if (type.equals(ScriptRenderer.DEFAULT_CONTENT_TYPE)) {
250+
return "script";
251+
} else if (type.equals(StylesheetRenderer.DEFAULT_CONTENT_TYPE)) {
252+
return "style";
253+
}
254+
255+
return null;
256+
}
257+
234258
/**
235259
* @see jakarta.faces.application.ResourceHandler#handleResourceRequest(jakarta.faces.context.FacesContext)
236260
*/
@@ -381,6 +405,23 @@ private void send304(FacesContext ctx) {
381405
ctx.getExternalContext().setResponseStatus(SC_NOT_MODIFIED);
382406
}
383407

408+
@Override
409+
public String getCurrentNonce(FacesContext context) {
410+
if (cspEnabled) {
411+
var viewMap = context.getViewRoot().getViewMap(true);
412+
var nonce = (String) viewMap.get(CURRENT_NONCE);
413+
414+
if (nonce == null) {
415+
nonce = Base64.getEncoder().encodeToString(UUID.randomUUID().toString().getBytes(UTF_8));
416+
viewMap.put(CURRENT_NONCE, nonce);
417+
}
418+
419+
return nonce;
420+
}
421+
422+
return null;
423+
}
424+
384425
// ------------------------------------------------- Package Private Methods
385426

386427
/**
@@ -556,6 +597,9 @@ private void handleHeaders(FacesContext ctx, Resource resource) {
556597
for (Map.Entry<String, String> cur : resource.getResponseHeaders().entrySet()) {
557598
extContext.setResponseHeader(cur.getKey(), cur.getValue());
558599
}
600+
if (cspEnabled && "script".equals(getResourceType(resource.getContentType()))) {
601+
extContext.addResponseHeader("Content-Security-Policy", "default-src 'none'; script-src 'self'");
602+
}
559603
}
560604

561605
private ByteBuffer allocateByteBuffer() {

impl/src/main/java/com/sun/faces/application/view/FaceletViewHandlingStrategy.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,12 @@ public void renderView(FacesContext ctx, UIViewRoot viewToRender) throws IOExcep
424424
FormOmittedChecker.check(ctx);
425425
}
426426

427+
// Add CSP header if necessary
428+
String nonce = ctx.getApplication().getResourceHandler().getCurrentNonce(ctx);
429+
if (nonce != null) {
430+
ctx.getExternalContext().addResponseHeader("Content-Security-Policy", "script-src 'self' 'nonce-" + nonce + "'");
431+
}
432+
427433
// Render the XML declaration to the response
428434
String xmlDecl = getXMLDECLFromFacesContextAttributes(ctx);
429435
if (xmlDecl != null) {

impl/src/main/java/com/sun/faces/config/WebConfiguration.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,7 @@ public enum WebContextInitParameter {
784784
ClientWindowMode(ClientWindow.CLIENT_WINDOW_MODE_PARAM_NAME, "none"),
785785
WebAppResourcesDirectory(ResourceHandler.WEBAPP_RESOURCES_DIRECTORY_PARAM_NAME, "/resources"),
786786
WebAppContractsDirectory(ResourceHandler.WEBAPP_CONTRACTS_DIRECTORY_PARAM_NAME, "/contracts"),
787+
CspNonceEnabled(ResourceHandler.ENABLE_CSP_NONCE, ""),
787788
;
788789

789790
private String defaultValue;

impl/src/main/java/com/sun/faces/facelets/tag/ui/UIDebug.java

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,15 @@
2222
import java.util.List;
2323
import java.util.Map;
2424

25-
import com.sun.faces.facelets.util.DevTools;
26-
import com.sun.faces.facelets.util.FastWriter;
27-
import com.sun.faces.renderkit.RenderKitUtils;
28-
import com.sun.faces.renderkit.html_basic.ScriptRenderer;
29-
3025
import jakarta.faces.component.UIComponentBase;
3126
import jakarta.faces.context.FacesContext;
3227
import jakarta.faces.context.ResponseWriter;
3328
import jakarta.servlet.http.HttpServletResponse;
3429

30+
import com.sun.faces.facelets.util.DevTools;
31+
import com.sun.faces.facelets.util.FastWriter;
32+
import com.sun.faces.renderkit.RenderKitUtils;
33+
3534
/**
3635
* @author Jacob Hookom
3736
*/
@@ -103,14 +102,9 @@ public void encodeBegin(FacesContext facesContext) throws IOException {
103102
ResponseWriter writer = facesContext.getResponseWriter();
104103
writer.startElement("span", this);
105104
writer.writeAttribute("id", getClientId(facesContext), "id");
106-
writer.startElement("script", this);
107105

108-
if (!RenderKitUtils.isOutputHtml5Doctype(facesContext)) {
109-
writer.writeAttribute("type", ScriptRenderer.DEFAULT_CONTENT_TYPE, "type");
110-
}
106+
RenderKitUtils.renderScript(facesContext, this, null, sb.toString());
111107

112-
writer.writeText(sb.toString(), this, null);
113-
writer.endElement("script");
114108
writer.endElement("span");
115109
}
116110
}

0 commit comments

Comments
 (0)