From 45bd96387ac25fd2c00d6067e007abcdf800df04 Mon Sep 17 00:00:00 2001 From: Virgil Date: Tue, 31 Mar 2026 13:47:35 +0000 Subject: [PATCH] refactor(workspace): harden path boundaries and naming Co-Authored-By: Virgil --- docs/RFC.md | 2 +- workspace/service.go | 14 +++++++++----- workspace/service_test.go | 10 ++++++++++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/docs/RFC.md b/docs/RFC.md index 9041f79..74cac69 100644 --- a/docs/RFC.md +++ b/docs/RFC.md @@ -2077,7 +2077,7 @@ service, _ := workspace.New(workspace.Options{KeyPairProvider: stubKeyPairProvid _ = service ``` -**CreateWorkspace(identifier, password string) (string, error)** +**CreateWorkspace(identifier, passphrase string) (string, error)** Example: ```go service, _ := workspace.New(workspace.Options{KeyPairProvider: stubKeyPairProvider{}}) diff --git a/workspace/service.go b/workspace/service.go index b1ede43..feefae8 100644 --- a/workspace/service.go +++ b/workspace/service.go @@ -17,7 +17,7 @@ import ( // Example: Medium: io.NewMemoryMedium(), // Example: }) type Workspace interface { - CreateWorkspace(identifier, password string) (string, error) + CreateWorkspace(identifier, passphrase string) (string, error) SwitchWorkspace(workspaceID string) error ReadWorkspaceFile(workspaceFilePath string) (string, error) WriteWorkspaceFile(workspaceFilePath, content string) error @@ -109,7 +109,7 @@ func New(options Options) (*Service, error) { } // Example: workspaceID, _ := service.CreateWorkspace("alice", "pass123") -func (service *Service) CreateWorkspace(identifier, password string) (string, error) { +func (service *Service) CreateWorkspace(identifier, passphrase string) (string, error) { service.stateLock.Lock() defer service.stateLock.Unlock() @@ -134,7 +134,7 @@ func (service *Service) CreateWorkspace(identifier, password string) (string, er } } - privateKey, err := service.keyPairProvider.CreateKeyPair(identifier, password) + privateKey, err := service.keyPairProvider.CreateKeyPair(identifier, passphrase) if err != nil { return "", core.E("workspace.CreateWorkspace", "failed to generate keys", err) } @@ -206,7 +206,8 @@ func (service *Service) WriteWorkspaceFile(workspaceFilePath, content string) er func (service *Service) HandleWorkspaceCommand(command WorkspaceCommand) core.Result { switch command.Action { case WorkspaceCreateAction: - workspaceID, err := service.CreateWorkspace(command.Identifier, command.Password) + passphrase := command.Password + workspaceID, err := service.CreateWorkspace(command.Identifier, passphrase) if err != nil { return core.Result{}.New(err) } @@ -221,7 +222,7 @@ func (service *Service) HandleWorkspaceCommand(command WorkspaceCommand) core.Re } // Example: result := service.HandleWorkspaceMessage(core.New(), WorkspaceCommand{Action: WorkspaceSwitchAction, WorkspaceID: "f3f0d7"}) -func (service *Service) HandleWorkspaceMessage(coreRuntime *core.Core, message core.Message) core.Result { +func (service *Service) HandleWorkspaceMessage(_ *core.Core, message core.Message) core.Result { switch command := message.(type) { case WorkspaceCommand: return service.HandleWorkspaceCommand(command) @@ -242,6 +243,9 @@ func resolveWorkspaceHomeDirectory() string { func joinPathWithinRoot(root string, parts ...string) (string, error) { candidate := core.Path(append([]string{root}, parts...)...) sep := core.Env("DS") + if sep == "" { + sep = "/" + } if candidate == root || core.HasPrefix(candidate, root+sep) { return candidate, nil } diff --git a/workspace/service_test.go b/workspace/service_test.go index e28dece..081d2a4 100644 --- a/workspace/service_test.go +++ b/workspace/service_test.go @@ -1,6 +1,7 @@ package workspace import ( + "io/fs" "testing" core "dappco.re/go/core" @@ -117,6 +118,15 @@ func TestService_WriteWorkspaceFile_TraversalBlocked_Bad(t *testing.T) { require.Error(t, err) } +func TestService_JoinPathWithinRoot_DefaultSeparator_Good(t *testing.T) { + t.Setenv("DS", "") + + path, err := joinPathWithinRoot("/tmp/workspaces", "../workspaces2") + require.Error(t, err) + assert.ErrorIs(t, err, fs.ErrPermission) + assert.Empty(t, path) +} + func TestService_HandleWorkspaceMessage_Command_Good(t *testing.T) { service, _ := newTestService(t)