Skip to content

[Bug] Resource leaks in SamlSettingsHolder, SamlValidator, and IndexResource — unclosed streams and connections #27091

@RajdeepKushwaha5

Description

@RajdeepKushwaha5

Affected module
Backend (openmetadata-service)

Describe the bug

Three resource leak bugs across openmetadata-service where streams and connections are opened but never closed, leaking file descriptors and TCP sockets.

Bug 1: SamlSettingsHolder — FileInputStream never closed

In SamlSettingsHolder.java, a FileInputStream is created inline and passed directly to keyStore.load() without being assigned to a variable or wrapped in try-with-resources:

KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(
    new FileInputStream(securityConfig.getKeyStoreFilePath()),  // ← NEVER CLOSED
    securityConfig.getKeyStorePassword().toCharArray());

Since the stream is created inline, it cannot be closed later — the reference is lost immediately. This leaks a file descriptor every time SAML settings are loaded.

Bug 2: SamlValidator — HttpURLConnection never disconnected

In SamlValidator.validateIdpConnectivity(), an HttpURLConnection is opened to test the IdP SSO URL but conn.disconnect() is never called in any code path:

HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
int responseCode = conn.getResponseCode();
// ... multiple if/else branches processing the response ...
// ← conn.disconnect() NEVER called in ANY code path

Additionally, readResponseSnippet() reads from the connection's error/input stream without closing it. Every SAML IdP connectivity validation leaks a TCP socket.

Bug 3: IndexResource — InputStream and BufferedReader never closed

In IndexResource.java, both the constructor and the static getIndexFile() method open an InputStream and wrap it in a BufferedReader, but neither is ever closed:

// Constructor (same pattern in getIndexFile):
InputStream inputStream = getClass().getResourceAsStream("/assets/index.html");
indexHtml = new BufferedReader(new InputStreamReader(inputStream))
    .lines()
    .collect(Collectors.joining("\n"));
// ← BOTH InputStream and BufferedReader NEVER CLOSED

Additionally, there's no null check — if /assets/index.html is missing from the classpath, this throws an unhelpful NPE.

To Reproduce

Bug 1:

  1. Configure SAML authentication with a JKS keystore
  2. Each SAML settings load/reload leaks one OS file descriptor
  3. Under repeated SAML reconfigurations, file descriptor count grows

Bug 2:

  1. Configure SAML SSO validation
  2. Each call to validateIdpConnectivity() leaks one TCP socket
  3. Under repeated SAML validation (e.g., testing configurations), socket count grows

Bug 3:

  1. Start the OpenMetadata server
  2. Both the IndexResource constructor and any call to getIndexFile() leak classpath streams
  3. Minor impact since these run at startup, but violates resource management best practices

Expected behavior

All three should use try-with-resources to ensure streams and connections are properly closed:

  • Bug 1: FileInputStream wrapped in try-with-resources before passing to keyStore.load()
  • Bug 2: HttpURLConnection wrapped in try-finally with conn.disconnect() in the finally block
  • Bug 3: InputStream and BufferedReader wrapped in try-with-resources with a null check

These patterns are already used correctly elsewhere in the codebase (e.g., SchemaFieldExtractor.getAllEntityTypes(), AutoPilotApp, JsonLdTranslator, OntologyLoader).

Version:

  • OpenMetadata version: main branch (latest)

Additional context

This is a continuation of resource leak cleanup work from PR #27063, which fixed similar InputStream leaks in SchemaFieldExtractor.loadMainSchema() and SchemaFieldExtractor.loadSchema(). The same try-with-resources pattern applies here.

Related prior work:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions