Skip to content

Commit

Permalink
Merge pull request #32 from KissKissBankBank/security/sanitize-content
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorentD authored Apr 29, 2022
2 parents 1aedc05 + 775a1c7 commit 3a6aadc
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 28 deletions.
16 changes: 9 additions & 7 deletions lib/controls/video/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
isPreviousEmptyBlock,
moveSelectionTo,
removePreviousEmptyBlock,
sanitizeIframeReactComp,
} from "../../utils";
import { getDataForProvider } from "./providers";

Expand All @@ -34,6 +35,7 @@ const VideoEditor = ({ contentState, entityKey, blockKey }) => {
dispatch(updateEditor(moveSelectionTo(editorState, blockKey)));
};
const hasFocus = hasEntityFocus(contentState, editorState, entityKey);
const reactComp = parseHtml(embedlyHtml || html, { sanitize: false });
return (
<ResponsiveIframeContainer
ratio={embedRatio || 67.5}
Expand All @@ -46,7 +48,7 @@ const VideoEditor = ({ contentState, entityKey, blockKey }) => {
})}
onClick={onClick}
>
{parseHtml(embedlyHtml || html, { sanitize: false })}
{sanitizeIframeReactComp(reactComp)}
</div>
</ResponsiveIframeContainer>
);
Expand All @@ -56,13 +58,14 @@ const VideoDisplayer = (props) => {
const { embedlyHtml, embedRatio, height, html } = props.contentState
.getEntity(props.entityKey)
.getData();
const reactComp = parseHtml(embedlyHtml || html, { sanitize: false });
return (
<ResponsiveIframeContainer
ratio={embedRatio || 67.5}
className="kiss-Draft__media-read"
style={{ ...(height && { height }) }}
>
{parseHtml(embedlyHtml || html, { sanitize: false })}
{sanitizeIframeReactComp(reactComp)}
</ResponsiveIframeContainer>
);
};
Expand Down Expand Up @@ -162,10 +165,7 @@ const VideoControls = ({ disabled, onChange, embedlyApiKey }) => {
{({ handleSubmit, isSubmitting, values }) => {
return (
<>
<Label
className="k-u-margin-bottom-single"
htmlFor="url"
>
<Label className="k-u-margin-bottom-single" htmlFor="url">
{translations.image_upload.label}
</Label>
<InputWithButton
Expand Down Expand Up @@ -200,7 +200,9 @@ const VideoControls = ({ disabled, onChange, embedlyApiKey }) => {
ratio={embedRatio}
style={{ ...(height && { height }) }}
>
{parseHtml(embedlyHtml, { sanitize: false })}
{sanitizeIframeReactComp(
parseHtml(embedlyHtml, { sanitize: false })
)}
</ResponsiveIframeContainer>
</div>
)}
Expand Down
1 change: 0 additions & 1 deletion lib/controls/video/providers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ export const calculRatio = ({ height, width }) =>
((height / width) * 100).toPrecision(4);

export const getDataForProvider = (response) => {
console.log(response);
if (
response.type === "video" ||
(response.type === "rich" && response.provider_name !== "SoundCloud")
Expand Down
29 changes: 15 additions & 14 deletions lib/decorators/lazy-media.jsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
import React from 'react'
import {
LazyLoader,
parseHtml,
ResponsiveIframeContainer,
LazyLoader
} from '@kisskissbankbank/kitten'
} from "@kisskissbankbank/kitten";
import React from "react";
import { sanitizeIframeReactComp } from "../utils";

const Media = (props) => {
const { html } = props.contentState.getEntity(props.entityKey).getData()

const { html } = props.contentState.getEntity(props.entityKey).getData();
const reactComp = parseHtml(html, { sanitize: false });
return (
<LazyLoader>
<ResponsiveIframeContainer ratio={67.5}>
{parseHtml(html, { sanitize: false })}
{sanitizeIframeReactComp(reactComp)}
</ResponsiveIframeContainer>
</LazyLoader>
)
}
);
};

const mediaStrategy = (contentBlock, callback, contentState) => {
contentBlock.findEntityRanges((character) => {
const entityKey = character.getEntity()
const entityKey = character.getEntity();
return (
entityKey !== null &&
contentState.getEntity(entityKey).getType() === 'MEDIA'
)
}, callback)
}
contentState.getEntity(entityKey).getType() === "MEDIA"
);
}, callback);
};

export default {
strategy: mediaStrategy,
component: Media,
}
};
23 changes: 23 additions & 0 deletions lib/utils.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { sanitizeUrl } from "@braintree/sanitize-url";
import { domElementHelper } from "@kisskissbankbank/kitten";
import {
AtomicBlockUtils,
Expand All @@ -15,6 +16,7 @@ import flow from "lodash/fp/flow";
import get from "lodash/fp/get";
import isEmpty from "lodash/fp/isEmpty";
import omit from "lodash/fp/omit";
import pick from "lodash/fp/pick";
import reduce from "lodash/fp/reduce";
import trim from "lodash/fp/trim";
import { decorator as buttonLinkDecorator } from "./controls/button-link";
Expand All @@ -33,6 +35,27 @@ export const isJSONContent = (content) => {
}
};

export const sanitizeIframeReactComp = (iframeReactComp) => {
return {
...iframeReactComp,
props: {
...pick([
"allow",
"allowFullScreen",
"className",
"style",
"sandbox",
"frameBorder",
"height",
"scrolling",
"title",
"width",
])(iframeReactComp?.props),
src: sanitizeUrl(iframeReactComp?.props?.src),
},
};
};

export const getJSONContent = (value) => {
if (!domElementHelper.canUseDom()) return {};
return isJSONContent(value) ? JSON.parse(value) : getRawContent(value, true);
Expand Down
23 changes: 17 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"translations": "docusaurus write-translations"
},
"dependencies": {
"@braintree/sanitize-url": "^6.0.0",
"@kisskissbankbank/kitten": "^10.3.0",
"classnames": "^2.3.1",
"draft-convert": "^2.1.12",
Expand Down

1 comment on commit 3a6aadc

@vercel
Copy link

@vercel vercel bot commented on 3a6aadc Apr 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.