HMCL-dev/HMCL · error · IllegalArgumentException
Theme-pack asset entry contains an unsafe segment:
Error message
Theme-pack asset entry contains an unsafe segment:
What it means
Each '/'-separated segment of an asset entry name must be non-empty and must not be '.' or '..'. Violations throw IllegalArgumentException("Theme-pack asset entry contains an unsafe segment: <name>"). This blocks path traversal and malformed names inside the pack.
Solutions
- Remove '.', '..' and duplicate slashes from the entry name (normalize before calling)
- Reject or sanitize pack entries containing traversal segments before lookup
- Canonicalize the intended path and verify it stays under assets/
Example fix
// before
ThemePackAsset.of("assets/" + userInput + ".png"); // userInput = "../x"
// after
String safe = userInput.replace("\\", "/");
if (safe.contains("..") || safe.contains("//")) throw new IllegalArgumentException("bad name");
ThemePackAsset.of("assets/" + safe + ".png"); Defensive patterns
Strategy: validation
Validate before calling
static boolean hasSafeSegments(String name) {
String n = name.replace('\\', '/');
for (String seg : n.split("/")) {
if (seg.isEmpty() || seg.equals(".") || seg.equals("..")) return false;
}
return true;
} Type guard
static boolean isSafeSegment(String seg) {
return !seg.isEmpty() && !".".equals(seg) && !"..".equals(seg);
} Try / catch
try {
ThemePackAsset.of(entryName);
} catch (IllegalArgumentException e) {
log.warn("Rejected unsafe asset entry: " + e.getMessage());
} Prevention
- Never build entry names from untrusted input without checking for '..'
- Normalize and canonicalize names before lookup
- Reject packs containing traversal-style entries at load time
When it happens
Trigger: Passing names like "assets/../secrets.png", "assets//icon.png" (empty segment), or "assets/./x.png" to ThemePackAsset / normalizeEntryName.
Common situations: Malicious or buggy pack manifests containing ../ traversal attempts; string concatenation producing double slashes or redundant dots.
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
- Theme-pack asset escapes the installed directory:
- Malformed modpack configuration
- Theme-pack entry contains an unsafe segment
- path escapes instance root
- Unsecure path:
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/6f9a223f6bfb3611.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackAsset.java:76
Objects.requireNonNull(entryName);
String normalized = entryName.trim().replace('\\', '/');
if (normalized.isEmpty()) {
throw new IllegalArgumentException("Theme-pack asset entry is empty");
}
if (normalized.startsWith("/") || normalized.matches("^[A-Za-z]:.*")) {
throw new IllegalArgumentException("Theme-pack asset entry must be relative: " + entryName);
}
if (!normalized.startsWith(ASSETS_PREFIX)) {
throw new IllegalArgumentException("Theme-pack asset entry must be under assets/: " + entryName);
}
if (normalized.endsWith("/")) {
throw new IllegalArgumentException("Theme-pack asset entry must be a file: " + entryName);
}
for (String segment : normalized.split("/")) {
if (segment.isEmpty() || ".".equals(segment) || "..".equals(segment)) {
throw new IllegalArgumentException("Theme-pack asset entry contains an unsafe segment: " + entryName);
}
for (int i = 0; i < segment.length(); i++) {
char ch = segment.charAt(i);
if (Character.isISOControl(ch) || ch == '\0') {
throw new IllegalArgumentException("Theme-pack asset entry contains a control character: " + entryName);
}
}
}
return normalized;
}
}
View on GitHub (pinned to 24702dc5a0)