Skip to content

Commit

Permalink
fix: prevent xss in form block reading sent data from BE response (#651)
Browse files Browse the repository at this point in the history
* fix: prevent xss in form block reading sent data from BE response

* chore: added customization for FormResult component and updated volto-form-block

* fix: replaceMessage

* chore: updated volto-form-block

* chore: customizations infos

---------

Co-authored-by: Piero Nicolli <[email protected]>
  • Loading branch information
giuliaghisini and pnicolli authored May 20, 2024
1 parent 449875d commit 81a5a9e
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 55 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
"volto-dropdownmenu": "4.1.1",
"volto-editablefooter": "5.1.1",
"volto-feedback": "0.3.0",
"volto-form-block": "3.7.2",
"volto-form-block": "3.7.5",
"volto-gdpr-privacy": "2.2.5",
"volto-google-analytics": "2.0.0",
"volto-multilingual-widget": "3.2.1",
Expand Down
77 changes: 77 additions & 0 deletions src/customizations/volto-form-block/components/FormResult.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
CUSTOMIZATIONS:
- used design-react-kit components to render form result
*/
import React from 'react';
import { useIntl, defineMessages } from 'react-intl';
import { Button, Alert } from 'design-react-kit';
import { getFieldName } from 'volto-form-block/components/utils';

const messages = defineMessages({
success: {
id: 'form_submit_success',
defaultMessage: 'Sent!',
},
reset: {
id: 'form_reset',
defaultMessage: 'Clear',
},
});

const alertTransition = {
appear: true,
baseClass: 'fade',
baseClassActive: 'show',
enter: true,
exit: true,
in: true,
mountOnEnter: false,
tag: 'div',
timeout: 150,
unmountOnExit: true,
};

/* Function that replaces variables from the user customized message */
const replaceMessage = (text, sent_data) => {
let i = 0;
while (i < sent_data.length) {
let idField = getFieldName(sent_data[i].label, sent_data[i].field_id);
text = text.replaceAll('${' + idField + '}', sent_data[i].value ?? '');
i++;
}
text = text.replaceAll('\n', '<br/>');
return text;
};

const FormResult = ({ formState, data, resetFormState }) => {
const intl = useIntl();
return (
<Alert color="success" fade isOpen tag="div" transition={alertTransition}>
<h4>{intl.formatMessage(messages.success)}</h4>
<br />
{/* Custom message */}
{data.send_message && (
<>
<p
dangerouslySetInnerHTML={{
__html: replaceMessage(data.send_message, formState.result.data),
}}
/>
<br />
</>
)}
<Button
color="primary"
outline
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
resetFormState();
}}
>
{intl.formatMessage(messages.reset)}
</Button>
</Alert>
);
};
export default FormResult;
55 changes: 6 additions & 49 deletions src/customizations/volto-form-block/components/FormView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import { getFieldName } from 'volto-form-block/components/utils';
// eslint-disable-next-line import/no-unresolved
import Field from 'volto-form-block/components/Field';
import { FormResult } from 'volto-form-block/components';
// eslint-disable-next-line import/no-unresolved
import config from '@plone/volto/registry';

Expand Down Expand Up @@ -86,23 +87,6 @@ const FormView = ({
return formErrors?.filter((e) => e.field === field).length === 0;
};

/* Function that replaces variables from the user customized message */
const replaceMessage = (text) => {
let i = 0;
while (i < data.subblocks.length) {
let idField = getFieldName(
data.subblocks[i].label,
data.subblocks[i].field_id,
);
text = text.replaceAll(
'${' + idField + '}',
formData[idField]?.value || '',
);
i++;
}
return text;
};

var FieldSchema = config.blocks.blocksConfig.form.fieldSchema;
var fieldSchemaProperties = FieldSchema()?.properties;
var fields_to_send = [];
Expand All @@ -128,38 +112,11 @@ const FormView = ({
<Card className="card-bg rounded py-3" noWrapper={false} tag="div">
<CardBody tag="div">
{formState.result ? (
<Alert
color="success"
fade
isOpen
tag="div"
transition={alertTransition}
>
<h4>{intl.formatMessage(messages.success)}</h4>
<br />
{/* Custom message */}
{data.send_message && (
<>
<p
dangerouslySetInnerHTML={{
__html: replaceMessage(data.send_message),
}}
/>
<br />
</>
)}
<Button
color="primary"
outline
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
resetFormState();
}}
>
{intl.formatMessage(messages.reset)}
</Button>
</Alert>
<FormResult
formState={formState}
data={data}
resetFormState={resetFormState}
/>
) : (
<form
onSubmit={submit}
Expand Down
10 changes: 5 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8216,7 +8216,7 @@ __metadata:
volto-dropdownmenu: 4.1.1
volto-editablefooter: 5.1.1
volto-feedback: 0.3.0
volto-form-block: 3.7.2
volto-form-block: 3.7.5
volto-gdpr-privacy: 2.2.5
volto-google-analytics: 2.0.0
volto-multilingual-widget: 3.2.1
Expand Down Expand Up @@ -16128,9 +16128,9 @@ __metadata:
languageName: node
linkType: hard

"volto-form-block@npm:3.7.2":
version: 3.7.2
resolution: "volto-form-block@npm:3.7.2"
"volto-form-block@npm:3.7.5":
version: 3.7.5
resolution: "volto-form-block@npm:3.7.5"
dependencies:
"@hcaptcha/react-hcaptcha": ^0.3.6
file-saver: ^2.0.5
Expand All @@ -16139,7 +16139,7 @@ __metadata:
peerDependencies:
"@plone/volto": ">=16.0.0-alpha.38"
volto-subblocks: ^2.0.0
checksum: 7387a1b85a877c3da5dd800b33b6a01673ef60e2bcecd2c25cafd22f8474bf167e0f39befc289d2ae8614abf35fdd424066dd83a77ad0bdced2d297ef8652eeb
checksum: fdd00192dff971ccec1e6b299d570116d194b2aa4fa010e0e4f201f603eeb67afb5887178abdab8504ca4687761495cb5c2272241e79474cdd6e36d6adc54cbe
languageName: node
linkType: hard

Expand Down

0 comments on commit 81a5a9e

Please sign in to comment.