You've already forked agentic-coding-workflow
fix(storage): reject empty key + nil ReadCloser on Get error
This commit is contained in:
@@ -28,8 +28,13 @@ func NewLocalFS(base string) (*LocalFS, error) {
|
||||
return &LocalFS{base: filepath.Clean(base)}, nil
|
||||
}
|
||||
|
||||
// resolveSafe 把 key 限制在 base 之下,拒绝 ".." / 绝对路径。
|
||||
// resolveSafe 把 key 限制在 base 之下,拒绝 ".." / 绝对路径 / 空 key。
|
||||
func (l *LocalFS) resolveSafe(key string) (string, error) {
|
||||
// Reject empty / dot keys (would resolve to base itself and corrupt the layout)
|
||||
if key == "" || key == "." {
|
||||
return "", errors.New("storage: key must not be empty")
|
||||
}
|
||||
|
||||
// Reject absolute paths
|
||||
if filepath.IsAbs(key) {
|
||||
return "", errors.New("storage: key must be relative")
|
||||
@@ -96,7 +101,11 @@ func (l *LocalFS) Get(ctx context.Context, storagePath string) (io.ReadCloser, e
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return os.Open(full)
|
||||
f, err := os.Open(full)
|
||||
if err != nil {
|
||||
return nil, err // 显式 nil interface,避免 typed-nil 包装
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (l *LocalFS) Delete(ctx context.Context, storagePath string) error {
|
||||
|
||||
@@ -52,3 +52,22 @@ func TestLocalFS_DeleteNonexistentIsNoop(t *testing.T) {
|
||||
fs, _ := NewLocalFS(t.TempDir())
|
||||
require.NoError(t, fs.Delete(context.Background(), "nope/nope.txt"))
|
||||
}
|
||||
|
||||
func TestLocalFS_RejectEmptyKey(t *testing.T) {
|
||||
fs, _ := NewLocalFS(t.TempDir())
|
||||
_, err := fs.Put(context.Background(), "", bytes.NewReader(nil), "text/plain")
|
||||
require.Error(t, err)
|
||||
_, err = fs.Put(context.Background(), ".", bytes.NewReader(nil), "text/plain")
|
||||
require.Error(t, err)
|
||||
_, err = fs.Get(context.Background(), "")
|
||||
require.Error(t, err)
|
||||
require.Error(t, fs.Delete(context.Background(), ""))
|
||||
}
|
||||
|
||||
func TestLocalFS_GetMissingFileReturnsNilCloser(t *testing.T) {
|
||||
// 验证错误路径下不会返回 typed-nil io.ReadCloser
|
||||
fs, _ := NewLocalFS(t.TempDir())
|
||||
r, err := fs.Get(context.Background(), "missing/file.txt")
|
||||
require.Error(t, err)
|
||||
require.Nil(t, r)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user