This is an automated email from the ASF dual-hosted git repository. ahuber pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push: new 00bd1196c3 ISIS-3077: refactor hardening utilities into their own class 00bd1196c3 is described below commit 00bd1196c3ac342460d17833430926d03cec540b Author: Andi Huber <ahu...@apache.org> AuthorDate: Thu Jun 23 09:59:30 2022 +0200 ISIS-3077: refactor hardening utilities into their own class --- .../isis/applib/value/LocalResourcePath.java | 4 +- .../java/org/apache/isis/applib/value/Markup.java | 3 +- .../isis/commons/internal/base/_Strings.java | 40 ------------ .../commons/internal/hardening/_Hardening.java | 75 ++++++++++++++++++++++ .../valuesemantics/URLValueSemantics.java | 3 +- 5 files changed, 81 insertions(+), 44 deletions(-) diff --git a/api/applib/src/main/java/org/apache/isis/applib/value/LocalResourcePath.java b/api/applib/src/main/java/org/apache/isis/applib/value/LocalResourcePath.java index 532365b983..d46c7eb637 100644 --- a/api/applib/src/main/java/org/apache/isis/applib/value/LocalResourcePath.java +++ b/api/applib/src/main/java/org/apache/isis/applib/value/LocalResourcePath.java @@ -30,7 +30,7 @@ import org.springframework.lang.Nullable; import org.apache.isis.applib.IsisModuleApplib; import org.apache.isis.applib.annotation.Value; import org.apache.isis.commons.internal.base._Blackhole; -import org.apache.isis.commons.internal.base._Strings; +import org.apache.isis.commons.internal.hardening._Hardening; import lombok.Getter; import lombok.NonNull; @@ -122,7 +122,7 @@ public final class LocalResourcePath implements Serializable { } try { // path syntax check - _Blackhole.consume(_Strings.toUrlWithXssGuard("http://localhost/"+path)); + _Blackhole.consume(_Hardening.toUrlWithXssGuard("http://localhost/"+path)); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(String.format("the given local path has an invalid syntax: '%s'", path), e); } diff --git a/api/applib/src/main/java/org/apache/isis/applib/value/Markup.java b/api/applib/src/main/java/org/apache/isis/applib/value/Markup.java index ce293d3b55..fcf9495bca 100644 --- a/api/applib/src/main/java/org/apache/isis/applib/value/Markup.java +++ b/api/applib/src/main/java/org/apache/isis/applib/value/Markup.java @@ -31,6 +31,7 @@ import org.apache.isis.applib.IsisModuleApplib; import org.apache.isis.applib.annotation.Value; import org.apache.isis.commons.internal.base._Strings; import org.apache.isis.commons.internal.base._Text; +import org.apache.isis.commons.internal.hardening._Hardening; import lombok.EqualsAndHashCode; @@ -79,7 +80,7 @@ public final class Markup implements Serializable { } private String validate(final String html) { - return _Strings.htmlNoScript(html); + return _Hardening.htmlNoScript(html); } public static final class JaxbToStringAdapter extends XmlAdapter<String, Markup> { diff --git a/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings.java b/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings.java index cafa922efa..f549e13d69 100644 --- a/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings.java +++ b/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings.java @@ -21,8 +21,6 @@ package org.apache.isis.commons.internal.base; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.PrintStream; -import java.net.MalformedURLException; -import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Arrays; @@ -537,44 +535,6 @@ public final class _Strings { return grep(input, matcher); } - // -- XSS GUARDS - - /** - * @throws IllegalArgumentException - when an XSS attack is encountered, or the URL is not parseable - * @implNote unfortunately has potential for false positives; but shall do for now - */ - public static Optional<URL> toUrlWithXssGuard(final @Nullable String urlString) { - if(urlString==null) { - return Optional.empty(); - } - if(_Strings.condenseWhitespaces(urlString.toLowerCase(), "").contains("javascript:")) { - // simple guard against XSS attacks like javascript:alert(document) - throw new IllegalArgumentException("Not parseable as an URL ('" + urlString + "')."); - } - try { - return Optional.of(new java.net.URL(urlString)); - } catch (final MalformedURLException ex) { - throw new IllegalArgumentException("Not parseable as an URL ('" + urlString + "').", ex); - } - } - - /** - * @throws IllegalArgumentException - when scripts are encountered - * @implNote unfortunately has potential for false positives; but shall do for now - */ - public static String htmlNoScript(final @Nullable String html) { - if(html==null) { - return null; - } - val condensed = _Strings.condenseWhitespaces(html.toLowerCase(), ""); - if(condensed.contains("javascript:") - || condensed.contains("<script")) { - throw new IllegalArgumentException("Not parseable as html free of scripts content."); - } - return html; - } - - // -- REPLACEMENT OPERATORS /** diff --git a/commons/src/main/java/org/apache/isis/commons/internal/hardening/_Hardening.java b/commons/src/main/java/org/apache/isis/commons/internal/hardening/_Hardening.java new file mode 100644 index 0000000000..c59854e196 --- /dev/null +++ b/commons/src/main/java/org/apache/isis/commons/internal/hardening/_Hardening.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.isis.commons.internal.hardening; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Optional; + +import org.springframework.lang.Nullable; + +import org.apache.isis.commons.internal.base._Strings; + +import lombok.val; + +/** + * Various hardening utilities. + * <p> + * Introduced as a consequence of ISIS-3077. + */ +public class _Hardening { + + // -- XSS GUARDS + + /** + * @throws IllegalArgumentException - when an XSS attack is encountered, or the URL is not parseable + * @implNote unfortunately has potential for false positives; but shall do for now + */ + public static Optional<URL> toUrlWithXssGuard(final @Nullable String urlString) { + if(urlString==null) { + return Optional.empty(); + } + if(_Strings.condenseWhitespaces(urlString.toLowerCase(), "").contains("javascript:")) { + // simple guard against XSS attacks like javascript:alert(document) + throw new IllegalArgumentException("Not parseable as an URL ('" + urlString + "')."); + } + try { + return Optional.of(new java.net.URL(urlString)); + } catch (final MalformedURLException ex) { + throw new IllegalArgumentException("Not parseable as an URL ('" + urlString + "').", ex); + } + } + + /** + * @throws IllegalArgumentException - when scripts are encountered + * @implNote unfortunately has potential for false positives; but shall do for now + */ + public static String htmlNoScript(final @Nullable String html) { + if(html==null) { + return null; + } + val condensed = _Strings.condenseWhitespaces(html.toLowerCase(), ""); + if(condensed.contains("javascript:") + || condensed.contains("<script")) { + throw new IllegalArgumentException("Not parseable as html free of scripts content."); + } + return html; + } + +} diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/URLValueSemantics.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/URLValueSemantics.java index 2d0109a923..77c1a75bd5 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/URLValueSemantics.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/URLValueSemantics.java @@ -32,6 +32,7 @@ import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract; import org.apache.isis.applib.value.semantics.ValueSemanticsProvider; import org.apache.isis.commons.collections.Can; import org.apache.isis.commons.internal.base._Strings; +import org.apache.isis.commons.internal.hardening._Hardening; import org.apache.isis.schema.common.v2.ValueType; import lombok.SneakyThrows; @@ -107,7 +108,7 @@ implements if(input==null) { return null; } - return _Strings.toUrlWithXssGuard(input).orElse(null); + return _Hardening.toUrlWithXssGuard(input).orElse(null); } @Override