Split from #934 (finding 7).
exporter.py:51 and :92 call os.makedirs() on the output directory without resolving symlinks first. If a symlink is pre-created at the intended output path, exported markdown lands wherever the symlink points.
The miner already rejects symlinked inputs (miner.py, convo_miner.py). The exporter should apply the same caution to outputs — defense-in-depth, not an actively exploited path.
Proposed fix: output_dir = os.path.realpath(output_dir) before makedirs, verify the resolved path stays within the intended root.
PR: #937.
Split from #934 (finding 7).
exporter.py:51and:92callos.makedirs()on the output directory without resolving symlinks first. If a symlink is pre-created at the intended output path, exported markdown lands wherever the symlink points.The miner already rejects symlinked inputs (
miner.py,convo_miner.py). The exporter should apply the same caution to outputs — defense-in-depth, not an actively exploited path.Proposed fix:
output_dir = os.path.realpath(output_dir)beforemakedirs, verify the resolved path stays within the intended root.PR: #937.