mirror of
https://github.com/HangarMC/Hangar.git
synced 2024-12-03 06:22:35 +08:00
Disgusting hacks to allow video embed and links
... before we either use a different sanitization lib or figure out how to move the sanitization before the markdown renderer without destroying plain text
This commit is contained in:
parent
d21dd69987
commit
4dc4c37559
@ -130,16 +130,16 @@ async function requireGlobalPerm(authStore: ReturnType<typeof useAuthStore>, to:
|
||||
permissions: toNamedPermission(to.meta.requireGlobalPerm as string[]),
|
||||
}).catch((e) => {
|
||||
try {
|
||||
console.log("erro!", e);
|
||||
console.log("error!", e);
|
||||
handleRequestError(e, useContext(), useI18n());
|
||||
} catch (e2) {
|
||||
console.log("error while checking perm", e);
|
||||
console.log("encountered additional error while error handling", e2);
|
||||
}
|
||||
});
|
||||
console.log("result", check);
|
||||
console.debug("result", check);
|
||||
if (check && (check.type !== PermissionType.GLOBAL || !check.result)) {
|
||||
console.log("404?");
|
||||
console.debug("404?");
|
||||
return useErrorRedirect(to, 404, "Not found");
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import com.vladsch.flexmark.parser.Parser;
|
||||
import com.vladsch.flexmark.util.ast.Node;
|
||||
import com.vladsch.flexmark.util.data.MutableDataSet;
|
||||
import io.papermc.hangar.config.hangar.HangarConfig;
|
||||
import io.papermc.hangar.util.HtmlSanitizerUtil;
|
||||
import io.papermc.hangar.util.HtmlSanitizer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -40,10 +40,12 @@ public class MarkdownService {
|
||||
private final Parser markdownParser;
|
||||
private final MutableDataSet options;
|
||||
private final HangarConfig config;
|
||||
private final HtmlSanitizer sanitizer;
|
||||
|
||||
@Autowired
|
||||
public MarkdownService(HangarConfig config) {
|
||||
public MarkdownService(HangarConfig config, final HtmlSanitizer sanitizer) {
|
||||
this.config = config;
|
||||
this.sanitizer = sanitizer;
|
||||
|
||||
options = new MutableDataSet()
|
||||
.set(AnchorLinkExtension.ANCHORLINKS_TEXT_SUFFIX, "<svg class=\"ml-2 text-xl\" preserveAspectRatio=\"xMidYMid meet\" viewBox=\"0 0 24 24\" width=\"1.2em\" height=\"1.2em\"><path fill=\"currentColor\" d=\"M10.59 13.41c.41.39.41 1.03 0 1.42c-.39.39-1.03.39-1.42 0a5.003 5.003 0 0 1 0-7.07l3.54-3.54a5.003 5.003 0 0 1 7.07 0a5.003 5.003 0 0 1 0 7.07l-1.49 1.49c.01-.82-.12-1.64-.4-2.42l.47-.48a2.982 2.982 0 0 0 0-4.24a2.982 2.982 0 0 0-4.24 0l-3.53 3.53a2.982 2.982 0 0 0 0 4.24m2.82-4.24c.39-.39 1.03-.39 1.42 0a5.003 5.003 0 0 1 0 7.07l-3.54 3.54a5.003 5.003 0 0 1-7.07 0a5.003 5.003 0 0 1 0-7.07l1.49-1.49c-.01.82.12 1.64.4 2.43l-.47.47a2.982 2.982 0 0 0 0 4.24a2.982 2.982 0 0 0 4.24 0l3.53-3.53a2.982 2.982 0 0 0 0-4.24a.973.973 0 0 1 0-1.42Z\"></path></svg>")
|
||||
@ -62,12 +64,13 @@ public class MarkdownService {
|
||||
AutolinkExtension.create(),
|
||||
AnchorLinkExtension.create(),
|
||||
StrikethroughExtension.create(),
|
||||
TaskListExtension.create(),
|
||||
TablesExtension.create(),
|
||||
TypographicExtension.create(),
|
||||
WikiLinkExtension.create(),
|
||||
EmojiExtension.create(),
|
||||
FootnoteExtension.create(),
|
||||
//TODO readd after sanitization is fixed
|
||||
//TaskListExtension.create(),
|
||||
//FootnoteExtension.create(),
|
||||
AdmonitionExtension.create(),
|
||||
GitLabExtension.create(),
|
||||
YouTubeLinkExtension.create(),
|
||||
@ -102,7 +105,7 @@ public class MarkdownService {
|
||||
|
||||
// Render markdown and then sanitize html
|
||||
input = htmlRenderer.render(markdownParser.parse(input));
|
||||
return HtmlSanitizerUtil.sanitize(input);
|
||||
return sanitizer.sanitize(input);
|
||||
}
|
||||
|
||||
static class RenderSettings {
|
||||
|
71
src/main/java/io/papermc/hangar/util/HtmlSanitizer.java
Normal file
71
src/main/java/io/papermc/hangar/util/HtmlSanitizer.java
Normal file
@ -0,0 +1,71 @@
|
||||
package io.papermc.hangar.util;
|
||||
|
||||
import io.papermc.hangar.config.hangar.HangarConfig;
|
||||
import java.util.List;
|
||||
import org.owasp.html.HtmlPolicyBuilder;
|
||||
import org.owasp.html.HtmlStreamEventReceiver;
|
||||
import org.owasp.html.HtmlStreamEventReceiverWrapper;
|
||||
import org.owasp.html.PolicyFactory;
|
||||
import org.owasp.html.Sanitizers;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public final class HtmlSanitizer {
|
||||
|
||||
private final PolicyFactory sanitizer;
|
||||
|
||||
@Autowired
|
||||
public HtmlSanitizer(final HangarConfig config) {
|
||||
//TODO remove this disgusting hack when we can put the sanitizer before the markdown renderer
|
||||
final PolicyFactory links = new HtmlPolicyBuilder().withPostprocessor((HtmlStreamEventReceiver r) -> new HtmlStreamEventReceiverWrapper(r) {
|
||||
@Override
|
||||
public void openTag(final String elementName, final List<String> attrs) {
|
||||
if (!"a".equals(elementName)) {
|
||||
super.openTag(elementName, attrs);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0, n = attrs.size(); i < n; i += 2) {
|
||||
if (!"href".equals(attrs.get(i))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final String url = attrs.get(i + 1);
|
||||
final String safeUrl = config.security.makeSafe(url);
|
||||
if (!url.equals(safeUrl)) {
|
||||
attrs.set(i + 1, safeUrl);
|
||||
}
|
||||
}
|
||||
super.openTag(elementName, attrs);
|
||||
}
|
||||
}).allowStandardUrlProtocols().allowElements("a").allowAttributes("href", "id", "class").onElements("a").toFactory();
|
||||
final PolicyFactory iframes = new HtmlPolicyBuilder().withPostprocessor((HtmlStreamEventReceiver r) -> new HtmlStreamEventReceiverWrapper(r) {
|
||||
@Override
|
||||
public void openTag(final String elementName, final List<String> attrs) {
|
||||
if (!"iframe".equals(elementName)) {
|
||||
super.openTag(elementName, attrs);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0, n = attrs.size(); i < n; i += 2) {
|
||||
if ("src".equals(attrs.get(i)) && !attrs.get(i + 1).startsWith("https://www.youtube-nocookie.com/embed/")) {
|
||||
// Only allow YouTube video embeds
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.openTag(elementName, attrs);
|
||||
}
|
||||
}).allowUrlProtocols("https").allowElements("iframe").allowAttributes("src", "allowfullscreen", "border", "height", "width", "frameborder", "allow", "class").onElements("iframe").toFactory();
|
||||
|
||||
final PolicyFactory images = new HtmlPolicyBuilder().allowStandardUrlProtocols().allowElements("img", "svg", "path")
|
||||
.allowAttributes("alt", "src", "border", "height", "width", "preserveAspectRatio", "viewBox", "class").onElements("img", "svg") // TODO don't allow class attribute
|
||||
.allowAttributes("fill", "d").onElements("path").toFactory();
|
||||
sanitizer = Sanitizers.FORMATTING.and(Sanitizers.BLOCKS).and(Sanitizers.TABLES).and(Sanitizers.STYLES)
|
||||
.and(images).and(links).and(iframes).and(new HtmlPolicyBuilder().allowElements("pre", "details", "summary", "hr").toFactory());
|
||||
}
|
||||
|
||||
public String sanitize(final String input) {
|
||||
return sanitizer.sanitize(input);
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package io.papermc.hangar.util;
|
||||
|
||||
import org.owasp.html.HtmlPolicyBuilder;
|
||||
import org.owasp.html.PolicyFactory;
|
||||
import org.owasp.html.Sanitizers;
|
||||
|
||||
public final class HtmlSanitizerUtil {
|
||||
|
||||
private static final PolicyFactory IMAGES = new HtmlPolicyBuilder().allowUrlProtocols("https").allowElements("img")
|
||||
.allowAttributes("alt", "src").onElements("img").allowAttributes("border", "height", "width").onElements("img").toFactory();
|
||||
private static final PolicyFactory SANITIZER = Sanitizers.FORMATTING.and(Sanitizers.BLOCKS).and(IMAGES).and(Sanitizers.TABLES).and(Sanitizers.STYLES)
|
||||
.and(new HtmlPolicyBuilder().allowElements("pre", "details", "summary").toFactory());
|
||||
|
||||
public static String sanitize(final String input) {
|
||||
return SANITIZER.sanitize(input);
|
||||
}
|
||||
}
|
@ -165,6 +165,10 @@ hangar:
|
||||
safe-download-hosts:
|
||||
- "github.com"
|
||||
- "youtu.be"
|
||||
- "youtube.com"
|
||||
- "papermc.io"
|
||||
- "discord.gg"
|
||||
- "markdownguide.org"
|
||||
|
||||
discourse:
|
||||
enabled: false
|
||||
|
Loading…
Reference in New Issue
Block a user