microsoft/playwright · error · Error

HAR entry _file escapes base directory: ${file}

Error message

HAR entry _file escapes base directory: ${file}

What it means

Thrown by HarBackend._loadContent() when a non-zipped HAR file's content entry has a _file property that, after path.resolve against the base directory, resolves to a path outside that base directory. This is a path-traversal security guard ensuring HAR content files cannot reference arbitrary filesystem locations.

Source

Thrown at packages/playwright-core/src/server/harBackend.ts:87

        status: response.status,
        headers: response.headers,
        body: buffer,
      };
    } catch (e) {
      return { action: 'error', message: e.message };
    }
  }

  private async _loadContent(content: { text?: string, encoding?: string, _file?: string }): Promise<Buffer> {
    const file = content._file;
    let buffer: Buffer;
    if (file) {
      if (this._zipFile) {
        buffer = await this._zipFile.read(file);
      } else {
        const resolved = path.resolve(this._baseDir!, file);
        if (!isPathInside(this._baseDir!, resolved))
          throw new Error(`HAR entry _file escapes base directory: ${file}`);
        buffer = await fs.promises.readFile(resolved);
      }
    } else {
      buffer = Buffer.from(content.text || '', content.encoding === 'base64' ? 'base64' : 'utf-8');
    }
    return buffer;
  }

  private async _harFindResponse(url: string, method: string, headers: HeadersArray, postData: Buffer | undefined): Promise<har.Entry | undefined> {
    const harLog = this._harFile.log;
    const visited = new Set<har.Entry>();
    while (true) {
      const entries: har.Entry[] = [];
      for (const candidate of harLog.entries) {
        if (candidate.request.url !== url || candidate.request.method !== method)
          continue;
        if (method === 'POST' && postData && candidate.request.postData) {
          const buffer = await this._loadContent(candidate.request.postData);

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Regenerate the HAR file using Playwright's built-in recording: npx playwright codegen --save-har=trace.har.
  2. Inspect the HAR JSON and ensure all content._file values are simple relative filenames (no .. or absolute paths).
  3. Use a zipped HAR format (.zip containing har.har) which bypasses the filesystem path check entirely.
  4. Ensure the HAR file and its referenced content files reside in the same base directory.
Defensive patterns

Strategy: validation

Validate before calling

// Validate HAR content._file paths before replay
const har = JSON.parse(fs.readFileSync(harPath, 'utf-8'));
for (const entry of har.log.entries) {
  if (entry.response?.content?._file?.includes('..'))
    throw new Error(`HAR entry has unsafe _file path: ${entry.response.content._file}`);
}

Prevention

When it happens

Trigger: Replaying a HAR file via routeFromHAR() where the HAR's content._file field contains a relative path with directory traversal sequences (e.g., ../../etc/passwd). The check uses isPathInside() to verify the resolved path stays within the HAR's base directory. Only applies to non-zipped HAR files; zipped HARs read entries from the zip archive directly.

Common situations: HAR file was manually edited or generated by a tool that inserted unsafe relative paths. HAR file was moved to a different directory and the _file paths are now interpreted relative to a different base. Malicious or corrupted HAR file supplied by a third party. Incorrect HAR export tool that writes absolute or traversal-containing paths.

Related errors


AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12). Data as JSON: /api/errors/651e07801c42f0e6. Report an issue: GitHub.