XSS and Reduced Markdown for Admin (#355)
This commit is contained in:
parent
1ae519e251
commit
a043c2dfa6
|
@ -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",
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
|
@ -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>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -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"
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -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: [],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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())
|
||||||
|
|
Loading…
Reference in New Issue