CVE-2017-1000491: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Shiba markdown live preview app version 1.1.0 is vulnerable to XSS which leads to code execution due to enabled node integration.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2018-01-03T01:29Z
Repository: https://github.com/rhysd/Shiba
Language: JSON
Files changed: package.json, renderer/markdown-preview.ts, renderer/tsconfig.json
Commit date: 2017-12-01 00:25:14 +0900
Commit message: improve marked renderer

Diff: diff --git a/package.json b/package.json
index 733f8da..a489bf5 100644
--- a/package.json
+++ b/package.json
@@ -49,13 +49,14 @@
   "devDependencies": {
     "@types/chokidar": "^1.7.3",
     "@types/empower": "^1.2.30",
     "@types/es6-promise": "0.0.33",
     "@types/he": "^0.5.29",
-    "@types/highlight.js": "^9.12.1",
+    "@types/highlight.js": "^9.12.2",
     "@types/js-yaml": "^3.9.1",
     "@types/katex": "0.5.0",
+    "@types/marked": "^0.3.0",
     "@types/mocha": "^2.2.44",
     "@types/mousetrap": "^1.5.34",
     "@types/node": "8.0.53",
     "@types/polymer": "^1.2.1",
     "@types/power-assert": "^1.4.29",
diff --git a/renderer/markdown-preview.ts b/renderer/markdown-preview.ts
index 48a8676..55569dc 100644
--- a/renderer/markdown-preview.ts
+++ b/renderer/markdown-preview.ts
@@ -39,21 +39,24 @@ marked.setOptions({
             console.log('Error on highlight: ' + e.message);
             return code;
         }
     },
 
+    // @ts-ignore: emoji is a dedicated method added by my fork
     emoji(name: string) {
         return emoji_replacer.replaceOne(name);
     },
+
+    sanitize: 1,
 });
 
 const REGEX_CHECKED_LISTITEM = /^\[x]\s+/;
 const REGEX_UNCHECKED_LISTITEM = /^\[ ]\s+/;
 
 class MarkdownRenderer {
     public outline: Heading[];
-    private renderer: MarkedRenderer;
+    private renderer: marked.Renderer;
     private link_id: number;
     private tooltips: string;
 
     constructor(public markdown_exts: string[]) {
         this.renderer = new marked.Renderer();
diff --git a/renderer/marked.d.ts b/renderer/marked.d.ts
deleted file mode 100644
index 2ebf0e7..0000000
--- a/renderer/marked.d.ts
+++ /dev/null
@@ -1,166 +0,0 @@
-// Generated by typings
-// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/9cfdb11648f823b889287c770254b85b78a7a4a4/marked/marked.d.ts
-interface MarkedStatic {
-    Renderer: {
-        new(): MarkedRenderer;
-    };
-
-    Parser: {
-        new(options: MarkedOptions): MarkedParser;
-    };
-
-    /**
-     * Compiles markdown to HTML.
-     *
-     * @param src String of markdown source to be compiled
-     * @param callback Function called when the markdownString has been fully parsed when using async highlighting
-     * @return String of compiled HTML
-     */
-    (src: string, callback: (...args: any[]) => void): string;
-
-    /**
-     * Compiles markdown to HTML.
-     *
-     * @param src String of markdown source to be compiled
-     * @param options Hash of options
-     * @param callback Function called when the markdownString has been fully parsed when using async highlighting
-     * @return String of compiled HTML
-     */
-    (src: string, options?: MarkedOptions, callback?: (...args: any[]) => void): string;
-
-    /**
-     * @param src String of markdown source to be compiled
-     * @param options Hash of options
-     */
-    lexer(src: string, options?: MarkedOptions): any[];
-
-    /**
-     * Compiles markdown to HTML.
-     *
-     * @param src String of markdown source to be compiled
-     * @param callback Function called when the markdownString has been fully parsed when using async highlighting
-     * @return String of compiled HTML
-     */
-    parse(src: string, callback: (...args: any[]) => void): string;
-
-    /**
-     * Compiles markdown to HTML.
-     *
-     * @param src String of markdown source to be compiled
-     * @param options Hash of options
-     * @param callback Function called when the markdownString has been fully parsed when using async highlighting
-     * @return String of compiled HTML
-     */
-    parse(src: string, options?: MarkedOptions, callback?: (...args: any[]) => void): string;
-
-    /**
-     * @param options Hash of options
-     */
-    parser(src: any[], options?: MarkedOptions): string;
-
-    /**
-     * Sets the default options.
-     *
-     * @param options Hash of options
-     */
-    setOptions(options: MarkedOptions): MarkedStatic;
-}
-
-interface MarkedRenderer {
-    code(code: string, language: string): string;
-    blockquote(quote: string): string;
-    html(html: string): string;
-    heading(text: string, level: number, raw: string): string;
-    hr(): string;
-    list(body: string, ordered: boolean): string;
-    listitem(text: string): string;
-    paragraph(text: string): string;
-    table(header: string, body: string): string;
-    tablerow(content: string): string;
-    tablecell(content: string, flags: {
-        header: boolean,
-        align: string
-    }): string;
-    strong(text: string): string;
-    em(text: string): string;
-    codespan(code: string): string;
-    br(): string;
-    del(text: string): string;
-    link(href: string, title: string, text: string): string;
-    image(href: string, title: string, text: string): string;
-    text(text: string): string;
-}
-
-interface MarkedParser {
-    parse(source: any[]): string;
-}
-
-interface MarkedOptions {
-    /**
-     * Type: object Default: new Renderer()
-     *
-     * An object containing functions to render tokens to HTML.
-     */
-    renderer?: MarkedRenderer;
-
-    /**
-     * Enable GitHub flavored markdown.
-     */
-    gfm?: boolean;
-
-    /**
-     * Enable GFM tables. This option requires the gfm option to be true.
-     */
-    tables?: boolean;
-
-    /**
-     * Enable GFM line breaks. This option requires the gfm option to be true.
-     */
-    breaks?: boolean;
-
-    /**
-     * Conform to obscure parts of markdown.pl as much as possible. Don't fix any of the original markdown bugs or poor behavior.
-     */
-    pedantic?: boolean;
-
-    /**
-     * Sanitize the output. Ignore any HTML that has been input.
-     */
-    sanitize?: boolean;
-
-    /**
-     * Use smarter list behavior than the original markdown. May eventually be default with the old behavior moved into pedantic.
-     */
-    smartLists?: boolean;
-
-    /**
-     * Shows an HTML error message when rendering fails.
-     */
-    silent?: boolean;
-
-    /**
-     * A function to highlight code blocks. The function takes three arguments: code, lang, and callback.
-     */
-    highlight?: (code: string, lang: string, callback?: (...args: any[]) => void) => string;
-
-    /**
-     * Set the prefix for code block classes.
-     */
-    langPrefix?: string;
-
-    /**
-     * Use 'smart' typograhic punctuation for things like quotes and dashes.
-     */
-    smartypants?: boolean;
-
-    /**
-     * Forked 'emoji' inline images
-     */
-    emoji?: (name: string) => string;
-}
-
-declare module 'marked' {
-    const marked: MarkedStatic;
-    export = marked;
-}
-
diff --git a/renderer/tsconfig.json b/renderer/tsconfig.json
index 647bd35..db75710 100644
--- a/renderer/tsconfig.json
+++ b/renderer/tsconfig.json
@@ -16,11 +16,10 @@
     "emoji.ts",
     "encoding-japanese.d.ts",
     "index.ts",
     "keyboard.ts",
     "lib.d.ts",
-    "marked.d.ts",
     "lint-message.ts",
     "lint-panel.ts",
     "markdown-preview.ts",
     "paw-filechooser.ts",
     "toc-dialog.ts"

Vulnerable code:     "@types/highlight.js": "^9.12.1",
    private renderer: MarkedRenderer;
// Generated by typings
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/9cfdb11648f823b889287c770254b85b78a7a4a4/marked/marked.d.ts
interface MarkedStatic {
    Renderer: {
        new(): MarkedRenderer;
    };

    Parser: {
        new(options: MarkedOptions): MarkedParser;
    };

    /**
     * Compiles markdown to HTML.
     *
     * @param src String of markdown source to be compiled
     * @param callback Function called when the markdownString has been fully parsed when using async highlighting
     * @return String of compiled HTML
     */
    (src: string, callback: (...args: any[]) => void): string;

    /**
     * Compiles markdown to HTML.
     *
     * @param src String of markdown source to be compiled
     * @param options Hash of options
     * @param callback Function called when the markdownString has been fully parsed when using async highlighting
     * @return String of compiled HTML
     */
    (src: string, options?: MarkedOptions, callback?: (...args: any[]) => void): string;

    /**
     * @param src String of markdown source to be compiled
     * @param options Hash of options
     */
    lexer(src: string, options?: MarkedOptions): any[];

    /**
     * Compiles markdown to HTML.
     *
     * @param src String of markdown source to be compiled
     * @param callback Function called when the markdownString has been fully parsed when using async highlighting
     * @return String of compiled HTML
     */
    parse(src: string, callback: (...args: any[]) => void): string;

    /**
     * Compiles markdown to HTML.
     *
     * @param src String of markdown source to be compiled
     * @param options Hash of options
     * @param callback Function called when the markdownString has been fully parsed when using async highlighting
     * @return String of compiled HTML
     */
    parse(src: string, options?: MarkedOptions, callback?: (...args: any[]) => void): string;

    /**
     * @param options Hash of options
     */
    parser(src: any[], options?: MarkedOptions): string;

    /**
     * Sets the default options.
     *
     * @param options Hash of options
     */
    setOptions(options: MarkedOptions): MarkedStatic;
}

interface MarkedRenderer {
    code(code: string, language: string): string;
    blockquote(quote: string): string;
    html(html: string): string;
    heading(text: string, level: number, raw: string): string;
    hr(): string;
    list(body: string, ordered: boolean): string;
    listitem(text: string): string;
    paragraph(text: string): string;
    table(header: string, body: string): string;
    tablerow(content: string): string;
    tablecell(content: string, flags: {
        header: boolean,
        align: string
    }): string;
    strong(text: string): string;
    em(text: string): string;
    codespan(code: string): string;
    br(): string;
    del(text: string): string;
    link(href: string, title: string, text: string): string;
    image(href: string, title: string, text: string): string;
    text(text: string): string;
}

interface MarkedParser {
    parse(source: any[]): string;
}

interface MarkedOptions {
    /**
     * Type: object Default: new Renderer()
     *
     * An object containing functions to render tokens to HTML.
     */
    renderer?: MarkedRenderer;

    /**
     * Enable GitHub flavored markdown.
     */
    gfm?: boolean;

    /**
     * Enable GFM tables. This option requires the gfm option to be true.
     */
    tables?: boolean;

    /**
     * Enable GFM line breaks. This option requires the gfm option to be true.
     */
    breaks?: boolean;

    /**
     * Conform to obscure parts of markdown.pl as much as possible. Don't fix any of the original markdown bugs or poor behavior.
     */
    pedantic?: boolean;

    /**
     * Sanitize the output. Ignore any HTML that has been input.
     */
    sanitize?: boolean;

    /**
     * Use smarter list behavior than the original markdown. May eventually be default with the old behavior moved into pedantic.
     */
    smartLists?: boolean;

    /**
     * Shows an HTML error message when rendering fails.
     */
    silent?: boolean;

    /**
     * A function to highlight code blocks. The function takes three arguments: code, lang, and callback.
     */
    highlight?: (code: string, lang: string, callback?: (...args: any[]) => void) => string;

    /**
     * Set the prefix for code block classes.
     */
    langPrefix?: string;

    /**
     * Use 'smart' typograhic punctuation for things like quotes and dashes.
     */
    smartypants?: boolean;

    /**
     * Forked 'emoji' inline images
     */
    emoji?: (name: string) => string;
}

declare module 'marked' {
    const marked: MarkedStatic;
    export = marked;
}

    "marked.d.ts",
Fixed code:     "@types/highlight.js": "^9.12.2",
    "@types/marked": "^0.3.0",
    // @ts-ignore: emoji is a dedicated method added by my fork

    sanitize: 1,
    private renderer: marked.Renderer;