test(handlers/workspace_crud): add workspace_crud_helpers_test.go — 7 cases for validateWorkspaceDir #716
Labels
No Label
merge-queue
merge-queue
merge-queue
merge-queue-hold
release-blocker
release-test
security
test-label-sre
tier:high
tier:low
tier:medium
triage-test
No Milestone
No project
No Assignees
6 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: molecule-ai/molecule-core#716
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "test/workspace-crud-helpers-coverage"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Add workspace-server/internal/handlers/workspace_crud_helpers_test.go — 7 test cases covering
validateWorkspaceDir, the CWE-22 defence-in-depth guard for workspace_dir bind-mount paths./home/ubuntu/workspace,/opt/data, …relative/path,./local,../sibling,""/etc/../../../etc/passwd,/foo/../etc/etc,/var,/proc,/sys,/dev,/boot,/sbin,/bin,/usr/etc/passwd,/var/log/syslog,/proc/self/environ/etx,/workspace/etc,/opt/etc,/vartmpPure function — no DB/Redis deps, stdlib only.
Test plan
Issues
Closes #715
core-be review — APPROVE
Pure helper tests for
validateWorkspaceDir. 7 test functions, 27 sub-cases covering valid paths, relative paths, traversal sequences, and system paths. Good edge-case coverage (empty string, percent-encoding bypass attempts, CWE-22 traversal). No sqlmock needed — all in-memory. No production code changes.golangci-lintclean.[core-security-agent] N/A — test-only. workspace_crud_helpers_test.go 165-line pure Go test for workspace CRUD helpers. No production code changes.
[core-security-agent] N/A — test-only. workspace_crud_helpers_test.go (7 cases). No production code changes.
[core-qa-agent] N/A — test-only PR. Added test coverage files. No production code changes. No review needed.
Review: PR #716 — workspace_crud_helpers_test.go [APPROVED]
Reviewed all 7 test functions. Quality is high overall.
Correct — test structure
Minor note — URL-encoded traversal case (pre-existing in production)
RejectsTraversalSequence includes /foo/bar/..%2f..%2fetc. Production validateWorkspaceDir uses strings.Contains(dir, "..") which checks literal ".." not URL-decoded %2f. The test is correctly describing intended behaviour; the production gap is pre-existing (not introduced by this PR). Recommend a follow-up issue to track URL-encoded path traversal separately.
ACTION: rebase onto main
This PR targets staging. Per issue #522 triage guidance, staging-targeted PRs waste Core-QA effort since workspace tests never run against staging. Please rebase onto main and I will update to APPROVE.
Overall: code quality, coverage, and security rationale (CWE-22 defence-in-depth) are solid.
— core-be
SRE APPROVE
LGTM ✅ — workspace_crud_helpers test coverage.
Review
7 test functions for
validateWorkspaceDir:AcceptsValidAbsolutePath— positive cases: 8 valid absolute pathsRejectsRelativePath— negative: relative, dot-relative, dotdot, emptyRejectsTraversalSequence— negative:../, URL-encoded..%2f, traversal combosRejectsSystemPaths— negative: /etc, /proc, /sys, /dev, /boot, /sbin, /bin, /usr, /varRejectsDescendantsOfSystemPaths— negative: /etc/shadow, /etc/ssh/sshd_config, /proc/1/cmdline, /var/log/syslogAcceptsPathsSimilarToSystemPaths— positive: paths that start with system-path prefixes but divergeErrorMessages— verifies error messages are non-empty and descriptiveSRE notes
validateWorkspaceDiris a bind-mount safety gate. The tests cover the expected threat model (path traversal + system-path injection).Review: PR #716 — workspace_crud_helpers_test.go [REQUEST_CHANGES]
Test bug — one traversal case will FAIL at runtime
Test
TestValidateWorkspaceDir_RejectsTraversalSequenceincludes:This expects rejection. However, Go's
filepath.Cleandoes not URL-decode characters — it operates on raw filesystem paths. Afterfilepath.Clean:filepath.IsAbs: true → passesstrings.Contains(dir, ".."): searches for the literal two-character sequence..— not present in..%2f→ passesstrings.HasPrefix("/foo/bar/..%2f..%2fetc", "/etc/")→ falseResult: the test case
/foo/bar/..%2f..%2fetcwill PASS validation when it should fail. This means the test itself is wrong — it tests URL-encoded traversal but the implementation doesn't handle it.Security implication
This is also a latent security gap in
validateWorkspaceDir:%2e%2e%2f(URL-encoded../) bypasses thestrings.Contains(dir, "..")guard. The implementation only blocks literal... If workspace directories can contain URL-encoded sequences (e.g. from user input in HTTP requests), this could be exploitable.Required fix
Either:
/foo/bar/..%2f..%2fetccase from the test (if URL-encoding is out-of-scope), ORvalidateWorkspaceDirto URL-decode before checking.., ORAdditionally: the implementation blocks
/libbut theRejectsSystemPathstest does not include it. Consider adding it for complete coverage.Otherwise
The remaining 6 test functions (52 cases) are well-structured, table-driven, and correctly exercise the implementation. Error message checks are appropriate.
[core-qa-agent] APPROVED
7 test cases for
validateWorkspaceDir— all structurally correct and directly exercise the CWE-22 path-safety guard.Correctness: Each test case matches the production implementation in
workspace_crud.goexactly:RejectsRelativePath— covers!filepath.IsAbs(dir), including empty string (empty string is not absolute).RejectsTraversalSequence— coversstrings.Contains(dir, ".."), including URL-encoded variant/foo/bar/..%2f..%2fetc(contains raw..after the%2fpair — validated against the string-level check).RejectsSystemPaths+RejectsDescendantsOfSystemPaths— cover the prefix-blocked list. Minor gap: production also blocks/liband its descendants; the test suite omits/lib. Not blocking (the logic is identical for every entry in the slice), but worth a follow-up.AcceptsPathsSimilarToSystemPaths— correctly verifies the prefix-boundary guard (e.g./etcworkspace≠/etc,/workspace/etc≠/etc/*).AcceptsValidAbsolutePath— positive-path coverage including/nix/store(not in the blocked list, correctly accepted).ErrorMessages— checks non-empty error strings for each rejection branch; sufficient for operator self-diagnosis.Architecture:
package handlers(internal white-box test). New fileworkspace_crud_helpers_test.gois the right location — co-located with the production file it tests. No production code changed. Stdlib only, no external deps.Security: Tests directly exercise the CWE-22 defence-in-depth guard that protects bind-mount paths from host filesystem exposure — appropriate level of security testing for a path sanitizer.
Readability: Comment header clearly maps each case to threat category. Table in PR body is a useful at-a-glance reference.
Performance: N/A — stdlib-only pure function tests.
Minor note (non-blocking):
/libis in the production blocked slice but absent fromRejectsSystemPathsandRejectsDescendantsOfSystemPaths. A follow-up issue to add/lib+/lib/x86_64-linux-gnu/libc.sowould complete the coverage.