go-yaml / yaml

YAML support for the Go language.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

safe yaml templating as a new feature

irsl opened this issue · comments

commented

Many applications use text/template (or even html/template!) with the intention to replace simple strings in a template that will be used later on as YAML. This approach is vulnerable to YAML injection attacks, if the replacement string is controlled by an attacker. We have seen many real-world, exploitable vulnerabilities with this root cause.

I propose safe templating feature to be added into this library with an interface compatible with text/template (so fixing vulnerable integrations would be super-easy).

I've got a prototype ready, it looks like this:

func TestSimple(t *testing.T) {
        yamlTemplate := `
name: "{{ .Name }}"
type: "{{ .PDType }}"
`
        tmpl, err := template.New("test").Parse(yamlTemplate)
        if err != nil {
                t.Fatalf("tmpl.Parse() error = %v", err)
        }

        type PersistentDiskType string

        type StorageClassSpec struct {
                Name   string
                PDType PersistentDiskType
        }

        var buf bytes.Buffer
        err = tmpl.Execute(&buf, StorageClassSpec{Name: "ssd", PDType: "pd-ssd"})
        if err != nil {
                t.Errorf("tmpl.Execute() error = %v", err)
        }
        expected := "name: ssd\ntype: pd-ssd\n"
        if buf.String() != expected {
                t.Errorf("tmpl.Execute() = %v, want: %v", buf.String(), expected)
        }

        buf.Reset()
        err = tmpl.Execute(&buf, StorageClassSpec{Name: "ssd\ninjection", PDType: "pd-ssd\ninjection"})
        if err != nil {
                t.Errorf("tmpl.Execute() error = %v", err)
        }
        expected = "name: |-\n    ssd\n    injection\ntype: |-\n    pd-ssd\n    injection\n"
        if buf.String() != expected {
                t.Errorf("tmpl.Execute() = %v, want: %v", buf.String(), expected)
        }
}

Why do I propose this feature to be part of this library (instead of publishing it as an independent one)?

  1. For better adoption
  2. To support templates that are not valid yaml (missing quotation marks), e.g. this one:
type: {{ print .ObjectMeta "" }}

For sake of a PoC, I've modified the parser (decode.go) to accept this syntax when it is configured in templating mode.

I'm happy to send a PR if you are open for this contribution.