This content originally appeared on flaviocopes.com and was authored by flaviocopes.com
This post is part of a new series where we build a clone of Airbnb with Next.js. See the first post here.
Our form is great, but we have a problem: the house description.
It is handling the description as HTML:
Unless our target audience for house owners is people that know HTML, this is not going to do a good job.
We need a more user friendly editor.
Second thing, even more important, is that we still don’t have it in the single page view, in the pages/houses/[id].js
file.
I deferred this task until now, because I want to show you something.
If we add the house description to pages/houses/[id].js
:
...
<p>{props.house.title}</p>
<div>{props.house.description}</div>
...
We’ll find a bad surprise:
The HTML is fully visible, and not interpreted! Just like in the editor above.
The reason is that JSX escapes all content by default, which is great to prevent XSS for example, but not great in this case.
What we must do is, we have to use dangerouslySetInnerHTML
:
pages/houses/[id].js
<div
dangerouslySetInnerHTML={{
__html: props.house.description
}}></div>
to make the description interpreted as HTML.
But if we don’t do any kind of filtering to the description, a house owner could also write JavaScript into the description, for example:
<script>alert('test')</script>
And this would run on the house page to people browsing for houses.
This is an XSS vulnerability.
Let’s do the first step first - we add an editor.
Add the Pell editor
The editor I chose is Pell.
It’s easy to use and small in size.
There’s also a React wrapper available at https://github.com/bpetetot/react-pell.
Install it using npm:
npm install react-pell
then go into components/HouseForm.js
and import it:
import Editor from 'react-pell'
Now change
<p>
<label>House description</label>
<textarea
required
onChange={event => setDescription(event.target.value)}
value={description}></textarea>
</p>
to this:
<div>
<Editor
onChange={html => setDescription(html)}
defaultContent={description}
actions={['bold', 'underline', 'italic']}
/>
</div>
and add this CSS block at the bottom, before the closing </div>
tag of the component:
<style jsx global>{`
.pell-container {
border: 1px solid #ccc;
}
.pell,
.pell-content {
box-sizing: border-box;
}
.pell-content {
height: 300px;
outline: 0;
overflow-y: auto;
padding: 10px;
}
.pell-actionbar {
background-color: #fff;
border-bottom: 1px solid hsla(0, 0%, 4%, 0.1);
}
.pell-button {
background-color: transparent;
border: none;
cursor: pointer;
height: 30px;
outline: 0;
width: 30px;
vertical-align: bottom;
color: black;
}
.pell-button-selected {
background-color: #f0f0f0;
}
`}</style>
This is the end result:
You should now be able to save the house description.
Solving the XSS problem
Now off to the second part - the XSS vulnerability caused by the use of dangerouslySetInnerHTML
.
How do we solve that? In the backend we are going to whitelist some tags in the description, eliminating all other tags. I’m going to use the sanitize-html npm package.
Run
npm install sanitize-html
Now in server.js
we add this line at the top:
const sanitizeHtml = require('sanitize-html')
and before saving the house using Sequelize in the /api/host/edit
and /api/host/new
endpoints, we add:
houseData.description = sanitizeHtml(houseData.description, {
allowedTags: [ 'b', 'i', 'em', 'strong', 'p', 'br' ]
})
This will clean the description and remove all tags except the ones we specifically allow.
This content originally appeared on flaviocopes.com and was authored by flaviocopes.com
flaviocopes.com | Sciencx (2022-01-08T05:00:00+00:00) Airbnb clone, safe HTML for the house description. Retrieved from https://www.scien.cx/2022/01/08/airbnb-clone-safe-html-for-the-house-description/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.