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

  1. Ensure the scanner and server are compatible versions and the scanner re-fetches the index (api/batch/index) before requesting files
  2. Restore any missing jars in the batch directory from the distribution
  3. Never hand-craft file paths in batch requests — use paths returned by get_index
  4. 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

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


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)