Skip to content

[Backport 3.1] Preserve response headers across context restore in SecurityInterceptor#6187

Open
KishoreKicha14 wants to merge 2 commits into
opensearch-project:3.1from
KishoreKicha14:backport/3.1
Open

[Backport 3.1] Preserve response headers across context restore in SecurityInterceptor#6187
KishoreKicha14 wants to merge 2 commits into
opensearch-project:3.1from
KishoreKicha14:backport/3.1

Conversation

@KishoreKicha14

Copy link
Copy Markdown
Contributor

Description

[Describe what this change achieves]

  • Category (Enhancement, New feature, Bug fix, Test fix, Refactoring, Maintenance, Documentation)
  • Why these changes are required?
  • What is the old behavior before changes and new behavior after changes?

Issues Resolved

[List any issues this PR will resolve]

Is this a backport? If so, please add backport PR # and/or commits #, and remove backport-failed label from the original PR.

Do these changes introduce new permission(s) to be displayed in the static dropdown on the front-end? If so, please open a draft PR in the security dashboards plugin and link the draft PR here

Testing

[Please provide details of testing done: unit testing, integration testing and manual testing]

Check List

  • New functionality includes testing
  • New functionality has been documented
  • New Roles/Permissions have a corresponding security dashboards plugin PR
  • API changes companion pull request created
  • Commits are signed per the DCO using --signoff

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

…rceptor

Signed-off-by: Kishore Kumaar Natarajan <kkumaarn@amazon.com>
Replace concatenated JSON strings with Java text blocks for improved
readability in SecurityInterceptorTests.

Signed-off-by: Kishore Kumaar Natarajan <kkumaarn@amazon.com>
@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

🧪 PR contains tests
🔒 No security concerns identified
✅ No TODO sections
🔀 No multiple PR themes
⚡ Recommended focus areas for review

Resource Leak

The restorableContextSupplier created at line 162 is never consumed if an exception occurs before the RestoringTransportResponseHandler is instantiated (lines 164-167). If stashContext() throws or any code between lines 162-163 fails, the supplier's internal context remains unreleased, potentially leaking ThreadContext resources.

final Supplier<ThreadContext.StoredContext> restorableContextSupplier = getThreadContext().newRestorableContext(true);
try (ThreadContext.StoredContext stashedContext = getThreadContext().stashContext()) {
    final TransportResponseHandler<T> restoringHandler = new RestoringTransportResponseHandler<T>(
        handler,
        restorableContextSupplier
    );
Missing Close

In handleResponse() at line 368, contextToRestore.get() is called but the returned StoredContext is not closed. Unlike handleException() which uses try-with-resources, this path leaves the context open, causing a resource leak on every successful response.

contextToRestore.get();

@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Close StoredContext to prevent leak

The contextToRestore.get() call in handleResponse() retrieves a StoredContext but
doesn't close it, potentially causing a resource leak. The context should be used in
a try-with-resources block to ensure proper cleanup, similar to the
handleException() method.

src/main/java/org/opensearch/security/transport/SecurityInterceptor.java [368]

-contextToRestore.get();
+try (ThreadContext.StoredContext ignore = contextToRestore.get()) {
+    // existing code for handling response headers and inner handler
+}
Suggestion importance[1-10]: 9

__

Why: The contextToRestore.get() call retrieves a StoredContext without closing it, which can cause a resource leak. The handleException() method correctly uses try-with-resources (line 399), but handleResponse() does not. This is a critical resource management issue that should be fixed.

High
General
Create restorable context after stashing

The restorableContextSupplier is created before stashing the context, which may
capture an inconsistent state. Consider creating the restorable context supplier
after stashing to ensure it captures the correct context state for restoration.

src/main/java/org/opensearch/security/transport/SecurityInterceptor.java [162-167]

-final Supplier<ThreadContext.StoredContext> restorableContextSupplier = getThreadContext().newRestorableContext(true);
 try (ThreadContext.StoredContext stashedContext = getThreadContext().stashContext()) {
+    final Supplier<ThreadContext.StoredContext> restorableContextSupplier = getThreadContext().newRestorableContext(true);
     final TransportResponseHandler<T> restoringHandler = new RestoringTransportResponseHandler<T>(
         handler,
         restorableContextSupplier
     );
Suggestion importance[1-10]: 2

__

Why: The suggestion misunderstands the purpose of newRestorableContext(true). Creating it before stashing is intentional - it captures the current context state (including response headers) that should be preserved. Moving it after stashing would defeat the purpose of the change, which is to preserve response headers across context restoration.

Low

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant