Rendering html combined with unsafe data with Phoenix.HTML

Say I have some external (unsafe) data

unsafe_data = "some unsafe data"

I want to render this using Phoenix.HTML.Tag.content_tag/2

content_tag(:p, "<i>#{unsafe_data}</i>") |> safe_to_string

It will render:

"<p>&lt;i&gt;some unsafe data&lt;/i&gt;</p>"

This will create html entities, so <i> will be literally printed on the screen.
So I can use Phoenix.HTML.raw/1:

content_tag(:p, raw "<i>#{unsafe_data}</i>") |> safe_to_string

However, this should not be secure.

Maybe I have to do the following?

unsafe_data = safe_to_string(html_escape(unsafe_data)) # <- does that make any sense?

content_tag(:p, raw "<i>#{unsafe_data}</i>") |> safe_to_string

Thank you for any help!

For this particular example, the best would be:

content_tag(:p, content_tag(:i, unsafe_data))

Alternatively you can put it in a list marking the safe parts:

content_tag(:p, [{:safe, "<i>"}, "<omg>", {:safe, "</i>"}])
7 Likes

You can also just use the sigil too:

content_tag(:p, ~E"<i><%= unsafe_data %></i>

Or all of it:

~E"<p><i><%= unsafe_data %></i></p>"
3 Likes

LiveView 0.17.5 – trying to render some unsafe data

unsafe_data = "<p><h2>This is the first post in child marriage.&nbsp;</h2><p>&nbsp;</p><ol><li>Say whatever you want here.&nbsp;</li></ol></p>"

Body: <%= unsafe_data %>

renders as

I wish it would render properly. Proper Render should be like following
image

None of the above approaches, works for me.

I am trying to guess your intention here. Maybe you want to sanitize the html then render it raw?

Sanitisation - that might be the first step

but importantly, seeing the html being ‘interpreted’ by the browser and not being printed in raw form as it is in above post.

Phoenix defaults to escape the html to prevent XSS attacks (what if someone embed javascript in the unsafe data?) If you have sanitize it or you have reason to believe that it is clean, just raw/1 it. See the 2 links I cited above.

1 Like

I can raw/1. That must be my first step. But that does not render it properly.

Current render after raw/1 is —

Proper render is – https://elixirforum.com/uploads/default/original/3X/f/a/fa61819915cc5477f65f3e4a5d70a5b49033ddf7.png

How do I render it properly after raw/1?

Without seeing your code I cannot guess what went wrong.

show.html.heex

<h1>Show Post</h1>

<%= if @live_action in [:edit] do %>
  <%= live_modal Lms01Web.PostLive.FormComponent,
    id: @post.id,
    title: @page_title,
    action: @live_action,
    post: @post,
    return_to: Routes.post_show_path(@socket, :show, @post) %>
<% end %>

<ul>
  <li>
    <strong>Title:</strong>
    <%= @post.title %>
  </li>
 

 <%# THIS LINE IS THE PROBLEM %>
 
  <li phx-hook="PostList" data-post={"postbody-#{@post.id}"}>
    <strong>Body:</strong>
    <%= @post.body %>
  </li>

  <li>
    <strong>Published:</strong>
    <%= @post.published %>
  </li>

  <li>
    <strong>Author:</strong>
    <%= @post.author %>
  </li>

  <li>
    <strong>Keywords:</strong>
    <%= @post.keywords %>
  </li>

</ul>

<span><%= live_patch "Edit", to: Routes.post_show_path(@socket, :edit, @post), class: "button" %></span> |
<span><%= live_redirect "Back", to: Routes.post_index_path(@socket, :index) %></span>

@post.body renders the html raw.

How do I get liveview to interpret html and make headings as they should be.

this is how body looks.

Body: is not rendered properly.

<%= raw(@post.body) %>

strange.

This exact thing was not working yesterday.

now it is working. :slight_smile:

thanks. I feel almost foolish .