Move email html body sanitization to the EmailTemplate.render

This change moves the sanitization of the html body of emails to render time instead of at message send time.
Move the sanitization code the the EmailTemplate class.
Add <hr> tag to allowed html tags.
Add global setting `watcher.actions.email.sanitize_html` that defaults to true. If this is set to false html sanitization will be disabled
Add documentation for sanitization disable setting.
Enhance email tests to verify that sanitization is happening at construction time.

Fixes elastic/elasticsearch#356

Original commit: elastic/x-pack-elasticsearch@282a2d85c2
This commit is contained in:
Brian Murphy 2015-05-03 23:45:19 -04:00
parent 5e9f747005
commit e6c4b53bf8
11 changed files with 238 additions and 106 deletions

View File

@ -113,8 +113,8 @@ public class EmailAction implements Action {
return builder.endObject();
}
public static EmailAction parse(String watchId, String actionId, XContentParser parser) throws IOException {
EmailTemplate.Parser emailParser = new EmailTemplate.Parser();
public static EmailAction parse(String watchId, String actionId, XContentParser parser, boolean sanitizeHtmlBody) throws IOException {
EmailTemplate.Parser emailParser = new EmailTemplate.Parser(sanitizeHtmlBody);
String account = null;
String user = null;
Secret password = null;

View File

@ -23,12 +23,16 @@ public class EmailActionFactory extends ActionFactory<EmailAction, EmailAction.R
private final EmailService emailService;
private final TemplateEngine templateEngine;
private final boolean sanitizeHtmlBodyOfEmails;
private static String SANITIZE_HTML_SETTING = "watcher.actions.email.sanitize_html";
@Inject
public EmailActionFactory(Settings settings, EmailService emailService, TemplateEngine templateEngine) {
super(Loggers.getLogger(ExecutableEmailAction.class, settings));
this.emailService = emailService;
this.templateEngine = templateEngine;
sanitizeHtmlBodyOfEmails = settings.getAsBoolean(SANITIZE_HTML_SETTING, true);
}
@Override
@ -38,7 +42,7 @@ public class EmailActionFactory extends ActionFactory<EmailAction, EmailAction.R
@Override
public EmailAction parseAction(String watchId, String actionId, XContentParser parser) throws IOException {
return EmailAction.parse(watchId, actionId, parser);
return EmailAction.parse(watchId, actionId, parser, sanitizeHtmlBodyOfEmails);
}
@Override

View File

@ -15,6 +15,7 @@ import org.elasticsearch.watcher.support.Variables;
import org.elasticsearch.watcher.support.template.TemplateEngine;
import org.elasticsearch.watcher.watch.Payload;
import java.util.HashMap;
import java.util.Map;
/**
@ -33,11 +34,16 @@ public class ExecutableEmailAction extends ExecutableAction<EmailAction, EmailAc
protected EmailAction.Result doExecute(String actionId, WatchExecutionContext ctx, Payload payload) throws Exception {
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
Email.Builder email = action.getEmail().render(templateEngine, model);
email.id(ctx.id().value());
Map<String, Attachment> attachmentMap = new HashMap<>();
Attachment.Bytes attachment = null;
if (action.getAttachData()) {
Attachment.Bytes attachment = new Attachment.XContent.Yaml("data", "data.yml", new Payload.Simple(model));
attachment = new Attachment.XContent.Yaml("data", "data.yml", new Payload.Simple(model));
attachmentMap.put(attachment.id(), attachment);
}
Email.Builder email = action.getEmail().render(templateEngine, model, attachmentMap);
email.id(ctx.id().value());
if (attachment != null) {
email.attach(attachment);
}

View File

@ -86,7 +86,6 @@ public class Account {
transport.connect(config.smtp.host, config.smtp.port, user, password);
try {
MimeMessage message = profile.toMimeMessage(email, session);
String mid = message.getMessageID();
message.saveChanges();

View File

@ -218,6 +218,7 @@ public class Email implements ToXContent {
private String htmlBody;
private ImmutableMap.Builder<String, Attachment> attachments = ImmutableMap.builder();
private ImmutableMap.Builder<String, Inline> inlines = ImmutableMap.builder();
private boolean sanitizeHtmlBody = true;
private Builder() {
}
@ -236,6 +237,8 @@ public class Email implements ToXContent {
htmlBody = email.htmlBody;
attachments.putAll(email.attachments);
inlines.putAll(email.inlines);
//The builder will already have sanitized the html when the email was built originally so don't double sanitize
sanitizeHtmlBody = false;
return this;
}
@ -330,7 +333,8 @@ public class Email implements ToXContent {
public Email build() {
assert id != null : "email id should not be null (should be set to the watch id";
return new Email(id, from, replyTo, priority, sentDate, to, cc, bcc, subject, textBody, htmlBody, attachments.build(), inlines.build());
ImmutableMap<String, Attachment> attachmentsMap = attachments.build();
return new Email(id, from, replyTo, priority, sentDate, to, cc, bcc, subject, textBody, htmlBody, attachmentsMap, inlines.build());
}
}

View File

@ -10,7 +10,9 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.watcher.support.template.Template;
import org.elasticsearch.watcher.support.template.TemplateEngine;
import org.owasp.html.*;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.mail.internet.AddressException;
import java.io.IOException;
import java.util.*;
@ -29,10 +31,11 @@ public class EmailTemplate implements ToXContent {
final Template subject;
final Template textBody;
final Template htmlBody;
final boolean sanitizeHtmlBody;
public EmailTemplate(Template from, Template[] replyTo, Template priority, Template[] to,
Template[] cc, Template[] bcc, Template subject, Template textBody,
Template htmlBody) {
Template htmlBody, boolean sanitizeHtmlBody) {
this.from = from;
this.replyTo = replyTo;
this.priority = priority;
@ -42,6 +45,7 @@ public class EmailTemplate implements ToXContent {
this.subject = subject;
this.textBody = textBody;
this.htmlBody = htmlBody;
this.sanitizeHtmlBody = sanitizeHtmlBody;
}
public Template from() {
@ -80,7 +84,11 @@ public class EmailTemplate implements ToXContent {
return htmlBody;
}
public Email.Builder render(TemplateEngine engine, Map<String, Object> model) throws AddressException {
public boolean sanitizeHtmlBody() {
return sanitizeHtmlBody;
}
public Email.Builder render(TemplateEngine engine, Map<String, Object> model, Map<String, Attachment> attachmentsMap) throws AddressException {
Email.Builder builder = Email.builder();
if (from != null) {
builder.from(engine.render(from, model));
@ -111,7 +119,11 @@ public class EmailTemplate implements ToXContent {
builder.textBody(engine.render(textBody, model));
}
if (htmlBody != null) {
builder.htmlBody(engine.render(htmlBody, model));
String renderedHtml = engine.render(htmlBody, model);
if (sanitizeHtmlBody && htmlBody != null) {
renderedHtml = sanitizeHtml(attachmentsMap, renderedHtml);
}
builder.htmlBody(renderedHtml);
}
return builder;
}
@ -199,31 +211,10 @@ public class EmailTemplate implements ToXContent {
return builder;
}
public static EmailTemplate parse(XContentParser parser) throws IOException{
EmailTemplate.Parser templateParser = parser();
String currentFieldName = null;
XContentParser.Token token;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else if ((token.isValue() || token == XContentParser.Token.START_OBJECT || token == XContentParser.Token.START_ARRAY) && currentFieldName != null) {
if (!templateParser.handle(currentFieldName, parser)) {
throw new EmailException("could not parse email template. unrecognized field [" + currentFieldName + "]");
}
}
}
return templateParser.parsedTemplate();
}
public static Builder builder() {
return new Builder();
}
public static Parser parser() {
return new Parser();
}
public static class Builder {
private Template from;
@ -235,6 +226,7 @@ public class EmailTemplate implements ToXContent {
private Template subject;
private Template textBody;
private Template htmlBody;
private boolean sanitizeHtmlBody = true;
private Builder() {
}
@ -327,17 +319,18 @@ public class EmailTemplate implements ToXContent {
return this;
}
public Builder htmlBody(String html) {
return htmlBody(new Template(html));
public Builder htmlBody(String html, boolean sanitizeHtmlBody) {
return htmlBody(new Template(html), sanitizeHtmlBody);
}
public Builder htmlBody(Template html) {
public Builder htmlBody(Template html, boolean sanitizeHtmlBody) {
this.htmlBody = html;
this.sanitizeHtmlBody = sanitizeHtmlBody;
return this;
}
public EmailTemplate build() {
return new EmailTemplate(from, replyTo, priority, to, cc, bcc, subject, textBody, htmlBody);
return new EmailTemplate(from, replyTo, priority, to, cc, bcc, subject, textBody, htmlBody, sanitizeHtmlBody);
}
}
@ -345,6 +338,11 @@ public class EmailTemplate implements ToXContent {
public static class Parser {
private final EmailTemplate.Builder builder = builder();
private final boolean sanitizeHtmlBody;
public Parser(boolean sanitizeHtmlBody) {
this.sanitizeHtmlBody = sanitizeHtmlBody;
}
public boolean handle(String fieldName, XContentParser parser) throws IOException {
if (Email.Field.FROM.match(fieldName)) {
@ -396,7 +394,7 @@ public class EmailTemplate implements ToXContent {
} else if (Email.Field.TEXT_BODY.match(fieldName)) {
builder.textBody(Template.parse(parser));
} else if (Email.Field.HTML_BODY.match(fieldName)) {
builder.htmlBody(Template.parse(parser));
builder.htmlBody(Template.parse(parser), sanitizeHtmlBody);
} else {
return false;
}
@ -407,4 +405,54 @@ public class EmailTemplate implements ToXContent {
return builder.build();
}
}
static String sanitizeHtml(final Map<String, Attachment> attachments, String html){
ElementPolicy onlyCIDImgPolicy = new AttachementVerifyElementPolicy(attachments);
PolicyFactory policy = Sanitizers.FORMATTING
.and(new HtmlPolicyBuilder()
.allowElements("img", "table", "tr", "td", "style", "body", "head", "hr")
.allowAttributes("src").onElements("img")
.allowAttributes("class").onElements("style")
.allowUrlProtocols("cid")
.allowCommonInlineFormattingElements()
.allowElements(onlyCIDImgPolicy, "img")
.allowStyling(CssSchema.DEFAULT)
.toFactory())
.and(Sanitizers.LINKS)
.and(Sanitizers.BLOCKS);
return policy.sanitize(html);
}
private static class AttachementVerifyElementPolicy implements ElementPolicy {
private final Map<String, Attachment> attachments;
AttachementVerifyElementPolicy(Map<String, Attachment> attachments) {
this.attachments = attachments;
}
@Override
public String apply(@ParametersAreNonnullByDefault String elementName, @ParametersAreNonnullByDefault List<String> attrs) {
if (attrs.size() == 0) {
return elementName;
}
for (int i = 0; i < attrs.size(); ++i) {
if(attrs.get(i).equals("src") && i < attrs.size() - 1) {
String srcValue = attrs.get(i+1);
if (!srcValue.startsWith("cid:")) {
return null; //Disallow anything other than content ids
}
String contentId = srcValue.substring(4);
if (attachments.containsKey(contentId)) {
return elementName;
} else {
return null; //This cid wasn't found
}
}
}
return elementName;
}
}
}

View File

@ -6,13 +6,9 @@
package org.elasticsearch.watcher.actions.email.service;
import org.elasticsearch.common.base.Charsets;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.owasp.html.*;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
@ -20,7 +16,6 @@ import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
/**
@ -92,8 +87,7 @@ public enum Profile implements ToXContent {
if (email.htmlBody != null) {
MimeBodyPart html = new MimeBodyPart();
String sanitizedHtml = sanitizeHtml(email.attachments, email.htmlBody);
html.setText(sanitizedHtml, Charsets.UTF_8.name(), "html");
html.setText(email.htmlBody, Charsets.UTF_8.name(), "html");
alternative.addBodyPart(html);
}
@ -222,55 +216,4 @@ public enum Profile implements ToXContent {
}
return part;
}
static String sanitizeHtml(final ImmutableMap<String, Attachment> attachments, String html){
ElementPolicy onlyCIDImgPolicy = new AttachementVerifyElementPolicy(attachments);
PolicyFactory policy = Sanitizers.FORMATTING
.and(new HtmlPolicyBuilder()
.allowElements("img", "table", "tr", "td", "style", "body", "head")
.allowAttributes("src").onElements("img")
.allowAttributes("class").onElements("style")
.allowUrlProtocols("cid")
.allowCommonInlineFormattingElements()
.allowElements(onlyCIDImgPolicy, "img")
.allowStyling(CssSchema.DEFAULT)
.toFactory())
.and(Sanitizers.LINKS)
.and(Sanitizers.BLOCKS);
return policy.sanitize(html);
}
private static class AttachementVerifyElementPolicy implements ElementPolicy {
private final ImmutableMap<String, Attachment> attachments;
AttachementVerifyElementPolicy(ImmutableMap<String, Attachment> attchments) {
this.attachments = attchments;
}
@Nullable
@Override
public String apply(@ParametersAreNonnullByDefault String elementName, @ParametersAreNonnullByDefault List<String> attrs) {
if (attrs.size() == 0) {
return elementName;
}
for (int i = 0; i < attrs.size(); ++i) {
if(attrs.get(i).equals("src") && i < attrs.size() - 1) {
String srcValue = attrs.get(i+1);
if (!srcValue.startsWith("cid:")) {
return null; //Disallow anything other than content ids
}
String contentId = srcValue.substring(4);
if (attachments.containsKey(contentId)) {
return elementName;
} else {
return null; //This cid wasn't found
}
}
}
return elementName;
}
}
}

View File

@ -72,7 +72,7 @@ public class EmailActionTests extends ElasticsearchTestCase {
Template htmlBody = null;
if (randomBoolean()) {
htmlBody = new Template("_html_body");
emailBuilder.htmlBody(htmlBody);
emailBuilder.htmlBody(htmlBody, true);
}
EmailTemplate email = emailBuilder.build();

View File

@ -0,0 +1,127 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.watcher.actions.email.service;
import com.carrotsearch.randomizedtesting.annotations.Repeat;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.test.ElasticsearchTestCase;
import org.elasticsearch.watcher.support.template.Template;
import org.elasticsearch.watcher.support.template.TemplateEngine;
import org.junit.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
*/
public class EmailTemplateTests extends ElasticsearchTestCase {
@Test @Repeat(iterations = 100)
public void testEmailTemplate_Parser_SelfGenerated() throws Exception {
Template from = randomFrom(new Template("from@from.com"), null);
List<Template> addresses = new ArrayList<>();
for( int i = 0; i < randomIntBetween(1, 5); ++i){
addresses.add(new Template("address" + i + "@test.com"));
}
Template[] possibleList = addresses.toArray(new Template[addresses.size()]);
Template[] replyTo = randomFrom(possibleList, null);
Template[] to = randomFrom(possibleList, null);
Template[] cc = randomFrom(possibleList, null);
Template[] bcc = randomFrom(possibleList, null);
Template priority = new Template(randomFrom(Email.Priority.values()).name());
boolean sanitizeHtml = randomBoolean();
Template templatedSubject = new Template("Templated Subject {{foo}}");
String renderedTemplatedSubject = "Templated Subject bar";
Template templatedBody = new Template("Templated Body {{foo}}");
String renderedTemplatedBody = "Templated Body bar";
Template templatedHtmlBodyGood = new Template("Templated Html Body <hr />");
String renderedTemplatedHtmlBodyGood = "Templated Html Body <hr /> bar";
Template templatedHtmlBodyBad = new Template("Templated Html Body <script>nefarious scripting</script>");
String renderedTemplatedHtmlBodyBad = "Templated Html Body<script>nefarious scripting</script>";
String renderedSanitizedHtmlBodyBad = "Templated Html Body";
Template htmlBody = randomFrom(templatedHtmlBodyGood, templatedHtmlBodyBad);
EmailTemplate emailTemplate = new EmailTemplate(from, replyTo, priority, to, cc, bcc,
templatedSubject, templatedBody, htmlBody, sanitizeHtml);
XContentBuilder builder = XContentFactory.jsonBuilder();
emailTemplate.toXContent(builder, ToXContent.EMPTY_PARAMS);
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
parser.nextToken();
EmailTemplate.Parser emailTemplateParser = new EmailTemplate.Parser(sanitizeHtml);
String currentFieldName = null;
XContentParser.Token token;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else {
assertThat(emailTemplateParser.handle(currentFieldName, parser), is(true));
}
}
EmailTemplate parsedEmailTemplate = emailTemplateParser.parsedTemplate();
Map<String, Object> model = new HashMap<>();
TemplateEngine templateEngine = mock(TemplateEngine.class);
when(templateEngine.render(templatedSubject, model)).thenReturn(renderedTemplatedSubject);
when(templateEngine.render(templatedBody, model)).thenReturn(renderedTemplatedBody);
when(templateEngine.render(templatedHtmlBodyGood, model)).thenReturn(renderedTemplatedHtmlBodyGood);
when(templateEngine.render(templatedHtmlBodyBad, model)).thenReturn(renderedTemplatedHtmlBodyBad);
for (Template possibleAddress : possibleList) {
when(templateEngine.render(possibleAddress, model)).thenReturn(possibleAddress.getTemplate());
}
if (from != null) {
when(templateEngine.render(from, model)).thenReturn(from.getTemplate());
}
when(templateEngine.render(priority, model)).thenReturn(priority.getTemplate());
Email.Builder emailBuilder = parsedEmailTemplate.render(templateEngine, model, new HashMap<String, Attachment>());
assertThat(emailTemplate.from, equalTo(parsedEmailTemplate.from));
assertThat(emailTemplate.replyTo, equalTo(parsedEmailTemplate.replyTo));
assertThat(emailTemplate.priority, equalTo(parsedEmailTemplate.priority));
assertThat(emailTemplate.to, equalTo(parsedEmailTemplate.to));
assertThat(emailTemplate.cc, equalTo(parsedEmailTemplate.cc));
assertThat(emailTemplate.bcc, equalTo(parsedEmailTemplate.bcc));
assertThat(emailTemplate.subject, equalTo(parsedEmailTemplate.subject));
assertThat(emailTemplate.textBody, equalTo(parsedEmailTemplate.textBody));
assertThat(emailTemplate.htmlBody, equalTo(parsedEmailTemplate.htmlBody));
emailBuilder.id("_id");
Email email = emailBuilder.build();
assertThat(email.subject, equalTo(renderedTemplatedSubject));
assertThat(email.textBody, equalTo(renderedTemplatedBody));
if (htmlBody.equals(templatedHtmlBodyBad)) {
if (sanitizeHtml) {
assertThat(email.htmlBody, equalTo(renderedSanitizedHtmlBodyBad));
} else {
assertThat(email.htmlBody, equalTo(renderedTemplatedHtmlBodyBad));
}
} else {
assertThat(email.htmlBody, equalTo(renderedTemplatedHtmlBodyGood));
}
}
}

View File

@ -42,7 +42,7 @@ public class EmailTest extends ElasticsearchTestCase {
Email.AddressList bcc = randomFrom(possibleList, null);
String subject = randomFrom("Random Subject", "", null);
String textBody = randomFrom("Random Body", "", null);
String htmlBody = randomFrom("<hr/>BODY<b/><hr/>", "", null);
String htmlBody = randomFrom("<hr /><b>BODY</b><hr />", "", null);
ImmutableMap<String, Attachment> attachments = null;
ImmutableMap<String, Inline> inlines = null;
@ -56,7 +56,6 @@ public class EmailTest extends ElasticsearchTestCase {
Email parsedEmail = Email.parse(parser);
assertThat(email.id, equalTo(parsedEmail.id));
assertThat(email.from, equalTo(parsedEmail.from));
assertThat(email.replyTo, equalTo(parsedEmail.replyTo));

View File

@ -9,8 +9,10 @@ import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.test.ElasticsearchTestCase;
import org.junit.Test;
import static org.elasticsearch.watcher.actions.email.service.EmailTemplate.sanitizeHtml;
import static org.hamcrest.Matchers.equalTo;
/**
*/
public class HtmlSanitizeTests extends ElasticsearchTestCase {
@ -21,7 +23,7 @@ public class HtmlSanitizeTests extends ElasticsearchTestCase {
"onclick=\"document.getElementById('demo').innerHTML = Date()\">" +
"Click me to display Date and Time.</button>";
byte[] bytes = new byte[0];
String sanitizedHtml = Profile.sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), badHtml);
String sanitizedHtml = sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), badHtml);
assertThat(sanitizedHtml, equalTo("Click me to display Date and Time."));
}
@ -29,7 +31,7 @@ public class HtmlSanitizeTests extends ElasticsearchTestCase {
public void test_HtmlSanitizer_Nonattachment_img() {
String badHtml = "<img src=\"http://test.com/nastyimage.jpg\"/>This is a bad image";
byte[] bytes = new byte[0];
String sanitizedHtml = Profile.sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), badHtml);
String sanitizedHtml = sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), badHtml);
assertThat(sanitizedHtml, equalTo("This is a bad image"));
}
@ -37,7 +39,7 @@ public class HtmlSanitizeTests extends ElasticsearchTestCase {
public void test_HtmlSanitizer_Goodattachment_img() {
String goodHtml = "<img src=\"cid:foo\" />This is a good image";
byte[] bytes = new byte[0];
String sanitizedHtml = Profile.sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), goodHtml);
String sanitizedHtml = sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), goodHtml);
assertThat(sanitizedHtml, equalTo(goodHtml));
}
@ -45,7 +47,7 @@ public class HtmlSanitizeTests extends ElasticsearchTestCase {
public void test_HtmlSanitizer_table() {
String goodHtml = "<table><tr><td>cell1</td><td>cell2</td></tr></table>";
byte[] bytes = new byte[0];
String sanitizedHtml = Profile.sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), goodHtml);
String sanitizedHtml = sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), goodHtml);
assertThat(sanitizedHtml, equalTo(goodHtml));
}
@ -54,7 +56,7 @@ public class HtmlSanitizeTests extends ElasticsearchTestCase {
public void test_HtmlSanitizer_Badattachment_img() {
String goodHtml = "<img src=\"cid:bad\" />This is a bad image";
byte[] bytes = new byte[0];
String sanitizedHtml = Profile.sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), goodHtml);
String sanitizedHtml = sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), goodHtml);
assertThat(sanitizedHtml, equalTo("This is a bad image"));
}
@ -62,7 +64,7 @@ public class HtmlSanitizeTests extends ElasticsearchTestCase {
public void test_HtmlSanitizer_Script() {
String badHtml = "<script>doSomethingNefarious()</script>This was a dangerous script";
byte[] bytes = new byte[0];
String sanitizedHtml = Profile.sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), badHtml);
String sanitizedHtml = sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), badHtml);
assertThat(sanitizedHtml, equalTo("This was a dangerous script"));
}
@ -70,7 +72,7 @@ public class HtmlSanitizeTests extends ElasticsearchTestCase {
public void test_HtmlSanitizer_FullHtmlWithMetaString() {
String needsSanitation = "<html><head></head><body><h1>Hello {{ctx.metadata.name}}</h1> meta <a href='https://www.google.com/search?q={{ctx.metadata.name}}'>Testlink</a>meta</body></html>";
byte[] bytes = new byte[0];
String sanitizedHtml = Profile.sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), needsSanitation);
String sanitizedHtml = sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), needsSanitation);
assertThat(sanitizedHtml, equalTo("<head></head><body><h1>Hello {{ctx.metadata.name}}</h1> meta <a href=\"https://www.google.com/search?q&#61;{{ctx.metadata.name}}\" rel=\"nofollow\">Testlink</a>meta</body>"));
}