Skip to content

Commit

Permalink
enh(parser) add throwUnescapedHTML to throw error when an HTML inject…
Browse files Browse the repository at this point in the history
…ion vulnerability detected (#3352)
  • Loading branch information
joshgoebel committed Oct 12, 2021
1 parent 1c79370 commit 7c87adc
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -3,6 +3,7 @@
Parser:

- add first rough performance testing script (#3280) [Austin Schick][]
- add `throwUnescapedHTML` to warn against potential HTML injection [Josh Goebel][]
- expose `regex` helper functions via `hljs` injection [Josh Goebel][]
- concat
- lookahead
Expand Down
3 changes: 3 additions & 0 deletions docs/api.rst
Expand Up @@ -89,6 +89,9 @@ Configures global options:
* ``languageDetectRe``: a regex to configure how CSS class names map to language (allows class names like say `color-as-php` vs the default of `language-php`, etc.)
* ``noHighlightRe``: a regex to configure which CSS classes are to be skipped completely.
* ``cssSelector``: a CSS selector to configure which elements are affected by ``hljs.highlightAll``. Defaults to ``'pre code'``.
* ``ignoreUnescapedHTML``: do not log warnings to console about unescaped HTML in code blocks
* ``throwUnescapedHTML``: throw a ``HTMLInjectionError`` when ``highlightElement`` is asked to highlight content that includes unescaped HTML


Accepts an object representing options with the values to updated. Other options don't change
::
Expand Down
25 changes: 20 additions & 5 deletions src/highlight.js
Expand Up @@ -13,6 +13,7 @@ import * as MODES from './lib/modes.js';
import { compileLanguage } from './lib/mode_compiler.js';
import * as packageJSON from '../package.json';
import * as logger from "./lib/logger.js";
import HTMLInjectionError from "./lib/html_injection_error.js";

/**
@typedef {import('highlight.js').Mode} Mode
Expand Down Expand Up @@ -66,6 +67,7 @@ const HLJS = function(hljs) {
/** @type HLJSOptions */
let options = {
ignoreUnescapedHTML: false,
throwUnescapedHTML: false,
noHighlightRe: /^(no-?highlight)$/i,
languageDetectRe: /\blang(?:uage)?-([\w-]+)\b/i,
classPrefix: 'hljs-',
Expand Down Expand Up @@ -724,11 +726,24 @@ const HLJS = function(hljs) {
fire("before:highlightElement",
{ el: element, language: language });

// we should be all text, no child nodes
if (!options.ignoreUnescapedHTML && element.children.length > 0) {
console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk.");
console.warn("https://github.com/highlightjs/highlight.js/issues/2886");
console.warn(element);
// we should be all text, no child nodes (unescaped HTML) - this is possibly
// an HTML injection attack - it's likely too late if this is already in
// production (the code has likely already done its damage by the time
// we're seeing it)... but we yell loudly about this so that hopefully it's
// more likely to be caught in development before making it to production
if (element.children.length > 0) {
if (!options.ignoreUnescapedHTML) {
console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk.");
console.warn("https://github.com/highlightjs/highlight.js/issues/2886");
console.warn(element);
}
if (options.throwUnescapedHTML) {
const err = new HTMLInjectionError(
"One of your code blocks includes unescaped HTML.",
element.innerHTML
);
throw err;
}
}

node = element;
Expand Down
7 changes: 7 additions & 0 deletions src/lib/html_injection_error.js
@@ -0,0 +1,7 @@
export default class HTMLInjectionError extends Error {
constructor(reason, html) {
super(reason);
this.name = "HTMLInjectionError";
this.html = html;
}
}
1 change: 1 addition & 0 deletions types/index.d.ts
Expand Up @@ -134,6 +134,7 @@ declare module 'highlight.js' {
languages?: string[]
__emitter: EmitterConstructor
ignoreUnescapedHTML?: boolean
throwUnescapedHTML?: boolean
}

export interface CallbackResponse {
Expand Down

0 comments on commit 7c87adc

Please sign in to comment.