alibaba/spring-ai-alibaba · warning · IllegalArgumentException

resolved path escapes root directory

Error message

resolved path escapes root directory

What it means

FileSystemStore.createItemPath resolves namespace+key into a path under the store root and rejects the result if it does not start with the normalized absolute root path. This IllegalArgumentException guards against path traversal, e.g. a key containing '..' or an absolute path component that survives normalization.

Source

Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/store/stores/FileSystemStore.java:264

		}
	}

	/**
	 * Create item path from namespace and key.
	 * @param namespace namespace
	 * @param key key
	 * @return item path
	 */
	private Path createItemPath(List<String> namespace, String key) {
		Path path = rootPath.toAbsolutePath().normalize();
		for (String ns : namespace) {
			validatePathSegment(ns, "namespace");
			path = path.resolve(ns);
		}
		validatePathSegment(key, "key");
		Path itemPath = path.resolve(key + ".json").normalize();
		if (!itemPath.startsWith(rootPath.toAbsolutePath().normalize())) {
			throw new IllegalArgumentException("resolved path escapes root directory");
		}
		return itemPath;
	}

	private void validatePathSegment(String segment, String fieldName) {
		if (segment == null || segment.trim().isEmpty()) {
			throw new IllegalArgumentException(fieldName + " cannot be null or empty");
		}
		Path candidate = Paths.get(segment);
		if (candidate.isAbsolute() || candidate.getNameCount() != 1 || "..".equals(segment) || ".".equals(segment)) {
			throw new IllegalArgumentException(fieldName + " contains unsafe path segment: " + segment);
		}
	}

	/**
	 * Ensure directory exists.
	 * @param directory directory to create
	 */

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Sanitize namespace/key to [A-Za-z0-9._-] before calling store APIs
  2. Reject keys containing path separators or '..' in your own validation layer
  3. Catch IllegalArgumentException and return a 400-style error to the caller
  4. Use fixed identifiers (UUIDs) instead of raw user strings as keys

Example fix

// before
store.putItem(List.of(userInputNs), userInputKey, value);
// after
if (!userInputKey.matches("[A-Za-z0-9._-]+")) {
    throw new IllegalArgumentException("invalid key");
}
store.putItem(List.of(userInputNs), userInputKey, value);
Defensive patterns

Strategy: validation

Validate before calling

static boolean safeSegment(String s) {
    return s != null && s.matches("[A-Za-z0-9][A-Za-z0-9._-]*") && !s.equals("..") && !s.equals(".");
}
// call for every namespace element and the key before store APIs

Try / catch

try {
    store.getItem(namespace, key);
} catch (IllegalArgumentException e) {
    throw new BadRequestException("invalid store key");
}

Prevention

When it happens

Trigger: Calling putItem/getItem/deleteItem/search with a namespace or key that normalizes outside the root (e.g. key '../escape', namespace containing '.' or '..' segments that slip past validatePathSegment on unusual platforms).

Common situations: Passing untrusted user input as namespace/key; keys built by string concatenation from request parameters; upstream validation removed leading '../' but not interior ones.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/979088fee0f40149. Report an issue: GitHub.