Skip to content

fix: redact sensitive information from log output#12271

Merged
ogabrielluiz merged 4 commits into
release-1.9.0from
fix/clear-text-logging-sensitive-info
Apr 1, 2026
Merged

fix: redact sensitive information from log output#12271
ogabrielluiz merged 4 commits into
release-1.9.0from
fix/clear-text-logging-sensitive-info

Conversation

@ogabrielluiz
Copy link
Copy Markdown
Contributor

@ogabrielluiz ogabrielluiz commented Mar 20, 2026

Summary

  • Redact sensitive config values and auth settings from debug log output
  • Log only dictionary keys instead of full variable contents in MCP and OpenAI response handlers
  • Use parameterized logging to avoid interpolating sensitive CLI config values
  • Fix missing await on async logger call in agentic_mcp
  • Remove redundant duplicate log line in openai_responses
  • Fix PERF403 lint error in setup.py (dict comprehension)

Note: Test helper output and the API key banner intentionally show full values, as they are meant for developer use (load testing setup, one-time key display).

@github-actions github-actions Bot added the community Pull Request from an external contributor label Mar 20, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 20, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bb7debe1-ffc5-4688-b403-f3fe85cadf99

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Changes reduce sensitive data exposure in logging across multiple backend modules by replacing full object/dictionary logging with redacted messages or key-only logs, and masking credentials (API keys, passwords, JWT tokens) to display only the last 4 characters.

Changes

Cohort / File(s) Summary
CLI and MCP Configuration Logging
src/backend/base/langflow/__main__.py, src/backend/base/langflow/api/utils/mcp/agentic_mcp.py, src/backend/base/langflow/api/utils/mcp/config_utils.py
Updated debug logging to use parameterized formatting and redacted/key-only output instead of full objects. Replaced auth settings logging with [REDACTED] constant and agentic variables dict logging with list(...keys()).
API Response Logging
src/backend/base/langflow/api/v1/openai_responses.py
Changed debug logging in run_flow_for_openai_responses and create_response to output only dictionary keys instead of full variables and context objects.
Test Credential Masking
src/backend/tests/locust/langflow_setup_test.py
Updated print_setup_results() to mask sensitive credentials in displayed output: passwords show only last 4 characters with *** prefix, JWT tokens display as *** + last 4 characters (or N/A if absent), and API keys masked similarly.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 minutes


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 2 warnings)

Check name Status Explanation Resolution
Test Coverage For New Implementations ❌ Error PR modifies four source files with sensitive information logging changes but lacks corresponding unit tests to verify redaction works correctly across all modules. Add pytest unit tests with caplog fixtures to verify API keys, passwords, tokens, and auth settings are properly redacted from logs in modified modules.
Test Quality And Coverage ⚠️ Warning No dedicated unit tests were added to verify sensitive information redaction across modified modules (main.py, agentic_mcp.py, config_utils.py, openai_responses.py). Add unit tests validating that sensitive data (API keys, tokens, passwords) are redacted in logs with [REDACTED] placeholders and only last 4 characters shown where applicable.
Test File Naming And Structure ⚠️ Warning Test file violates naming convention by using langflow_setup_test.py instead of test_langflow_setup.py, and lacks proper pytest structure with test functions. Rename file to test_langflow_setup.py and refactor to use pytest structure with proper test_* function names and fixtures.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely summarizes the main change: redacting sensitive information from log output, which is the primary objective across all five modified files.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.
Excessive Mock Usage Warning ✅ Passed The load test setup script contains no mocks or patches—only real httpx HTTP calls to a running Langflow server, making the excessive mock usage check inapplicable.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/clear-text-logging-sensitive-info

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the bug Something isn't working label Mar 20, 2026
@ogabrielluiz ogabrielluiz requested a review from Jkavia March 20, 2026 19:09
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 20, 2026

Frontend Unit Test Coverage Report

Coverage Summary

Lines Statements Branches Functions
Coverage: 28%
28.01% (29184/104184) 64.76% (3717/5739) 30.03% (689/2294)

Unit Test Results

Tests Skipped Failures Errors Time
3014 0 💤 0 ❌ 0 🔥 4m 42s ⏱️

@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 20, 2026

Codecov Report

❌ Patch coverage is 66.66667% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 48.91%. Comparing base (389f702) to head (72df117).
⚠️ Report is 2 commits behind head on release-1.9.0.

Files with missing lines Patch % Lines
...backend/base/langflow/api/utils/mcp/agentic_mcp.py 0.00% 1 Missing ⚠️
...c/backend/base/langflow/api/v1/openai_responses.py 50.00% 1 Missing ⚠️

❌ Your project status has failed because the head coverage (45.53%) is below the target coverage (60.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@                Coverage Diff                @@
##           release-1.9.0   #12271      +/-   ##
=================================================
+ Coverage          48.86%   48.91%   +0.04%     
=================================================
  Files               1897     1896       -1     
  Lines             167656   167624      -32     
  Branches           23193    23120      -73     
=================================================
+ Hits               81928    81987      +59     
+ Misses             84817    84727      -90     
+ Partials             911      910       -1     
Flag Coverage Δ
backend 54.89% <66.66%> (+<0.01%) ⬆️
frontend 48.27% <ø> (+0.06%) ⬆️
lfx 45.53% <ø> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/backend/base/langflow/__main__.py 55.30% <100.00%> (ø)
...ackend/base/langflow/api/utils/mcp/config_utils.py 69.95% <100.00%> (ø)
...backend/base/langflow/api/utils/mcp/agentic_mcp.py 12.50% <0.00%> (ø)
...c/backend/base/langflow/api/v1/openai_responses.py 40.89% <50.00%> (-0.24%) ⬇️

... and 35 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Mar 20, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/backend/tests/locust/langflow_setup_test.py (1)

407-418: ⚠️ Potential issue | 🟡 Minor

Credentials file still contains full sensitive values.

The save_credentials function writes the full unmasked password, access_token, and api_key to a JSON file. While this may be intentional for the load testing use case, it's inconsistent with the redaction approach in print_setup_results. Consider adding a warning when saving credentials to file, or document this explicitly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/backend/tests/locust/langflow_setup_test.py` around lines 407 - 418, The
save_credentials function is currently persisting full sensitive values
(password, access_token, api_key) while print_setup_results redacts them; update
save_credentials to either redact these fields before writing or emit a clear
warning/log that full credentials are being written so reviewers/users are
aware. Concretely, in save_credentials replace or duplicate sensitive fields
(password, access_token, api_key) with masked versions (e.g., keep last 4 chars)
before serializing, and/or add a processLogger.warning call (or raise a flag) in
the same function to document that unredacted credentials will be saved;
reference save_credentials and print_setup_results so the change is consistent
with the redaction behavior.
🧹 Nitpick comments (2)
src/backend/tests/locust/langflow_setup_test.py (1)

360-362: Consider simplifying the conditional print statement.

The inline conditional expression spanning multiple lines is harder to read. Consider refactoring for clarity.

Proposed refactor
-    print(f"JWT Token:   ***{setup_state['access_token'][-4:]}") if setup_state["access_token"] else print(
-        "JWT Token:   N/A"
-    )
+    if setup_state["access_token"]:
+        print(f"JWT Token:   ***{setup_state['access_token'][-4:]}")
+    else:
+        print("JWT Token:   N/A")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/backend/tests/locust/langflow_setup_test.py` around lines 360 - 362,
Replace the inline conditional print with a simple if/else for readability:
check setup_state["access_token"] and if present print the masked token using
setup_state['access_token'][-4:], otherwise print "JWT Token:   N/A"; update the
code around the existing print statement that references setup_state and
access_token (the block currently using the inline conditional) to use this
clearer if/else structure.
src/backend/base/langflow/api/v1/openai_responses.py (1)

620-622: Redundant log statement.

Line 622 logs Variables dict keys: {list(variables.keys())} which duplicates the information already logged on line 621 (Extracted global variables from headers: {list(variables.keys())}). Consider removing the redundant log.

Proposed fix
     await logger.adebug(f"All headers received: {list(http_request.headers.keys())}")
     await logger.adebug(f"Extracted global variables from headers: {list(variables.keys())}")
-    await logger.adebug(f"Variables dict keys: {list(variables.keys())}")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/backend/base/langflow/api/v1/openai_responses.py` around lines 620 - 622,
Remove the redundant debug log that repeats the same keys already logged: delete
the second/third call to logger.adebug that prints list(variables.keys()) so
only one meaningful message remains (e.g., keep "Extracted global variables from
headers: {list(variables.keys())}"); locate the three consecutive await
logger.adebug calls (the ones referencing http_request.headers and variables)
and remove the duplicate "Variables dict keys" logger call to avoid duplicated
output.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/backend/base/langflow/api/utils/mcp/agentic_mcp.py`:
- Line 325: Inside the async context where Agentic variables are logged, the
call to logger.adebug is not awaited (logger.adebug(f"Agentic variables:
{list(agentic_variables.keys())}")), causing inconsistent async behavior with
other awaits; change this call to use await logger.adebug(...) so it matches the
surrounding awaited logger calls (see other occurrences of await logger.adebug
in this file) and ensure the statement remains inside the same async function
that references agentic_variables.

In `@src/backend/tests/locust/langflow_setup_test.py`:
- Line 374: The export command currently prints a masked API key with
print(f"export API_KEY='***{setup_state['api_key'][-4:]}'"), which prevents
copy-paste use; update the print to emit the full API key value from
setup_state['api_key'] so the export command is immediately usable (or, if
redaction is required, change the export print to instruct users to paste the
previously-displayed full key, e.g., print("export API_KEY='<use the API key
displayed above>'")). Ensure you modify the print statement that references
setup_state['api_key'] so the exported command contains the actual key or a
clear instruction to retrieve it.

---

Outside diff comments:
In `@src/backend/tests/locust/langflow_setup_test.py`:
- Around line 407-418: The save_credentials function is currently persisting
full sensitive values (password, access_token, api_key) while
print_setup_results redacts them; update save_credentials to either redact these
fields before writing or emit a clear warning/log that full credentials are
being written so reviewers/users are aware. Concretely, in save_credentials
replace or duplicate sensitive fields (password, access_token, api_key) with
masked versions (e.g., keep last 4 chars) before serializing, and/or add a
processLogger.warning call (or raise a flag) in the same function to document
that unredacted credentials will be saved; reference save_credentials and
print_setup_results so the change is consistent with the redaction behavior.

---

Nitpick comments:
In `@src/backend/base/langflow/api/v1/openai_responses.py`:
- Around line 620-622: Remove the redundant debug log that repeats the same keys
already logged: delete the second/third call to logger.adebug that prints
list(variables.keys()) so only one meaningful message remains (e.g., keep
"Extracted global variables from headers: {list(variables.keys())}"); locate the
three consecutive await logger.adebug calls (the ones referencing
http_request.headers and variables) and remove the duplicate "Variables dict
keys" logger call to avoid duplicated output.

In `@src/backend/tests/locust/langflow_setup_test.py`:
- Around line 360-362: Replace the inline conditional print with a simple
if/else for readability: check setup_state["access_token"] and if present print
the masked token using setup_state['access_token'][-4:], otherwise print "JWT
Token:   N/A"; update the code around the existing print statement that
references setup_state and access_token (the block currently using the inline
conditional) to use this clearer if/else structure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: eca215ac-0029-44c5-b592-8e8c787afe04

📥 Commits

Reviewing files that changed from the base of the PR and between cacb54d and b4f4525.

📒 Files selected for processing (5)
  • src/backend/base/langflow/__main__.py
  • src/backend/base/langflow/api/utils/mcp/agentic_mcp.py
  • src/backend/base/langflow/api/utils/mcp/config_utils.py
  • src/backend/base/langflow/api/v1/openai_responses.py
  • src/backend/tests/locust/langflow_setup_test.py

# Create a dict with agentic variable names and default values as empty strings
agentic_variables = dict.fromkeys(AGENTIC_VARIABLES, DEFAULT_AGENTIC_VARIABLE_VALUE)
logger.adebug(f"Agentic variables: {agentic_variables}")
logger.adebug(f"Agentic variables: {list(agentic_variables.keys())}")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent use of sync logger in async function.

Line 325 uses logger.adebug(...) without await, while the surrounding code (e.g., lines 330, 341, 352, 354) correctly uses await logger.adebug(...). This should be awaited for consistency and proper async behavior.

Proposed fix
-        logger.adebug(f"Agentic variables: {list(agentic_variables.keys())}")
+        await logger.adebug(f"Agentic variables: {list(agentic_variables.keys())}")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
logger.adebug(f"Agentic variables: {list(agentic_variables.keys())}")
await logger.adebug(f"Agentic variables: {list(agentic_variables.keys())}")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/backend/base/langflow/api/utils/mcp/agentic_mcp.py` at line 325, Inside
the async context where Agentic variables are logged, the call to logger.adebug
is not awaited (logger.adebug(f"Agentic variables:
{list(agentic_variables.keys())}")), causing inconsistent async behavior with
other awaits; change this call to use await logger.adebug(...) so it matches the
surrounding awaited logger calls (see other occurrences of await logger.adebug
in this file) and ensure the statement remains inside the same async function
that references agentic_variables.

print("# Set environment variables:")
print(f"export LANGFLOW_HOST='{setup_state['host']}'")
print(f"export API_KEY='{setup_state['api_key']}'")
print(f"export API_KEY='***{setup_state['api_key'][-4:]}'")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Masked API key in export command defeats copy-paste purpose.

The export command is meant to be copied and pasted by users to set environment variables. Masking the API key here makes the command non-functional. Users would need to manually retrieve the actual API key value.

Consider keeping the full API key in the export command since users explicitly run this setup script to obtain working credentials, or provide the value in a separate secure output section.

Proposed fix - keep full API key in export command
-    print(f"export API_KEY='***{setup_state['api_key'][-4:]}'")
+    print(f"export API_KEY='{setup_state['api_key']}'")

Alternatively, if redaction is required, inform users where to find the full key:

print("export API_KEY='<use the API key displayed above>'")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/backend/tests/locust/langflow_setup_test.py` at line 374, The export
command currently prints a masked API key with print(f"export
API_KEY='***{setup_state['api_key'][-4:]}'"), which prevents copy-paste use;
update the print to emit the full API key value from setup_state['api_key'] so
the export command is immediately usable (or, if redaction is required, change
the export print to instruct users to paste the previously-displayed full key,
e.g., print("export API_KEY='<use the API key displayed above>'")). Ensure you
modify the print statement that references setup_state['api_key'] so the
exported command contains the actual key or a clear instruction to retrieve it.

@ogabrielluiz ogabrielluiz removed the community Pull Request from an external contributor label Mar 24, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Mar 24, 2026
@github-actions github-actions Bot added the lgtm This PR has been approved by a maintainer label Mar 26, 2026
@Jkavia
Copy link
Copy Markdown
Collaborator

Jkavia commented Mar 26, 2026

can you merge this into 1.9.0 instead ?

@ogabrielluiz ogabrielluiz enabled auto-merge April 1, 2026 13:15
@ogabrielluiz ogabrielluiz disabled auto-merge April 1, 2026 13:15
Mask or remove API keys, passwords, tokens, auth settings, and
configuration values from logger calls and print statements to prevent
clear-text exposure of credentials in logs.
- Restore full API key display in Windows fallback banner (masking
  defeated the purpose of showing the key for the only time)
- Revert test helper masking in locust setup (developers need full
  credentials for load testing)
- Add missing await on logger.adebug in agentic_mcp
- Remove redundant duplicate log line in openai_responses
@ogabrielluiz ogabrielluiz force-pushed the fix/clear-text-logging-sensitive-info branch from e594be2 to 6e673ea Compare April 1, 2026 13:17
@ogabrielluiz ogabrielluiz changed the base branch from main to release-1.9.0 April 1, 2026 13:17
@ogabrielluiz ogabrielluiz enabled auto-merge April 1, 2026 13:17
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Apr 1, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Apr 1, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Apr 1, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Apr 1, 2026
@ogabrielluiz ogabrielluiz added this pull request to the merge queue Apr 1, 2026
Merged via the queue into release-1.9.0 with commit 2ef9a5f Apr 1, 2026
102 of 103 checks passed
@ogabrielluiz ogabrielluiz deleted the fix/clear-text-logging-sensitive-info branch April 1, 2026 20:16
Adam-Aghili pushed a commit that referenced this pull request Apr 15, 2026
* fix: redact sensitive information from log output

Mask or remove API keys, passwords, tokens, auth settings, and
configuration values from logger calls and print statements to prevent
clear-text exposure of credentials in logs.

* fix: address code review feedback on sensitive info redaction

- Restore full API key display in Windows fallback banner (masking
  defeated the purpose of showing the key for the only time)
- Revert test helper masking in locust setup (developers need full
  credentials for load testing)
- Add missing await on logger.adebug in agentic_mcp
- Remove redundant duplicate log line in openai_responses

* fix: replace unnecessary dict comprehension with dict() call

---------

Co-authored-by: Janardan Singh Kavia <janardankavia@ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working lgtm This PR has been approved by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants