test(#150): add positive test for in-repo symlink allowed by EvalSymlinks fix
PR Ready Gate / clear-labels (pull_request) Successful in 1s
CI / test (pull_request) Successful in 18s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 26s
CI / review (gpt-5, security, ., rodin/security-patterns, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 1m16s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 1m22s
PR Ready Gate / clear-labels (pull_request) Successful in 1s
CI / test (pull_request) Successful in 18s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 26s
CI / review (gpt-5, security, ., rodin/security-patterns, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 1m16s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 1m22s
Finding 5 [NIT] from self-review:
TestValidateDocmapPath_InRepoSymlinkAllowed verifies that a file-level
symlink inside the repo root whose resolved target is also within the
root is accepted by validateDocmapPath. This is the positive case for
the issue #150 behavioral change (commit 4dce8e4): only symlinks whose
resolved destination escapes the root are rejected. Intra-repo symlinks
are permitted and their resolved path is returned to the caller.
The test also asserts that the returned path is the resolved real file,
not the symlink entry itself (i.e., EvalSymlinks did its job).
This commit is contained in:
@@ -61,7 +61,7 @@ func validateDocmapPath(localPath, resolvedRoot string) (string, error) {
|
||||
// nodes, etc.) — ParseDocMapConfig expects a plain YAML file and would
|
||||
// produce a confusing error on non-regular entries.
|
||||
if !fi.Mode().IsRegular() {
|
||||
return fmt.Errorf("docmap must be a regular file")
|
||||
return "", fmt.Errorf("docmap must be a regular file")
|
||||
}
|
||||
|
||||
// Confine to resolvedRoot: use the fully-resolved path so that a directory
|
||||
|
||||
@@ -649,3 +649,45 @@ mappings:
|
||||
t.Errorf("expected exit 0 for './' prefixed covered file, got %d; stderr: %q", code, stderr)
|
||||
}
|
||||
}
|
||||
|
||||
// TestValidateDocmapPath_InRepoSymlinkAllowed verifies that an in-repo
|
||||
// file-level symlink whose resolved target is still within the repo root is
|
||||
// accepted. This is the positive case for the issue #150 behavioral change:
|
||||
// only symlinks that escape the root are rejected; intra-repo symlinks are
|
||||
// allowed because EvalSymlinks resolves the target and the confinement check
|
||||
// is applied to the resolved path, not the symlink entry itself.
|
||||
func TestValidateDocmapPath_InRepoSymlinkAllowed(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
|
||||
// Create the real docmap file inside the repo root.
|
||||
if err := os.MkdirAll(filepath.Join(dir, ".review-bot"), 0o755); err != nil {
|
||||
t.Fatalf("MkdirAll: %v", err)
|
||||
}
|
||||
realDocmap := filepath.Join(dir, ".review-bot", "doc-map-real.yml")
|
||||
if err := os.WriteFile(realDocmap, []byte("mappings: []\n"), 0o644); err != nil {
|
||||
t.Fatalf("WriteFile: %v", err)
|
||||
}
|
||||
|
||||
// Create a symlink inside the repo root that points to the real file
|
||||
// (also inside the root).
|
||||
symlinkPath := filepath.Join(dir, ".review-bot", "doc-map-link.yml")
|
||||
if err := os.Symlink(realDocmap, symlinkPath); err != nil {
|
||||
t.Skipf("cannot create symlink (platform may not support it): %v", err)
|
||||
}
|
||||
|
||||
// Resolve dir to a symlink-free root, as runValidateDocmap does.
|
||||
resolvedRoot, err := filepath.EvalSymlinks(dir)
|
||||
if err != nil {
|
||||
t.Fatalf("EvalSymlinks(dir): %v", err)
|
||||
}
|
||||
|
||||
// In-repo symlink whose target is within root: must be accepted.
|
||||
resolved, err := validateDocmapPath(symlinkPath, resolvedRoot)
|
||||
if err != nil {
|
||||
t.Fatalf("expected in-repo symlink to be accepted, got error: %v", err)
|
||||
}
|
||||
// The returned resolved path must be the real file (not the symlink entry).
|
||||
if resolved == symlinkPath {
|
||||
t.Errorf("expected resolved path to differ from symlink path")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user