Skip to content

Commit ce1bf68

Browse files
committed
Add tests for symlinks in and outside output directory
1 parent 2cbb1fb commit ce1bf68

1 file changed

Lines changed: 37 additions & 0 deletions

File tree

‎tests/snekio/test_memfs.py‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import logging
2+
import os
23
from concurrent.futures import ThreadPoolExecutor
34
from contextlib import ExitStack
5+
from pathlib import Path
6+
from tempfile import NamedTemporaryFile
47
from unittest import TestCase, mock
58
from uuid import uuid4
69

@@ -63,3 +66,37 @@ def test_implicit_cleanup(self):
6366
with self.assertWarns(ResourceWarning):
6467
del memfs
6568
self.assertFalse(path.exists())
69+
70+
def test_symlink_to_file_outside_output_is_not_collected(self):
71+
"""A symlink pointing at a file outside output must not be read."""
72+
with NamedTemporaryFile(mode="w", suffix=".secret", delete=False) as f:
73+
f.write("host-secret-content")
74+
secret_path = Path(f.name)
75+
76+
try:
77+
with MemFS(1024) as memfs:
78+
os.symlink(secret_path, memfs.output / "leak.txt")
79+
80+
results = memfs.files_list(limit=10, pattern="**/*")
81+
leaked = [r for r in results if r.content == b"host-secret-content"]
82+
83+
self.assertEqual(
84+
leaked,
85+
[],
86+
"Symlink to a file outside the output dir was followed "
87+
"and its content was exfiltrated",
88+
)
89+
finally:
90+
secret_path.unlink(missing_ok=True)
91+
92+
def test_symlink_within_output_dir_still_collected(self):
93+
"""Symlinks pointing to files within the output dir should still be collected."""
94+
with MemFS(1024) as memfs:
95+
real = memfs.output / "real.txt"
96+
real.write_text("normal-output-content")
97+
os.symlink(real, memfs.output / "link.txt")
98+
99+
results = {r.path: r.content for r in memfs.files_list(limit=10, pattern="**/*")}
100+
101+
self.assertIn("link.txt", results)
102+
self.assertEqual(results["link.txt"], b"normal-output-content")

0 commit comments

Comments
 (0)