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

What kind of end user security does this implementation have? #35

Open
salman-ca opened this issue Jan 4, 2019 · 2 comments
Open

What kind of end user security does this implementation have? #35

salman-ca opened this issue Jan 4, 2019 · 2 comments

Comments

@salman-ca
Copy link

Compared to the ruby implementation, does the go version have similar security/safety guarantees?
What I mean is, liquid was meant for end-user modification and should not allow malicious code to be executed.
Curious as to your comments in this regards.

Great work!

@osteele
Copy link
Owner

osteele commented May 12, 2019

Here's what I can think of:

  • The code, and the included filters and tags, don't access the disk or network.
  • It is trivial to write a template that runs an infinite loop or consumes arbitrarily large CPU or RAM resources. If untrusted templates are run, this can be used to inject a DoS attack.
  • It is trivial to write a template that runs on some data, but runs an infinite loop or consumes arbitrarily large CPU or RAM resources depending on the data. If data from untrusted sources is used, even on a trusted (but insufficiently audited) template, this can be used in a DoS attack.
  • If you run any third-party tags, filters, or Droplet providers, you're running whatever Go code implements those extensions, which could of course do anything. You have to do some explicit programming work to compile or link such code into your program, of course.
  • This code hasn't had an independent security audit, so user beware. There are likely to be vulnerabilities that I'm not aware of. I don't think the code base is particularly low-quality or insecure, but I also think that most unaudited code bases of similar size and complexity — especially code that implements interpreters, such as this program — are likely to have vulnerabilities.

@jamslinger
Copy link
Contributor

Hi, first of all many thanks for the effort building this engine for Go, I very much appreciate it :) Now, I'm also using this in a public domain, i.e. end users are able to define their own templates. Of course DoS is a potential risk which must be tackled somehow in order to prevent server-side issues. Right now I do this via a timer + panic/recover, something like:

	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
		}
	}()

	t := time.NewTimer(time.Second)
	done := make(chan struct{})
	go func() {
		_, _ = schema.Liquid.ParseAndRenderString(tmpl.Template, map[string]any{
			"order": order,
		})
		done <- struct{}{}
	}()

	select {
	case <-t.C:
		panic("render deadline exceeded")
	case <-done:
		t.Stop()
	}

This works. However, it would be nice if I could handle this via the engine directly, e.g. by passing a context.Context with a timeout to RenderWithContext, by specifying an upper buffer size limit or by allowing to pass a custom io.Writer to e.g. RenderF. Do you have any thoughts on this?

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

3 participants