{"action":"closed","issue":{"url":"https://api.github.com/repos/appKom/notifier/issues/12","labels_url":"https://api.github.com/repos/appKom/notifier/issues/12/labels{/name}","comments_url":"https://api.github.com/repos/appKom/notifier/issues/12/comments","events_url":"https://api.github.com/repos/appKom/notifier/issues/12/events","html_url":"https://github.com/appKom/notifier/issues/12","id":31053605,"number":12,"title":"Ajaxer.cleanHtml() is vulnerable ","user":{"login":"michaelmcmillan","id":147197,"avatar_url":"https://avatars.githubusercontent.com/u/147197?v=3","gravatar_id":"","url":"https://api.github.com/users/michaelmcmillan","html_url":"https://github.com/michaelmcmillan","followers_url":"https://api.github.com/users/michaelmcmillan/followers","following_url":"https://api.github.com/users/michaelmcmillan/following{/other_user}","gists_url":"https://api.github.com/users/michaelmcmillan/gists{/gist_id}","starred_url":"https://api.github.com/users/michaelmcmillan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaelmcmillan/subscriptions","organizations_url":"https://api.github.com/users/michaelmcmillan/orgs","repos_url":"https://api.github.com/users/michaelmcmillan/repos","events_url":"https://api.github.com/users/michaelmcmillan/events{/privacy}","received_events_url":"https://api.github.com/users/michaelmcmillan/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/appKom/notifier/labels/invalid","name":"invalid","color":"e6e6e6"}],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2014-04-08T09:00:29Z","updated_at":"2015-02-15T12:29:33Z","closed_at":"2015-02-15T12:29:33Z","body":"The regular expressions which try to strip HTML-tags form the response bodies in XMLHttpRequest can be bypassed.  \r\n```javascript\r\nhtml = html.replace(/<head\\b[^<]*(?:(?!<\\/head>)<[^<]*)*<\\/head>/gi, '');\r\nhtml = html.replace(/<link\\b[^<]*(?:(?!<\\/link>)<[^<]*)*<\\/link>/gi, '');\r\nhtml = html.replace(/<meta\\b[^<]*(?:(?!<\\/meta>)<[^<]*)*<\\/meta>/gi, '');\r\nhtml = html.replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '');\r\nhtml = html.replace(/<iframe\\b[^<]*(?:(?!<\\/iframe>)<[^<]*)*<\\/iframe>/gi, '');\r\nhtml = html.replace(/<frame\\b[^<]*(?:(?!<\\/frame>)<[^<]*)*<\\/frame>/gi, '');\r\nhtml = html.replace(/<frameset\\b[^<]*(?:(?!<\\/frameset>)<[^<]*)*<\\/frameset>/gi, '');\r\nhtml = html.replace(/<audio\\b[^<]*(?:(?!<\\/audio>)<[^<]*)*<\\/audio>/gi, '');\r\nhtml = html.replace(/<video\\b[^<]*(?:(?!<\\/video>)<[^<]*)*<\\/video>/gi, '');\r\nhtml = html.replace(/<object\\b[^<]*(?:(?!<\\/object>)<[^<]*)*<\\/object>/gi, '');\r\nhtml = html.replace(/<canvas\\b[^<]*(?:(?!<\\/canvas>)<[^<]*)*<\\/canvas>/gi, '');\r\nhtml = html.replace(/<applet\\b[^<]*(?:(?!<\\/applet>)<[^<]*)*<\\/applet>/gi, '');\r\nhtml = html.replace(/<embed\\b[^<]*(?:(?!<\\/embed>)<[^<]*)*<\\/embed>/gi, '');\r\nhtml = html.replace(/on\\w+\\s*?=\\s*?(\"[^\"]*\"|'[^']*')/gi, '');\r\nhtml = html.replace(/on\\w+\\s*?=/gi, 'title=');\r\nhtml = html.replace(/<[\\s]*?img/gi, '<pic');\r\nhtml = html.replace(/<[\\s]*?\\/[\\s]*?img/gi, '</pic');\r\n```\r\n\r\nExpression | Matches | Malicious\r\n--- | --- | ---\r\n`<audio\\b[^<]*(?:(?!<\\/audio>)<[^<]*)*<\\/audio>` | `<audio onerror=\"evil()\"></audio>` | `<aud<audio></audio>io onerror=\"evil()></audio>`\r\n\r\nA possible solution is to recursively traverse the HTML until everything is stripped, this is however a really slow way of solving the issue.\r\n"}}