SonarSource/sonarqube · error · NotFoundException
Bad filename
Error message
Bad filename: ${filename} What it means
BatchIndex.getFile resolves a requested scanner file name against the batch directory and rejects it unless the file's canonical path is contained within the batch directory AND the file exists, throwing NotFoundException 'Bad filename: <name>'. It is a path-traversal and existence guard for the batch file-serving endpoint.
Solutions
- Ensure the scanner and server are compatible versions and the scanner re-fetches the index (api/batch/index) before requesting files
- Restore any missing jars in the batch directory from the distribution
- Never hand-craft file paths in batch requests — use paths returned by get_index
- If batch is behind a proxy/symlink, ensure the real canonical path stays inside the batch directory
Example fix
// before GET api/batch/file?name=../../etc/passwd // after GET api/batch/index -> use returned filenames, e.g. name=sonar-scanner-api-2.1.0.244.jar
Defensive patterns
Strategy: try-catch
Validate before calling
// Before requesting a batch file, take the name only from the index response:
const index = await (await fetch(`${sonarUrl}/api/batch/index`)).text();
if (!index.includes(requestedFile)) {
throw new Error(`'${requestedFile}' is not in the batch index — refresh the index instead of crafting paths`);
} Type guard
function isSafeBatchFilename(name) {
return typeof name === 'string' && /^[A-Za-z0-9._-]+\.jar$/.test(name) && !name.includes('..');
} Try / catch
try {
jar = batchIndex.file(filename);
} catch (NotFoundException e) {
if (e.getMessage().startsWith("Bad filename:")) {
log.warn("Rejected batch file request (traversal or missing): " + e.getMessage());
// re-fetch api/batch/index and retry with a valid listed name
} else { throw e; }
} Prevention
- Always fetch api/batch/index first and request only listed file names
- Keep scanner and server versions aligned so requested jars exist in lib/batch
- Never send relative/absolute path components in batch file requests
- Avoid symlinked batch directories that break canonical containment checks
When it happens
Trigger: A batch WS request (get_file/check_location_of_file) asks for a filename containing '../' or absolute paths, or a name not present in the batch directory — including clients requesting jars that were removed.
Common situations: Scanner/server version mismatch where the scanner requests a jar no longer in lib/batch; malicious or buggy clients probing for traversal; symlinked batch dirs breaking canonical containment checks.
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
- Analysis ' ' not found
- Can get file
- Component ' ' of pull request ' ' not found
- Component ' ' on branch ' ' not found
- Email configuration doesn't exist.
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/fcc042f4c2b80ab7.
Report an issue: GitHub.
Appendix: source
Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/batch/BatchIndex.java:90
throw new IllegalStateException(format("%s folder not found", batchDir.getAbsolutePath()));
}
this.index = sb.toString();
}
@Override
public void stop() {
// Nothing to do
}
String getIndex() {
return index;
}
File getFile(String filename) {
try {
File input = new File(batchDir, filename);
if (!FilenameUtils.directoryContains(batchDir.getCanonicalPath(), input.getCanonicalPath()) || !input.exists()) {
throw new NotFoundException("Bad filename: " + filename);
}
return input;
} catch (IOException e) {
throw new IllegalStateException("Can get file " + filename, e);
}
}
}
View on GitHub (pinned to 184c821202)