
Prend du HTML tiers et produit du HTML sûr à intégrer dans votre application web. Rapide et facile à configurer.
Un assainisseur HTML rapide et facile à configurer, écrit en Java, qui vous permet d'inclure du HTML rédigé par des tiers dans votre application web tout en vous protégeant contre les XSS.
La dépendance existante porte sur JSR 305. Les autres jars ne sont nécessaires que pour la suite de tests. La dépendance JSR 305 est une dépendance de compilation uniquement, nécessaire seulement pour les annotations.
Ce code a été écrit en gardant à l'esprit les bonnes pratiques de sécurité, il dispose d'une suite de tests complète et a fait l'objet d'une revue de sécurité contradictoire.
Commencer inclut des instructions sur la façon de démarrer avec ou sans Maven.
Vous pouvez utiliser des politiques pré-packagées :
PolicyFactory policy = Sanitizers.FORMATTING.and(Sanitizers.LINKS);
String safeHTML = policy.sanitize(untrustedHTML);
Les tests montrent comment configurer votre propre politique :
PolicyFactory policy = new HtmlPolicyBuilder()
.allowElements("a")
.allowUrlProtocols("https")
.allowAttributes("href").onElements("a")
.requireRelNofollowOnLinks()
.toFactory();
String safeHTML = policy.sanitize(untrustedHTML);
Vous pouvez écrire des
politiques personnalisées
pour faire des choses comme transformer les h1 en div avec une certaine classe :
PolicyFactory policy = new HtmlPolicyBuilder()
.allowElements("p")
.allowElements(
(String elementName, List<String> attrs) -> {
// Add a class attribute.
attrs.add("class");
attrs.add("header-" + elementName);
// Return elementName to include, null to drop.
return "div";
}, "h1", "h2", "h3", "h4", "h5", "h6")
.toFactory();
String safeHTML = policy.sanitize(untrustedHTML);
Veuillez noter que les éléments « a », « font », « img », « input » et « span »
doivent être explicitement ajoutés à la liste blanche à l'aide de la méthode allowWithoutAttributes()
si vous souhaitez qu'ils soient autorisés à traverser le filtre lorsque ces
éléments n'incluent aucun attribut.
Les politiques d'attributs permettent également d'exécuter du code personnalisé. L'ajout d'une politique d'attributs n'affaiblira aucune politique par défaut comme style ou les vérifications d'attributs d'URL.
new HtmlPolicyBuilder = new HtmlPolicyBuilder()
.allowElement("div", "span")
.allowAttributes("data-foo")
.matching(
(String elementName, String attributeName, String value) -> {
// Return value for the attribute or null to drop.
})
.onElements("div", "span")
.build()
Les préprocesseurs permettent d'insérer du texte et de procéder à des modifications structurelles à grande échelle.
new HtmlPolicyBuilder = new HtmlPolicyBuilder()
// Use a preprocessor to be backwards compatible with the
// <plaintext> element which
.withPreprocessor(
(HtmlStreamEventReceiver r) -> {
// Provide user with info about links before they click.
// Before: <a href="https://example.com/...">
// After: (https://example.com) <a href="https://example.com/...">
return new HtmlStreamEventReceiverWrapper(r) {
@Override public void openTag(String elementName, List<String> attrs) {
if ("a".equals(elementName)) {
for (int i = 0, n = attrs.size(); i < n; i += 2) {
if ("href".equals(attrs.get(i)) {
String url = attrs.get(i + 1);
String origin;
try {
URI uri = new URI(url);
String scheme = uri.getScheme();
String authority = uri.getRawAuthority();
if (scheme == null && authority == null) {
origin = null;
} else {
origin = (scheme != null ? scheme + ":" : "")
+ (authority != null ? "//" + authority : "");
}
} catch (URISyntaxException ex) {
origin = "about:invalid";
}
if (origin != null) {
text(" (" + origin + ") ");
}
}
}
}
super.openTag(elementName, attrs);
}
};
}
.allowElement("a")
...
.build()
Le prétraitement a lieu avant l'application d'une politique, il ne peut donc pas affecter la sécurité de la sortie.
Lorsqu'une politique rejette un élément ou un attribut, elle notifie un HtmlChangeListener.
Vous pouvez l'utiliser pour suivre les tendances des violations de politique et découvrir quand quelqu'un fait un effort pour compromettre votre sécurité.
PolicyFactory myPolicyFactory = ...;
// If you need to associate reports with some context, you can do so.
MyContextClass myContext = ...;
String sanitizedHtml = myPolicyFactory.sanitize(
unsanitizedHtml,
new HtmlChangeListener<MyContextClass>() {
@Override
public void discardedTag(MyContextClass context, String elementName) {
// ...
}
@Override
public void discardedAttributes(
MyContextClass context, String elementName, String... attributeNames) {
// ...
}
},
myContext);
Remarque : Si une chaîne est assainie sans aucune notification de changement, cela ne signifie pas que la chaîne d'entrée est nécessairement sûre à utiliser. Utilisez uniquement la sortie de l'assainisseur.
L'assainisseur garantit que la sortie est un sous-ensemble de HTML dont la signification est acceptée par les analyseurs HTML couramment utilisés, mais l'absence de notifications ne signifie pas que l'entrée est dans un tel sous-ensemble, seulement qu'elle ne contient pas d'éléments ou d'attributs qui ont été supprimés.
Voir "Why sanitize when you can validate" pour en savoir plus sur ce sujet.
Si vous souhaitez signaler une vulnérabilité, veuillez consulter AttackReviewGroundRules.
Abonnez-vous à la liste de diffusion pour être informé des Vulnérabilités connues et des mises à jour importantes.
Si vous souhaitez contribuer, veuillez contacter @mvsamuel ou @manicode.
Nous accueillons favorablement les rapports de problèmes et les PR. Les PR qui modifient le comportement ou ajoutent des fonctionnalités doivent inclure à la fois des tests négatifs et positifs.
Veuillez noter que les contributions relèvent de la Licence Apache 2.0.
Merci à tous ceux qui ont aidé par leurs critiques et leur code