Skip to content

Resource leak: OkHttp Response not closed in FetchVideoDataTask.doInBackground #53

Description

@CyberSecurity-NCC

Summary

The doInBackground method of the inner class FetchVideoDataTask (in YouTubeCaptureActivity) fails to close the OkHttp Response object in several code paths, leading to a leak of native network resources.

Impact

  • File descriptor exhaustion: Each leaked Response holds a connection and its associated file descriptor. Error conditions such as an invalid YouTube URL, a network interruption, or any non‑2xx HTTP status cause the response to be discarded without being closed. Under repeated use – for example tapping “Fetch” multiple times with a malformed URL – the process can quickly exhaust available file descriptors, resulting in java.io.IOException: Too many open files, random crashes, and possibly OutOfMemoryError.
  • System strain: Leaked connections put extra pressure on the garbage collector, degrade network throughput, and can contribute to application ANRs over time.

Code Analysis

File: app/src/main/java/.../YouTubeCaptureActivity.java (inner class FetchVideoDataTask), line 127

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();

if (response.isSuccessful()) {
    return response.body().string();
} else {
    Log.e(TAG, "Error: " + response.code());
}
// Exception handling not shown; if body().string() throws IOException,
// the Response is also not closed.

The OkHttp documentation states that Response implements Closeable and must be closed to release the underlying socket and file descriptors. The code above fails to close the response in three scenarios:

  1. Success pathbody().string() returns, but the Response is never closed.
  2. Failure branch – the non‑2xx response is logged and then discarded.
  3. Exception path – if body().string() or execute() throws an IOException, no finally block or try‑with‑resources exists to close the response.

Suggested Fix

Wrap the Response in a try-with-resources block (available since Java 7 / Android API 19). This guarantees automatic closure on success, failure, or exception.

@Override
protected String doInBackground(String... videoIds) {
    String url = buildUrl(videoIds[0]);
    try (Response response = new OkHttpClient().newCall(
            new Request.Builder().url(url).build()).execute()) {
        if (!response.isSuccessful()) {
            Log.e(TAG, "Error fetching video data: " + response.code());
            return null;
        }
        return response.body().string();
    } catch (IOException e) {
        Log.e(TAG, "Error fetching video data: ", e);
        return null;
    }
}

Optionally, consider reusing a single OkHttpClient instance (e.g., via a singleton) for better connection pooling and reduced overhead.

Context & Acknowledgement

This issue was identified during our academic research on Java resource management. We have manually reviewed this finding to ensure its validity.
Thank you for maintaining this open-source project! We hope this report helps.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions