mirror of
https://github.com/anchore/syft.git
synced 2026-02-12 10:36:45 +01:00
unapply base path for resolver inbound requests (#4478)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
parent
e0b61a3ae3
commit
beb70891e5
@ -14,10 +14,11 @@ import (
|
|||||||
// the user given root, the base path (if any) to consider as the root, and the current working directory.
|
// the user given root, the base path (if any) to consider as the root, and the current working directory.
|
||||||
// Note: this only works on a real filesystem, not on a virtual filesystem (such as a stereoscope filetree).
|
// Note: this only works on a real filesystem, not on a virtual filesystem (such as a stereoscope filetree).
|
||||||
type ChrootContext struct {
|
type ChrootContext struct {
|
||||||
root string
|
root string
|
||||||
base string
|
rootRelativeToBase string
|
||||||
cwd string
|
base string
|
||||||
cwdRelativeToRoot string
|
cwd string
|
||||||
|
cwdRelativeToRoot string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewChrootContextFromCWD(root, base string) (*ChrootContext, error) {
|
func NewChrootContextFromCWD(root, base string) (*ChrootContext, error) {
|
||||||
@ -40,10 +41,26 @@ func NewChrootContext(root, base, cwd string) (*ChrootContext, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we need to track the relative path from root to base (if set) so that request paths can un-apply the base path
|
||||||
|
// changes from any incoming requests.
|
||||||
|
var rootRelativeToBase string
|
||||||
|
if cleanBase != cleanRoot && cleanBase != "" {
|
||||||
|
absRoot := cleanRoot
|
||||||
|
if !filepath.IsAbs(cleanRoot) {
|
||||||
|
absRoot = filepath.Join(cwd, cleanRoot)
|
||||||
|
}
|
||||||
|
|
||||||
|
rootRelativeToBase, err = filepath.Rel(absRoot, cleanBase) // validate that base is within root
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("base path %q is not within root path %q: %w", cleanBase, cleanRoot, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
chroot := &ChrootContext{
|
chroot := &ChrootContext{
|
||||||
root: cleanRoot,
|
root: cleanRoot,
|
||||||
base: cleanBase,
|
rootRelativeToBase: rootRelativeToBase,
|
||||||
cwd: cwd,
|
base: cleanBase,
|
||||||
|
cwd: cwd,
|
||||||
}
|
}
|
||||||
|
|
||||||
return chroot, chroot.ChangeDirectory(cwd)
|
return chroot, chroot.ChangeDirectory(cwd)
|
||||||
@ -125,8 +142,8 @@ func (r ChrootContext) ToNativePath(chrootPath string) (string, error) {
|
|||||||
responsePath := chrootPath
|
responsePath := chrootPath
|
||||||
|
|
||||||
if filepath.IsAbs(responsePath) {
|
if filepath.IsAbs(responsePath) {
|
||||||
// don't allow input to potentially hop above root path
|
// don't allow input to potentially hop above root path (and still un-apply any base paths)
|
||||||
responsePath = path.Join(r.root, responsePath)
|
responsePath = path.Join(r.root, r.rootRelativeToBase, responsePath)
|
||||||
} else {
|
} else {
|
||||||
// ensure we take into account any relative difference between the root path and the CWD for relative requests
|
// ensure we take into account any relative difference between the root path and the CWD for relative requests
|
||||||
responsePath = path.Join(r.cwdRelativeToRoot, responsePath)
|
responsePath = path.Join(r.cwdRelativeToRoot, responsePath)
|
||||||
|
|||||||
@ -452,6 +452,25 @@ func Test_ChrootContext_RequestResponse(t *testing.T) {
|
|||||||
expectedNativePath: absRelOutsidePath,
|
expectedNativePath: absRelOutsidePath,
|
||||||
expectedChrootPath: "to/the/rel-outside.txt",
|
expectedChrootPath: "to/the/rel-outside.txt",
|
||||||
},
|
},
|
||||||
|
// base path within root cases...
|
||||||
|
// note: for absolute input paths, rootRelativeToBase is used to resolve the native path
|
||||||
|
// note: for relative input paths, cwdRelativeToRoot is used (base does not affect relative path resolution)
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, with base",
|
||||||
|
root: relative,
|
||||||
|
base: filepath.Join(relative, "path", "to"),
|
||||||
|
input: "/the/file.txt",
|
||||||
|
expectedNativePath: absPathToTheFile,
|
||||||
|
expectedChrootPath: "/the/file.txt", // ToChrootPath trims base prefix without adding separator
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, with base",
|
||||||
|
root: absolute,
|
||||||
|
base: filepath.Join(absolute, "path", "to"),
|
||||||
|
input: "/the/file.txt",
|
||||||
|
expectedNativePath: absPathToTheFile,
|
||||||
|
expectedChrootPath: "/the/file.txt", // ToChrootPath trims base prefix without adding separator
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(c.name, func(t *testing.T) {
|
||||||
@ -480,6 +499,69 @@ func Test_ChrootContext_RequestResponse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewChrootContext_BaseValidation(t *testing.T) {
|
||||||
|
testDir, err := os.Getwd()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
relative := filepath.Join("test-fixtures", "req-resp")
|
||||||
|
absolute := filepath.Join(testDir, relative)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
root string
|
||||||
|
base string
|
||||||
|
cwd string
|
||||||
|
expectedRootRelativeToBase string
|
||||||
|
wantErr require.ErrorAssertionFunc
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "base within root",
|
||||||
|
root: absolute,
|
||||||
|
base: filepath.Join(absolute, "path", "to"),
|
||||||
|
cwd: testDir,
|
||||||
|
expectedRootRelativeToBase: filepath.Join("path", "to"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "base equals root",
|
||||||
|
root: absolute,
|
||||||
|
base: absolute,
|
||||||
|
cwd: testDir,
|
||||||
|
expectedRootRelativeToBase: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty base",
|
||||||
|
root: absolute,
|
||||||
|
base: "",
|
||||||
|
cwd: testDir,
|
||||||
|
expectedRootRelativeToBase: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root with base",
|
||||||
|
root: relative,
|
||||||
|
base: filepath.Join(absolute, "path", "to"),
|
||||||
|
cwd: testDir,
|
||||||
|
expectedRootRelativeToBase: filepath.Join("path", "to"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if tt.wantErr == nil {
|
||||||
|
tt.wantErr = require.NoError
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, err := NewChrootContext(tt.root, tt.base, tt.cwd)
|
||||||
|
tt.wantErr(t, err)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, tt.expectedRootRelativeToBase, ctx.rootRelativeToBase)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestToNativeGlob(t *testing.T) {
|
func TestToNativeGlob(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user