Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Security Concern: eval-based Serialization in Seroval Breaks Strict CSP #1825

Open
amirhhashemi opened this issue Feb 22, 2025 · 7 comments
Open

Comments

@amirhhashemi
Copy link

amirhhashemi commented Feb 22, 2025

I'm not sure whether this is directly related to SolidStart, but I believe here is the best place to get the conversion going.

The issue I'm experiencing is related to the use of eval in Seroval, which I believe you use for serializing data in server functions. Use of eval is restricted for websites using a strict CSP, which is a huge problem because that's one of the main ways to protect against XSS attacks.

There is not a viable solution for this. Two potential fixes are:

  1. Adding 'unsafe-eval' to the script-src directive which, as its name implies, is unsafe.
  2. Using the Trusted Types API which has limited availability.

The only Issue I found about this is Eventually drop eval? which is closed and it seems there won't be any change. In that Issue, performance is mentioned as the main reason for using eval.

I get it, you want to be fast, but being fast in this instance comes with a huge cost and that is: basically no serious project can use SolidStart. I'm seriously considering moving to another framework just because of this, even though I'm using SolidStart for any serious project. I don't feel good about a framework that limits using a core security feature like CSP.

I'm surprised this has not come up before. I only found little information about it in Discord. So I'm not entirely sure what's going on and how this can be fixed. But I hope I get an answer here.

Thank you for reading this.

@lxsmnsyc
Copy link
Member

lxsmnsyc commented Feb 22, 2025

SolidStart (and SolidJS) uses seroval for serializing data, but only SolidStart uses the eval part of Seroval since SolidJS uses html streaming for inserting script elements. I'm not sure if there's a workaround for eval but we needed the JS serialization format since it's a lot faster and cheaper (in terms of response size) than if we go for the JSON route (Seroval also offers that mode), which is like 100x worse in terms of perf.

@thedanchez
Copy link

I think the OP is more questioning the rationale of sacrificing security for the sake of performance? For some, that tradeoff could be a dealbreaker.

@amirhhashemi
Copy link
Author

I'm obviously not an expert in this area, but I wonder if this 100x difference is a significant concern in practice. I haven't noticed if other popular frameworks require eval for serialization. So it seems JSON-based serialization is at least passable.

I'm not suggesting changing the default serialization method, but I think it would be valuable for some users to have the option to choose a slightly slower serialization method if they prioritize security over speed.

@XiNiHa
Copy link

XiNiHa commented Feb 25, 2025

turbo-stream, a Seroval-like streaming ser/de package that is used with React Router, does not use eval, and therefore performs pretty poorly: lxsmnsyc/seroval@b5f7bf0

@amirhhashemi
Copy link
Author

amirhhashemi commented Feb 25, 2025

In most benchmarks, devalue performs similarly without using eval. It's slightly slower, but in a realistic scenario, it seems to be fast enough since it's used in Svelte.

Now that I have seen the benchmarks, the performance argument makes less sense to me. Honestly, I'm not convinced I'm going to feel a performance hit if SolidStart used, for example, devalue.

@lxsmnsyc
Copy link
Member

lxsmnsyc commented Feb 25, 2025

devalue never really considered eval iirc, while seroval's prior art was an eval serde.

Performance isn't really the main concern, but the response size affects the client (the JSON print of seroval is a lot larger than it's JS output), which in turn affects client performance. In which case, creating another serialization format for the sake of response size, perf and security might be the next other option. (React does this)

I'll need to discuss this with Ryan, but for now, the current state is highly desirable.

@thedanchez
Copy link

Yeah, flexibility for configuration in this area I think is a good compromise. Can easily keep the current behavior as the default and just provide the other methods of serialization alongside it. Hope that conversation goes well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants