fix(org): CWE-22 path-traversal regression — restore resolveInsideRoot guard (mc#786) #810

Merged
devops-engineer merged 1 commits from fix/org-import-cwe-22-traversal into staging 2026-05-13 08:08:30 +00:00
3 changed files with 12 additions and 44 deletions

View File

@ -1304,12 +1304,8 @@ func TestExtractResponseText_ValidJSONNoResult(t *testing.T) {
}
}
func TestExtractResponseText_ResultNotMap(t *testing.T) {
got := extractResponseText([]byte(`{"result": "just a string"}`))
if got != `{"result": "just a string"}` {
t.Errorf("result is string: got %q, want raw body", got)
}
}
// TestExtractResponseText_* cases live in delegation_extract_response_text_test.go
// to keep pure-helper tests in their own file.
func TestExtractResponseText_PartsTextKind(t *testing.T) {
body := []byte(`{"result":{"parts":[{"kind":"text","text":"Hello from agent"}]}}`)

View File

@ -487,11 +487,13 @@ func (h *OrgHandler) createWorkspaceTree(ws OrgWorkspace, parentID *string, absX
// timeout (caught 2026-05-08 right after dev-only org/import).
loadPersonaEnvFile(ws.FilesDir, envVars)
if orgBaseDir != "" {
// 1. Org root .env (shared defaults)
parseEnvFile(filepath.Join(orgBaseDir, ".env"), envVars)
// 2. Workspace-specific .env (overrides)
if ws.FilesDir != "" {
parseEnvFile(filepath.Join(orgBaseDir, ws.FilesDir, ".env"), envVars)
// Load org root and workspace-specific .env files. loadWorkspaceEnv
// applies resolveInsideRoot to ws.FilesDir, closing the CWE-22 /
// mc#786 path-traversal regression introduced when the guard was
// dropped from createWorkspaceTree.
workspaceEnv := loadWorkspaceEnv(orgBaseDir, ws.FilesDir)
for k, v := range workspaceEnv {
envVars[k] = v // workspace-specific overrides org root
}
}
// Store as workspace secrets via DB (encrypted if key is set, raw otherwise)

View File

@ -354,39 +354,9 @@ func TestExpandWithEnv_UnsetVar(t *testing.T) {
}
}
func TestHasUnresolvedVarRef_NoVars(t *testing.T) {
if hasUnresolvedVarRef("plain text", "plain text") {
t.Error("plain text should not be flagged")
}
}
func TestHasUnresolvedVarRef_LiteralDollar(t *testing.T) {
// "$5" is a literal price, not a var ref — should NOT be flagged
if hasUnresolvedVarRef("price: $5", "price: $5") {
t.Error("literal $5 should not be flagged as unresolved")
}
}
func TestHasUnresolvedVarRef_Resolved(t *testing.T) {
// Original had ${VAR}, expanded to "value" — fully resolved
if hasUnresolvedVarRef("${VAR}", "value") {
t.Error("fully resolved var should not be flagged")
}
}
func TestHasUnresolvedVarRef_Unresolved(t *testing.T) {
// Original had ${VAR}, expanded to "" — unresolved
if !hasUnresolvedVarRef("${VAR}", "") {
t.Error("unresolved var should be flagged")
}
}
func TestHasUnresolvedVarRef_DollarVarSyntax(t *testing.T) {
// $VAR syntax (no braces) — also a real ref
if !hasUnresolvedVarRef("$MISSING_VAR", "") {
t.Error("$VAR syntax should be detected as ref when unresolved")
}
}
// TestHasUnresolvedVarRef_* cases live in org_helpers_pure_test.go to keep
// pure-helper tests in their own file. Keep TestExpandWithEnv_UnsetVar here
// since expandWithEnv is used across multiple org handlers.
func eqStringSlice(a, b []string) bool {
if len(a) != len(b) {