Skip to content

Commit

Permalink
loader: Avoid reading UNC paths by default
Browse files Browse the repository at this point in the history
Signed-off-by: Ashutosh Narkar <anarkar4387@gmail.com>
  • Loading branch information
ashutosh-narkar committed Aug 15, 2024
1 parent 83f8dc6 commit 0039f28
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 0 deletions.
36 changes: 36 additions & 0 deletions loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (
"github.com/open-policy-agent/opa/util"
)

const readUNCPathEnv = "READ_UNC_PATH"

// Result represents the result of successfully loading zero or more files.
type Result struct {
Documents map[string]interface{}
Expand Down Expand Up @@ -247,13 +249,18 @@ func (fl fileLoader) AsBundle(path string) (*bundle.Bundle, error) {
return nil, err
}

if err := checkForUNCPath(path); err != nil {
return nil, err
}

var bundleLoader bundle.DirectoryLoader
var isDir bool
if fl.reader != nil {
bundleLoader = bundle.NewTarballLoaderWithBaseURL(fl.reader, path).WithFilter(fl.filter)
} else {
bundleLoader, isDir, err = GetBundleDirectoryLoaderFS(fl.fsys, path, fl.filter)
}

if err != nil {
return nil, err
}
Expand Down Expand Up @@ -303,6 +310,10 @@ func GetBundleDirectoryLoaderFS(fsys fs.FS, path string, filter Filter) (bundle.
return nil, false, err
}

if err := checkForUNCPath(path); err != nil {
return nil, false, err
}

var fi fs.FileInfo
if fsys != nil {
fi, err = fs.Stat(fsys, path)
Expand Down Expand Up @@ -663,12 +674,18 @@ func allRec(fsys fs.FS, path string, filter Filter, errors *Errors, loaded *Resu
return
}

if err := checkForUNCPath(path); err != nil {
errors.add(err)
return
}

var info fs.FileInfo
if fsys != nil {
info, err = fs.Stat(fsys, path)
} else {
info, err = os.Stat(path)
}

if err != nil {
errors.add(err)
return
Expand Down Expand Up @@ -804,3 +821,22 @@ func makeDir(path []string, x interface{}) (map[string]interface{}, bool) {
}
return makeDir(path[:len(path)-1], map[string]interface{}{path[len(path)-1]: x})
}

// isUNC reports whether path is a UNC path.
func isUNC(path string) bool {
return len(path) > 1 && isSlash(path[0]) && isSlash(path[1])
}

func isSlash(c uint8) bool {
return c == '\\' || c == '/'
}

func checkForUNCPath(path string) error {
if isUNC(path) {
readUNCPath := os.Getenv(readUNCPathEnv)
if readUNCPath == "" || readUNCPath == "false" {
return fmt.Errorf("reading UNC paths is not allowed (hint: set READ_UNC_PATH env var)")
}
}
return nil
}
93 changes: 93 additions & 0 deletions loader/loader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"bytes"
"embed"
"encoding/json"
"fmt"
"io"
"io/fs"
"os"
Expand Down Expand Up @@ -574,6 +575,98 @@ func TestAsBundleWithFile(t *testing.T) {
})
}

func TestCheckForUNCPath(t *testing.T) {
cases := []struct {
input string
readUNCPath string
wantErr bool
err error
}{
{
input: "c:/foo",
wantErr: false,
},
{
input: "file:///c:/a/b",
wantErr: false,
},
{
input: `\\localhost\c$`,
wantErr: true,
err: fmt.Errorf("reading UNC paths is not allowed (hint: set READ_UNC_PATH env var)"),
},
{
input: `\\localhost\c$`,
wantErr: true,
readUNCPath: "false",
err: fmt.Errorf("reading UNC paths is not allowed (hint: set READ_UNC_PATH env var)"),
},
{
input: `\\localhost\c$`,
readUNCPath: "true",
wantErr: false,
},
{
input: `\\\\localhost\c$`,
wantErr: true,
err: fmt.Errorf("reading UNC paths is not allowed (hint: set READ_UNC_PATH env var)"),
},
{
input: `\\\\localhost\c$`,
wantErr: true,
readUNCPath: "false",
err: fmt.Errorf("reading UNC paths is not allowed (hint: set READ_UNC_PATH env var)"),
},
{
input: `\\\\localhost\c$`,
readUNCPath: "true",
wantErr: false,
},
{
input: `//localhost/foo`,
wantErr: true,
readUNCPath: "false",
err: fmt.Errorf("reading UNC paths is not allowed (hint: set READ_UNC_PATH env var)"),
},
{
input: `//localhost/foo`,
wantErr: false,
readUNCPath: "true",
},
{
input: `file:///a/b/c`,
wantErr: false,
readUNCPath: "true",
err: nil,
},
}

for _, tc := range cases {
t.Run(tc.input, func(t *testing.T) {
os.Unsetenv(readUNCPathEnv)

if tc.readUNCPath != "" {
os.Setenv(readUNCPathEnv, tc.readUNCPath)
}

err := checkForUNCPath(tc.input)
if tc.wantErr {
if err == nil {
t.Fatal("Expected error but got nil")
}

if tc.err != nil && tc.err.Error() != err.Error() {
t.Fatalf("Expected error message %v but got %v", tc.err.Error(), err.Error())
}
} else {
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
}
})
}
}

func TestLoadRooted(t *testing.T) {
files := map[string]string{
"/foo.json": "[1,2,3]",
Expand Down

0 comments on commit 0039f28

Please sign in to comment.