XSS and Reduced Markdown for Admin (#355)

This commit is contained in:
AMStrix 2019-03-13 18:35:22 -05:00 committed by Daniel Ternyak
parent 1ae519e251
commit a043c2dfa6
7 changed files with 52 additions and 8 deletions

View File

@ -106,7 +106,7 @@
"webpack-cli": "^3.1.0", "webpack-cli": "^3.1.0",
"webpack-dev-server": "3.2.1", "webpack-dev-server": "3.2.1",
"webpack-hot-middleware": "^2.24.0", "webpack-hot-middleware": "^2.24.0",
"xss": "1.0.3" "xss": "^1.0.3"
}, },
"devDependencies": { "devDependencies": {
"@types/bn.js": "4.11.1", "@types/bn.js": "4.11.1",

View File

@ -5,12 +5,13 @@ import './index.less';
interface Props extends React.HTMLAttributes<HTMLDivElement> { interface Props extends React.HTMLAttributes<HTMLDivElement> {
source: string; source: string;
reduced?: boolean;
} }
export default class Markdown extends React.PureComponent<Props> { export default class Markdown extends React.PureComponent<Props> {
render() { render() {
const { source, ...rest } = this.props; const { source, reduced, ...rest } = this.props;
const html = mdToHtml(source); const html = mdToHtml(source, reduced);
// TS types seem to be fighting over react prop defs for div // TS types seem to be fighting over react prop defs for div
const divProps = rest as any; const divProps = rest as any;
return ( return (

View File

@ -54,7 +54,7 @@ class ModerationItem extends React.Component<Comment> {
} }
description={ description={
<ShowMore height={100}> <ShowMore height={100}>
<Markdown source={p.content} /> <Markdown source={p.content} reduced />
</ShowMore> </ShowMore>
} }
/> />

View File

@ -270,7 +270,11 @@ class UserDetailNaked extends React.Component<Props, State> {
</Link>{' '} </Link>{' '}
at {formatDateMs(c.dateCreated)} at {formatDateMs(c.dateCreated)}
</div> </div>
<Markdown source={c.content} className="UserDetail-comment" /> <Markdown
source={c.content}
reduced
className="UserDetail-comment"
/>
</> </>
} }
/> />

View File

@ -1,4 +1,5 @@
import Showdown from 'showdown'; import Showdown from 'showdown';
import xss from 'xss';
const showdownConverter = new Showdown.Converter({ const showdownConverter = new Showdown.Converter({
simplifiedAutoLink: true, simplifiedAutoLink: true,
@ -9,6 +10,41 @@ const showdownConverter = new Showdown.Converter({
excludeTrailingPunctuationFromURLs: true, excludeTrailingPunctuationFromURLs: true,
}); });
export const mdToHtml = (text: string) => { export const mdToHtml = (text: string, reduced: boolean = false) => {
return showdownConverter.makeHtml(text); const html = showdownConverter.makeHtml(text);
return reduced ? xss(html, reducedXssOpts) : xss(html);
};
const reducedXssOpts = {
stripIgnoreTag: true,
whiteList: {
a: ['target', 'href', 'title'],
b: [],
blockquote: [],
br: [],
code: [],
del: [],
em: [],
h4: [],
h5: [],
h6: [],
hr: [],
i: [],
li: [],
ol: [],
p: [],
pre: [],
small: [],
sub: [],
sup: [],
strong: [],
table: ['width', 'border', 'align', 'valign'],
tbody: ['align', 'valign'],
td: ['width', 'rowspan', 'colspan', 'align', 'valign'],
tfoot: ['align', 'valign'],
th: ['width', 'rowspan', 'colspan', 'align', 'valign'],
thead: ['align', 'valign'],
tr: ['rowspan', 'align', 'valign'],
ul: [],
},
}; };

View File

@ -8477,9 +8477,10 @@ xregexp@4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020"
xss@1.0.3: xss@^1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.3.tgz#d04bd2558fd6c29c46113824d5e8b2a910054e23" resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.3.tgz#d04bd2558fd6c29c46113824d5e8b2a910054e23"
integrity sha512-LTpz3jXPLUphMMmyufoZRSKnqMj41OVypZ8uYGzvjkMV9C1EdACrhQl/EM8Qfh5htSAuMIQFOejmKAZGkJfaCg==
dependencies: dependencies:
commander "^2.9.0" commander "^2.9.0"
cssfilter "0.0.10" cssfilter "0.0.10"

View File

@ -385,6 +385,8 @@ def make_envelope(to, type, email_args):
def sendgrid_send(mail): def sendgrid_send(mail):
to = mail.___to
type = mail.___type
try: try:
sg = sendgrid.SendGridAPIClient(apikey=SENDGRID_API_KEY) sg = sendgrid.SendGridAPIClient(apikey=SENDGRID_API_KEY)
res = sg.client.mail.send.post(request_body=mail.get()) res = sg.client.mail.send.post(request_body=mail.get())