forked from google/safehtml
-
Notifications
You must be signed in to change notification settings - Fork 0
/
trustedsource.go
105 lines (94 loc) · 4.39 KB
/
trustedsource.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright (c) 2017 The Go Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
package template
import (
"fmt"
"os"
"path/filepath"
"strings"
"flag"
)
// A TrustedSource is an immutable string-like type referencing
// trusted template files under application control. It can be passed to
// template-parsing functions and methods to safely load templates
// without the risk of untrusted template execution.
//
// In order to ensure that an attacker cannot influence the TrustedSource
// value, a TrustedSource can be instantiated only from untyped string
// constants, command-line flags, and other application-controlled strings, but
// never from arbitrary string values potentially representing untrusted user input.
//
// Note that TrustedSource's constructors cannot truly guarantee that the
// templates it references are not attacker-controlled; it can guarantee only that
// the path to the template itself is under application control. Users of these
// constructors must ensure themselves that TrustedSource never references
// attacker-controlled files or directories that contain such files.
type TrustedSource struct {
// We declare a TrustedSource not as a string but as a struct wrapping a string
// to prevent construction of TrustedSource values through string conversion.
src string
}
// TrustedSourceFromConstant constructs a TrustedSource with its underlying
// src set to the given src, which must be an untyped string constant.
//
// No runtime validation or sanitization is performed on src; being under
// application control, it is simply assumed to comply with the TrustedSource type
// contract.
func TrustedSourceFromConstant(src stringConstant) TrustedSource {
return TrustedSource{string(src)}
}
// TrustedSourceFromConstantDir constructs a TrustedSource calling path/filepath.Join on
// an application-controlled directory path, which must be an untyped string constant,
// a TrustedSource, and a dynamic filename. It returns an error if filename contains
// filepath or list separators, since this might cause the resulting path to reference a
// file outside of the given directory.
//
// dir or src may be empty if either of these path segments are not required.
func TrustedSourceFromConstantDir(dir stringConstant, src TrustedSource, filename string) (TrustedSource, error) {
if i := strings.IndexAny(filename, string([]rune{filepath.Separator, filepath.ListSeparator})); i != -1 {
return TrustedSource{}, fmt.Errorf("filename %q must not contain the separator %q", filename, filename[i])
}
if filename == ".." {
return TrustedSource{}, fmt.Errorf("filename must not be the special name %q", filename)
}
return TrustedSource{filepath.Join(string(dir), src.String(), filename)}, nil
}
// TrustedSourceJoin is a wrapper around path/filepath.Join that returns a
// TrustedSource formed by joining the given path elements into a single path,
// adding an OS-specific path separator if necessary.
func TrustedSourceJoin(elem ...TrustedSource) TrustedSource {
return TrustedSource{filepath.Join(trustedSourcesToStrings(elem)...)}
}
// TrustedSourceFromFlag returns a TrustedSource containing the string
// representation of the retrieved value of the flag.
//
// In a server setting, flags are part of the application's deployment
// configuration and are hence considered application-controlled.
func TrustedSourceFromFlag(value flag.Value) TrustedSource {
return TrustedSource{fmt.Sprint(value.String())}
}
// TrustedSourceFromEnvVar is a wrapper around os.Getenv that
// returns a TrustedSource containing the value of the environment variable
// named by the key. It returns the value, which will be empty if the variable
// is not present. To distinguish between an empty value and an unset value,
// use os.LookupEnv.
//
// In a server setting, environment variables are part of the application's
// deployment configuration and are hence considered application-controlled.
func TrustedSourceFromEnvVar(key stringConstant) TrustedSource {
return TrustedSource{os.Getenv(string(key))}
}
// String returns the string form of the TrustedSource.
func (t TrustedSource) String() string {
return t.src
}
func trustedSourcesToStrings(paths []TrustedSource) []string {
ret := make([]string, 0, len(paths))
for _, p := range paths {
ret = append(ret, p.String())
}
return ret
}