GithubHelp home page GithubHelp logo

Escape by default about hiccup HOT 8 CLOSED

weavejester avatar weavejester commented on July 4, 2024
Escape by default

from hiccup.

Comments (8)

DerGuteMoritz avatar DerGuteMoritz commented on July 4, 2024 2

Why was this issue closed? Not escaping by default is really bad and leads to all kinds of vulnerabilities which could easily be avoided. Why does html need to be nestable and why does it block this feature?

from hiccup.

weavejester avatar weavejester commented on July 4, 2024

If you can figure out a way of doing this without significantly impacting performance, I'm all ears :)

Metadata can't be added to strings, and Hiccup functions frequently return strings of HTML, e.g.

(defhtml foo [x]
  [:div.foo x])

from hiccup.

ngocdaothanh avatar ngocdaothanh commented on July 4, 2024

Metadata can't be added to strings

Because the reason to add metadata to a string is to mark that the string should not be escaped automatically, I think there is some other way to mark.

For example, (raw s) would convert s to:

  • a map {:raw true, :content s}
  • or an object of a special class MyRawString

then on rendering check if the input has the mark.

Because we are outputting HTML elements, another way is to mark the entire element to be raw:

[:div {:raw true, :style "some style"} anything]

"raw" is not a common HTML attribute, so I think it would be OK.

from hiccup.

weavejester avatar weavejester commented on July 4, 2024

The problem with this approach is that the html macro would have to return (raw s) as well, e.g.

(html [:span "foo"])
=> {:raw true, :content "<span>foo</span>"}

This needs to be the case so that we can embed one HTML inside another:

(defhtml foo [x]
  [:span.foo x])

(html [:div (foo "hello")])
=> <div><span class="foo">hello</span></div>

from hiccup.

ngocdaothanh avatar ngocdaothanh commented on July 4, 2024

How about the option style approach?
[:div {:raw true, :style "some style"} anything]

I feel that it works and it is more elegant than the (raw s) approach.

from hiccup.

weavejester avatar weavejester commented on July 4, 2024

No, it wouldn't really work. The problem is that this:

(html [:div (html [:span "foo"])])

Needs to produce the same output as:

(html [:div [:span "foo"]])

And this output needs to be indistinguishable from a string.

from hiccup.

weavejester avatar weavejester commented on July 4, 2024

There are several issues that can only be solved by a redesign of the Hiccup compiler. I was in two minds whether to keep them all, or whether to close all but one, since they're all facets of the same problem. In the end, I chose to keep issue #7 up and close the rest.

As to why it's not possible with the current architecture, consider the following code:

(defn foo [x]
  (html [:div.foo x]))

(defn bar [x]
  (html [:div.bar (foo x)]))

If we automatically escape all strings, then the result of (bar "baz") will be:

<div class="bar">&lt;div class=&quot;foo&quot;&gt;baz&lt;/div&gt;</div>

Instead of:

<div class="bar"><div class="foo">baz</div></div>

You might very well say that we could just require that the html macro is only at the top level, i.e.

(defn foo [x]
  [:div.foo x])

(defn bar [x]
  (html [:div.bar (foo x)]))

The problem with this approach is that (a) it breaks existing code, and (b) Hiccup can no longer pre-compile foo. It has to parse the body each time, making it significantly slower.

So what's the solution?

Well, the only real solution is for html not to return a string, but I haven't worked out an efficient design for that yet. It might be that a performance hit is just something we need to take, but I'd like to explore all options first.

from hiccup.

DerGuteMoritz avatar DerGuteMoritz commented on July 4, 2024

Thanks a lot for the detailed reply! In my case I'd much prefer a safe over a fast version. I have started hacking up a custom solution which does the trick. Perhaps it would make sense if I polished it some more and then released it as a separate project? I don't want to fragment the library space too much though so if you are working on the issue and are willing to change Hiccup's default behavior in such a breaking way, let me know and I'll happily use my custom solution until that new Hiccup version comes around :-)

from hiccup.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.