Avoid using print() for debugging to prevent sensitive information from leaking via container logs #628

Closed
opened 2026-02-16 10:19:58 -05:00 by yindo · 5 comments
Owner

Originally created by @kurokobo on GitHub (Sep 6, 2025).

Self Checks

  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues Dify issues & Dify Official Plugins, including closed ones.
  • I confirm that I am using English to submit this report (我已阅读并同意 Language Policy).
  • [FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)
  • Please do not modify this template :) and fill in all the required fields.

Dify version

2.0.0-beta.1

Plugin version

Any

Cloud or Self Hosted

Self Hosted (Docker)

Steps to reproduce

  1. Install S3 Datasource plugin and configure it.
  2. Place it in the knowledge pipeline and run test.
  3. Check the logs of the Plugin Daemon.

✔️ Error log

Credentials are there in plain text.

Image
Originally created by @kurokobo on GitHub (Sep 6, 2025). ### Self Checks - [x] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general). - [x] I have searched for existing issues [Dify issues](https://github.com/langgenius/dify/issues) & [Dify Official Plugins](https://github.com/langgenius/dify-official-plugins/issues), including closed ones. - [x] I confirm that I am using English to submit this report (我已阅读并同意 [Language Policy](https://github.com/langgenius/dify/issues/1542)). - [x] [FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:) - [x] Please do not modify this template :) and fill in all the required fields. ### Dify version 2.0.0-beta.1 ### Plugin version Any ### Cloud or Self Hosted Self Hosted (Docker) ### Steps to reproduce 1. Install S3 Datasource plugin and configure it. 2. Place it in the knowledge pipeline and run test. 3. Check the logs of the Plugin Daemon. ### ✔️ Error log Credentials are there in plain text. <img width="1199" height="209" alt="Image" src="https://github.com/user-attachments/assets/5c88e2c0-ab30-43d6-b858-1c72ad81f3e6" />
yindo added the bug label 2026-02-16 10:19:58 -05:00
yindo closed this issue 2026-02-16 10:19:58 -05:00
Author
Owner

@kurokobo commented on GitHub (Sep 6, 2025):

@crazywoola @Yeuoly
It seems that some plugins in this repository use print() for debugging purposes or error output.

Standard output from print() is passed to the Plugin Daemon, which tries to parse it as JSON. However, most print() outputs are not JSON strings, so this leads to parsing errors, which are then output as errors in the logs of the Plugin Daemon container.

Because of this, information intended only for debugging may leak into the logs.

For example, the S3 data source plugin outputs credentials in plain text, as above screenshot, since it has print(credentials).

https://github.com/langgenius/dify-official-plugins/blob/205d2fb694c9cda6324c0fc66c9c20c05f59b2ae/datasources/aws_s3_storage/datasources/aws_s3_storage.py#L25

In the case of the Google Drive data source plugin, file information is outputted. It prints raw api response.

https://github.com/langgenius/dify-official-plugins/blob/205d2fb694c9cda6324c0fc66c9c20c05f59b2ae/datasources/google_drive/datasources/google_drive.py#L70

Image

While errors caused by print() in the Plugin Daemon do not affect the actual behavior of the plugin itself, the plugin still works as expected. That said, unnecessary errors should be suppressed, and since it could potentially lead to the leakage of sensitive information, I personally think print() shouldn’t be used in principle.

What do you think?

For now, I’ll open a PR for the S3 and Google Drive plugins, which I was able to test.
Since there are quite a few plugins with print(), I’ll leave it up to you how far you want to go with it.

$ find . -name '*.py' -print0 | xargs -0 grep 'print('
./datasources/aws_s3_storage/datasources/aws_s3_storage.py:        print(credentials)
./datasources/firecrawl_datasource/datasources/crawl.py:            print(crawl_res)
./datasources/tavily_datasource/datasources/search_extract.py:                            print(f"Failed to extract content from {result.get('url', '')}: {str(e)}")
./datasources/tavily_datasource/datasources/search_extract.py:                    print(f"Error processing result {idx}: {str(e)}")
./datasources/notion_datasource/datasources/notion_datasource.py:        print(online_document_res)
./datasources/google_drive/datasources/google_drive.py:            print(results)
./datasources/confluence_datasource/provider/confluence_datasource.py:        print(f"Expires in: {expires_in}")
./datasources/confluence_datasource/datasources/confluence_datasource.py:        print(f"Fetching Confluence pages from: {url}")
./datasources/confluence_datasource/datasources/confluence_datasource.py:                    print(f"Authentication failed with 401. URL: {url}")
./datasources/confluence_datasource/datasources/confluence_datasource.py:                    print(f"Response: {response.text[:200]}")
./datasources/confluence_datasource/datasources/confluence_datasource.py:                    print(f"Request failed: {response.status_code} - {response.text[:200]}")
./models/huggingface_tei/models/text_embedding/text_embedding.py:            print(extra_args)
./models/huggingface_tei/models/helper.py:                print(f"Request failed, retry {attempt+1}/{max_retries}... ({e})")
./models/huggingface_tei/models/helper.py:                print(f"Request failed, retry {attempt+1}/{max_retries}... ({e})")
./models/huggingface_tei/models/helper.py:                print(f"Request failed, retry {attempt+1}/{max_retries}... ({e})")
./models/tongyi/models/text_embedding/text_embedding.py:                print(f"Rate limit exceeded (429). Response: {response}")
./models/tongyi/models/rerank/rerank.py:            print(ex)
./models/gemini/models/tests/test_document_filtering.py:        print(f"Cache key: {cache_key}")
./models/gemini/models/tests/test_document_filtering.py:        print(f"Cache exists before: {self.memory_cache.exists(cache_key)}")
./models/gemini/models/tests/test_document_filtering.py:            print(f"After first upload - call count: {self.mock_client.files.upload.call_count}")
./models/gemini/models/tests/test_document_filtering.py:            print(f"Cache exists after first: {self.memory_cache.exists(cache_key)}")
./models/gemini/models/tests/test_document_filtering.py:            print(f"After second upload - call count: {self.mock_client.files.upload.call_count}")
./models/gemini/models/tests/test_document_filtering.py:        print(f"{self.mock_client.files.upload.call_count=}")
./models/oci/models/llm/call_api.py:    # print("body"*20, body)
./models/oci/models/text_embedding/call_api.py:    # print("body"*20, body)
./models/sagemaker/provider/sagemaker.py:        print(f"Error generating presigned URL: {e}")
./models/sagemaker/models/text_embedding/text_embedding.py:            print("validate_credentials ok....")
./models/vertex_ai/models/llm/llm.py:                    # print(f"Warning: Unknown schema key '{key}' encountered. Ignoring.")
./models/cometapi/tools/yaml_batch_operator.py:                print(f"[DRY RUN] Would perform on {yaml_file.relative_to(yaml_file.parents[3])}: {', '.join(completed_operations)}")
./models/cometapi/tools/yaml_batch_operator.py:            print(f"✓ Modified {yaml_file.relative_to(yaml_file.parents[3])}: {', '.join(completed_operations)}")
./models/cometapi/tools/yaml_batch_operator.py:            print(f"✗ {error_msg}")
./models/cometapi/tools/yaml_batch_operator.py:        print(f"🔍 Scanning directory: {root_dir}")
./models/cometapi/tools/yaml_batch_operator.py:        print(f"🎯 Operations to perform: {', '.join(op_summary)}")
./models/cometapi/tools/yaml_batch_operator.py:            print("🧪 Running in DRY-RUN mode - no files will be modified")
./models/cometapi/tools/yaml_batch_operator.py:            print("❌ No YAML files found matching criteria")
./models/cometapi/tools/yaml_batch_operator.py:        print(f"📄 Found {len(yaml_files)} YAML files to process")
./models/cometapi/tools/yaml_batch_operator.py:        print()
./models/cometapi/tools/yaml_batch_operator.py:        print()
./models/cometapi/tools/yaml_batch_operator.py:        print("=" * 60)
./models/cometapi/tools/yaml_batch_operator.py:        print("📊 SUMMARY")
./models/cometapi/tools/yaml_batch_operator.py:        print("=" * 60)
./models/cometapi/tools/yaml_batch_operator.py:        print(f"Total files processed: {len(self.processed_files)}")
./models/cometapi/tools/yaml_batch_operator.py:        print(f"Files modified: {len(self.modified_files)}")
./models/cometapi/tools/yaml_batch_operator.py:        print(f"Errors encountered: {len(self.errors)}")
./models/cometapi/tools/yaml_batch_operator.py:            print("\n⚠️  ERRORS:")
./models/cometapi/tools/yaml_batch_operator.py:                print(f"  - {error}")
./models/cometapi/tools/yaml_batch_operator.py:            print(f"\n✅ Successfully modified {len(self.modified_files)} files")
./models/cometapi/tools/yaml_batch_operator.py:                print("💾 Backup files created with timestamp suffix")
./models/cometapi/tools/yaml_batch_operator.py:        print(f"❌ Error: Directory '{args.dir}' does not exist")
./models/cometapi/tools/yaml_batch_operator.py:        print(f"❌ Error: '{args.dir}' is not a directory")
./models/cometapi/tools/yaml_batch_operator.py:        print(f"❌ Error: Number of operators ({num_operators}) must match number of keys ({num_keys})")
./models/cometapi/tools/yaml_batch_operator.py:                    print(f"❌ Error: Remove operation with 'by-value' mode requires a value for key '{args.key[i]}'")
./models/cometapi/tools/yaml_batch_operator.py:                    print(f"❌ Error: Remove operation with 'by-index' mode requires an index for key '{args.key[i]}'")
./models/cometapi/tools/yaml_batch_operator.py:                    print(f"❌ Error: Operation '{op}' requires a value for key '{args.key[i]}'")
./models/cometapi/tools/yaml_batch_operator.py:            print(f"❌ Error: Empty key specified")
./models/cometapi/tools/yaml_batch_operator.py:        print("\n⏹️  Operation cancelled by user")
./models/cometapi/tools/yaml_batch_operator.py:        print(f"\n❌ Unexpected error: {e}")
./models/cometapi/tools/renew_model_list.py:            print(f"Warning: Unable to read file {yaml_file}: {e}")
./models/cometapi/tools/renew_model_list.py:            print(f"Warning: No 'model' field found in {yaml_file}")
./models/cometapi/tools/renew_model_list.py:                print(f"Error: Cannot rename {yaml_file.name} to {new_filename} - target file already exists")
./models/cometapi/tools/renew_model_list.py:                print(f"Renamed: {yaml_file.name} -> {new_filename} (model: {model_name})")
./models/cometapi/tools/renew_model_list.py:                print(f"Error renaming {yaml_file.name} to {new_filename}: {e}")
./models/cometapi/tools/renew_model_list.py:        print(f"Error checking filename for {yaml_file}: {e}")
./models/cometapi/tools/renew_model_list.py:        print(f"Error loading {yaml_file}: {e}")
./models/cometapi/tools/renew_model_list.py:        print(f"No models found for {model_type_dir}")
./models/cometapi/tools/renew_model_list.py:            print(f"Backed up existing file to {backup_file}")
./models/cometapi/tools/renew_model_list.py:        print(f"Updated {position_file}")
./models/cometapi/tools/renew_model_list.py:        print(f"Total models: {sum(len(models) for models in provider_groups.values())}")
./models/cometapi/tools/renew_model_list.py:        print(f"Error updating {position_file}: {e}")
./models/cometapi/tools/renew_model_list.py:        print(f"Models directory not found: {models_dir}")
./models/cometapi/tools/renew_model_list.py:    print(f"Scanning models directory: {models_dir}")
./models/cometapi/tools/renew_model_list.py:        print(f"\nProcessing {model_type} models...")
./models/cometapi/tools/renew_model_list.py:                print(f"Warning: Unable to process file {yaml_file}: {e}")
./models/cometapi/tools/renew_model_list.py:            print(f"No YAML files found in {model_type_dir}")
./models/cometapi/tools/renew_model_list.py:    print("\n✅ _position.yaml files updated successfully!")
./tools/linear/client/Linear.py:            print(f"[Linear] {message}")
./tools/gitlab/tools/gitlab_commits.py:            print(f"Error fetching data from GitLab: {e}")
./tools/gitlab/tools/gitlab_files.py:            print(f"Error fetching data from GitLab: {e}")
./tools/gitlab/tools/gitlab_files.py:            print(f"Error fetching project ID from GitLab: {e}")
./tools/gitlab/tools/gitlab_projects.py:            print(f"Error fetching data from GitLab: {e}")
./tools/gitlab/tools/gitlab_mergerequests.py:            print(f"Error fetching merge requests from GitLab: {e}")
./tools/google_calendar/tools/create_event.py:            print(f"Error building event data: {str(e)}")
./tools/tavily/tools/utils.py:            print(f"Failed to download image {image_url}: {str(e)}")
./tools/tavily/tools/utils.py:            print(f"Failed to download favicon {favicon_url}: {str(e)}")
./tools/slidespeak/tools/slidespeak_client.py:        print("\n=== REQUEST ===")
./tools/slidespeak/tools/slidespeak_client.py:        print(f"Method: {method}")
./tools/slidespeak/tools/slidespeak_client.py:        print(f"URL: {url}")
./tools/slidespeak/tools/slidespeak_client.py:        print(f"Headers: {json.dumps(headers, indent=2)}")
./tools/slidespeak/tools/slidespeak_client.py:            print(f"Body: {json.dumps(body, indent=2)}")
./tools/slidespeak/tools/slidespeak_client.py:            print(f"Files: {files}")
./tools/slidespeak/tools/slidespeak_client.py:        print("================\n")
./tools/slidespeak/tools/slidespeak_client.py:        print("\n=== RESPONSE ===")
./tools/slidespeak/tools/slidespeak_client.py:        print(f"Status Code: {response.status_code}")
./tools/slidespeak/tools/slidespeak_client.py:        print(f"Headers: {dict(response.headers)}")
./tools/slidespeak/tools/slidespeak_client.py:            print(f"Body: {json.dumps(response_json, indent=2)}")
./tools/slidespeak/tools/slidespeak_client.py:            print(f"Body (raw): {response.text}")
./tools/slidespeak/tools/slidespeak_client.py:        print("=================\n")
./tools/slidespeak/tools/slidespeak_client.py:            print("\n=== FETCH RESPONSE ===")
./tools/slidespeak/tools/slidespeak_client.py:            print(f"Status Code: {response.status_code}")
./tools/slidespeak/tools/slidespeak_client.py:            print(f"Headers: {dict(response.headers)}")
./tools/slidespeak/tools/slidespeak_client.py:            print(f"Content Length: {len(response.content)} bytes")
./tools/slidespeak/tools/slidespeak_client.py:            print("=======================\n")
./tools/outlook/tools/get_message.py:            print(f"Error getting attachments: {str(e)}")
./tools/outlook/tools/send_draft.py:            print(f"Error getting sent message: {str(e)}")
./tools/outlook/tools/list_draft.py:            print(f"Error getting attachment details: {str(e)}")
./tools/openai/provider/openai.py:            print(f"API test successful: {response.choices[0].message.content}")
./tools/judge0ce/provider/judge0ce.py:                tool_parameters={"source_code": "print('hello world')", "language_id": 71}
./tools/hap/tools/hap_api_utils.py:            print(
./tools/hap/tools/hap_api_utils.py:                print(f"[HAP DEBUG] Response: {json.dumps(safe_data, ensure_ascii=False)[:4096]}")
./tools/comfyui/tools/comfyui_workflow.py:    print(workflow)
./tools/comfyui/tools/comfyui_client.py:                    print("In K-Sampler -> Step: ", current_step, " of: ", data["max"])
./tools/comfyui/tools/comfyui_client.py:                            print(
./tools/comfyui/tools/comfyui_client.py:                        print(
./tools/pubmed/tools/pubmed_search.py:                    print(f"Too Many Requests, waiting for {self.sleep_time:.2f} seconds...")
@kurokobo commented on GitHub (Sep 6, 2025): @crazywoola @Yeuoly It seems that some plugins in this repository use `print()` for debugging purposes or error output. Standard output from `print()` is passed to the Plugin Daemon, which tries to parse it as JSON. However, most `print()` outputs are not JSON strings, so this leads to parsing errors, which are then output as errors in the logs of the Plugin Daemon container. Because of this, information intended only for debugging may leak into the logs. For example, the S3 data source plugin outputs credentials in plain text, as above screenshot, since it has `print(credentials)`. https://github.com/langgenius/dify-official-plugins/blob/205d2fb694c9cda6324c0fc66c9c20c05f59b2ae/datasources/aws_s3_storage/datasources/aws_s3_storage.py#L25 In the case of the Google Drive data source plugin, file information is outputted. It `print`s raw api response. https://github.com/langgenius/dify-official-plugins/blob/205d2fb694c9cda6324c0fc66c9c20c05f59b2ae/datasources/google_drive/datasources/google_drive.py#L70 <img width="1212" height="275" alt="Image" src="https://github.com/user-attachments/assets/244d9861-3f6b-4fca-a26c-c531f50b9e2e" /> While errors caused by `print()` in the Plugin Daemon do not affect the actual behavior of the plugin itself, the plugin still works as expected. That said, unnecessary errors should be suppressed, and since it could potentially lead to the leakage of sensitive information, I personally think `print()` shouldn’t be used in principle. What do you think? For now, I’ll open a PR for the S3 and Google Drive plugins, which I was able to test. Since there are quite a few plugins with `print()`, I’ll leave it up to you how far you want to go with it. ```bash $ find . -name '*.py' -print0 | xargs -0 grep 'print(' ./datasources/aws_s3_storage/datasources/aws_s3_storage.py: print(credentials) ./datasources/firecrawl_datasource/datasources/crawl.py: print(crawl_res) ./datasources/tavily_datasource/datasources/search_extract.py: print(f"Failed to extract content from {result.get('url', '')}: {str(e)}") ./datasources/tavily_datasource/datasources/search_extract.py: print(f"Error processing result {idx}: {str(e)}") ./datasources/notion_datasource/datasources/notion_datasource.py: print(online_document_res) ./datasources/google_drive/datasources/google_drive.py: print(results) ./datasources/confluence_datasource/provider/confluence_datasource.py: print(f"Expires in: {expires_in}") ./datasources/confluence_datasource/datasources/confluence_datasource.py: print(f"Fetching Confluence pages from: {url}") ./datasources/confluence_datasource/datasources/confluence_datasource.py: print(f"Authentication failed with 401. URL: {url}") ./datasources/confluence_datasource/datasources/confluence_datasource.py: print(f"Response: {response.text[:200]}") ./datasources/confluence_datasource/datasources/confluence_datasource.py: print(f"Request failed: {response.status_code} - {response.text[:200]}") ./models/huggingface_tei/models/text_embedding/text_embedding.py: print(extra_args) ./models/huggingface_tei/models/helper.py: print(f"Request failed, retry {attempt+1}/{max_retries}... ({e})") ./models/huggingface_tei/models/helper.py: print(f"Request failed, retry {attempt+1}/{max_retries}... ({e})") ./models/huggingface_tei/models/helper.py: print(f"Request failed, retry {attempt+1}/{max_retries}... ({e})") ./models/tongyi/models/text_embedding/text_embedding.py: print(f"Rate limit exceeded (429). Response: {response}") ./models/tongyi/models/rerank/rerank.py: print(ex) ./models/gemini/models/tests/test_document_filtering.py: print(f"Cache key: {cache_key}") ./models/gemini/models/tests/test_document_filtering.py: print(f"Cache exists before: {self.memory_cache.exists(cache_key)}") ./models/gemini/models/tests/test_document_filtering.py: print(f"After first upload - call count: {self.mock_client.files.upload.call_count}") ./models/gemini/models/tests/test_document_filtering.py: print(f"Cache exists after first: {self.memory_cache.exists(cache_key)}") ./models/gemini/models/tests/test_document_filtering.py: print(f"After second upload - call count: {self.mock_client.files.upload.call_count}") ./models/gemini/models/tests/test_document_filtering.py: print(f"{self.mock_client.files.upload.call_count=}") ./models/oci/models/llm/call_api.py: # print("body"*20, body) ./models/oci/models/text_embedding/call_api.py: # print("body"*20, body) ./models/sagemaker/provider/sagemaker.py: print(f"Error generating presigned URL: {e}") ./models/sagemaker/models/text_embedding/text_embedding.py: print("validate_credentials ok....") ./models/vertex_ai/models/llm/llm.py: # print(f"Warning: Unknown schema key '{key}' encountered. Ignoring.") ./models/cometapi/tools/yaml_batch_operator.py: print(f"[DRY RUN] Would perform on {yaml_file.relative_to(yaml_file.parents[3])}: {', '.join(completed_operations)}") ./models/cometapi/tools/yaml_batch_operator.py: print(f"✓ Modified {yaml_file.relative_to(yaml_file.parents[3])}: {', '.join(completed_operations)}") ./models/cometapi/tools/yaml_batch_operator.py: print(f"✗ {error_msg}") ./models/cometapi/tools/yaml_batch_operator.py: print(f"🔍 Scanning directory: {root_dir}") ./models/cometapi/tools/yaml_batch_operator.py: print(f"🎯 Operations to perform: {', '.join(op_summary)}") ./models/cometapi/tools/yaml_batch_operator.py: print("🧪 Running in DRY-RUN mode - no files will be modified") ./models/cometapi/tools/yaml_batch_operator.py: print("❌ No YAML files found matching criteria") ./models/cometapi/tools/yaml_batch_operator.py: print(f"📄 Found {len(yaml_files)} YAML files to process") ./models/cometapi/tools/yaml_batch_operator.py: print() ./models/cometapi/tools/yaml_batch_operator.py: print() ./models/cometapi/tools/yaml_batch_operator.py: print("=" * 60) ./models/cometapi/tools/yaml_batch_operator.py: print("📊 SUMMARY") ./models/cometapi/tools/yaml_batch_operator.py: print("=" * 60) ./models/cometapi/tools/yaml_batch_operator.py: print(f"Total files processed: {len(self.processed_files)}") ./models/cometapi/tools/yaml_batch_operator.py: print(f"Files modified: {len(self.modified_files)}") ./models/cometapi/tools/yaml_batch_operator.py: print(f"Errors encountered: {len(self.errors)}") ./models/cometapi/tools/yaml_batch_operator.py: print("\n⚠️ ERRORS:") ./models/cometapi/tools/yaml_batch_operator.py: print(f" - {error}") ./models/cometapi/tools/yaml_batch_operator.py: print(f"\n✅ Successfully modified {len(self.modified_files)} files") ./models/cometapi/tools/yaml_batch_operator.py: print("💾 Backup files created with timestamp suffix") ./models/cometapi/tools/yaml_batch_operator.py: print(f"❌ Error: Directory '{args.dir}' does not exist") ./models/cometapi/tools/yaml_batch_operator.py: print(f"❌ Error: '{args.dir}' is not a directory") ./models/cometapi/tools/yaml_batch_operator.py: print(f"❌ Error: Number of operators ({num_operators}) must match number of keys ({num_keys})") ./models/cometapi/tools/yaml_batch_operator.py: print(f"❌ Error: Remove operation with 'by-value' mode requires a value for key '{args.key[i]}'") ./models/cometapi/tools/yaml_batch_operator.py: print(f"❌ Error: Remove operation with 'by-index' mode requires an index for key '{args.key[i]}'") ./models/cometapi/tools/yaml_batch_operator.py: print(f"❌ Error: Operation '{op}' requires a value for key '{args.key[i]}'") ./models/cometapi/tools/yaml_batch_operator.py: print(f"❌ Error: Empty key specified") ./models/cometapi/tools/yaml_batch_operator.py: print("\n⏹️ Operation cancelled by user") ./models/cometapi/tools/yaml_batch_operator.py: print(f"\n❌ Unexpected error: {e}") ./models/cometapi/tools/renew_model_list.py: print(f"Warning: Unable to read file {yaml_file}: {e}") ./models/cometapi/tools/renew_model_list.py: print(f"Warning: No 'model' field found in {yaml_file}") ./models/cometapi/tools/renew_model_list.py: print(f"Error: Cannot rename {yaml_file.name} to {new_filename} - target file already exists") ./models/cometapi/tools/renew_model_list.py: print(f"Renamed: {yaml_file.name} -> {new_filename} (model: {model_name})") ./models/cometapi/tools/renew_model_list.py: print(f"Error renaming {yaml_file.name} to {new_filename}: {e}") ./models/cometapi/tools/renew_model_list.py: print(f"Error checking filename for {yaml_file}: {e}") ./models/cometapi/tools/renew_model_list.py: print(f"Error loading {yaml_file}: {e}") ./models/cometapi/tools/renew_model_list.py: print(f"No models found for {model_type_dir}") ./models/cometapi/tools/renew_model_list.py: print(f"Backed up existing file to {backup_file}") ./models/cometapi/tools/renew_model_list.py: print(f"Updated {position_file}") ./models/cometapi/tools/renew_model_list.py: print(f"Total models: {sum(len(models) for models in provider_groups.values())}") ./models/cometapi/tools/renew_model_list.py: print(f"Error updating {position_file}: {e}") ./models/cometapi/tools/renew_model_list.py: print(f"Models directory not found: {models_dir}") ./models/cometapi/tools/renew_model_list.py: print(f"Scanning models directory: {models_dir}") ./models/cometapi/tools/renew_model_list.py: print(f"\nProcessing {model_type} models...") ./models/cometapi/tools/renew_model_list.py: print(f"Warning: Unable to process file {yaml_file}: {e}") ./models/cometapi/tools/renew_model_list.py: print(f"No YAML files found in {model_type_dir}") ./models/cometapi/tools/renew_model_list.py: print("\n✅ _position.yaml files updated successfully!") ./tools/linear/client/Linear.py: print(f"[Linear] {message}") ./tools/gitlab/tools/gitlab_commits.py: print(f"Error fetching data from GitLab: {e}") ./tools/gitlab/tools/gitlab_files.py: print(f"Error fetching data from GitLab: {e}") ./tools/gitlab/tools/gitlab_files.py: print(f"Error fetching project ID from GitLab: {e}") ./tools/gitlab/tools/gitlab_projects.py: print(f"Error fetching data from GitLab: {e}") ./tools/gitlab/tools/gitlab_mergerequests.py: print(f"Error fetching merge requests from GitLab: {e}") ./tools/google_calendar/tools/create_event.py: print(f"Error building event data: {str(e)}") ./tools/tavily/tools/utils.py: print(f"Failed to download image {image_url}: {str(e)}") ./tools/tavily/tools/utils.py: print(f"Failed to download favicon {favicon_url}: {str(e)}") ./tools/slidespeak/tools/slidespeak_client.py: print("\n=== REQUEST ===") ./tools/slidespeak/tools/slidespeak_client.py: print(f"Method: {method}") ./tools/slidespeak/tools/slidespeak_client.py: print(f"URL: {url}") ./tools/slidespeak/tools/slidespeak_client.py: print(f"Headers: {json.dumps(headers, indent=2)}") ./tools/slidespeak/tools/slidespeak_client.py: print(f"Body: {json.dumps(body, indent=2)}") ./tools/slidespeak/tools/slidespeak_client.py: print(f"Files: {files}") ./tools/slidespeak/tools/slidespeak_client.py: print("================\n") ./tools/slidespeak/tools/slidespeak_client.py: print("\n=== RESPONSE ===") ./tools/slidespeak/tools/slidespeak_client.py: print(f"Status Code: {response.status_code}") ./tools/slidespeak/tools/slidespeak_client.py: print(f"Headers: {dict(response.headers)}") ./tools/slidespeak/tools/slidespeak_client.py: print(f"Body: {json.dumps(response_json, indent=2)}") ./tools/slidespeak/tools/slidespeak_client.py: print(f"Body (raw): {response.text}") ./tools/slidespeak/tools/slidespeak_client.py: print("=================\n") ./tools/slidespeak/tools/slidespeak_client.py: print("\n=== FETCH RESPONSE ===") ./tools/slidespeak/tools/slidespeak_client.py: print(f"Status Code: {response.status_code}") ./tools/slidespeak/tools/slidespeak_client.py: print(f"Headers: {dict(response.headers)}") ./tools/slidespeak/tools/slidespeak_client.py: print(f"Content Length: {len(response.content)} bytes") ./tools/slidespeak/tools/slidespeak_client.py: print("=======================\n") ./tools/outlook/tools/get_message.py: print(f"Error getting attachments: {str(e)}") ./tools/outlook/tools/send_draft.py: print(f"Error getting sent message: {str(e)}") ./tools/outlook/tools/list_draft.py: print(f"Error getting attachment details: {str(e)}") ./tools/openai/provider/openai.py: print(f"API test successful: {response.choices[0].message.content}") ./tools/judge0ce/provider/judge0ce.py: tool_parameters={"source_code": "print('hello world')", "language_id": 71} ./tools/hap/tools/hap_api_utils.py: print( ./tools/hap/tools/hap_api_utils.py: print(f"[HAP DEBUG] Response: {json.dumps(safe_data, ensure_ascii=False)[:4096]}") ./tools/comfyui/tools/comfyui_workflow.py: print(workflow) ./tools/comfyui/tools/comfyui_client.py: print("In K-Sampler -> Step: ", current_step, " of: ", data["max"]) ./tools/comfyui/tools/comfyui_client.py: print( ./tools/comfyui/tools/comfyui_client.py: print( ./tools/pubmed/tools/pubmed_search.py: print(f"Too Many Requests, waiting for {self.sleep_time:.2f} seconds...") ```
Author
Owner

@dosubot[bot] commented on GitHub (Sep 6, 2025):

You're absolutely right—using print() for debugging or error output in plugins is risky, especially since it can leak sensitive data like credentials and file metadata into container logs, and causes parsing errors in the Plugin Daemon logs. This is a widespread issue in the repository, and there isn't a unified logging framework or guideline in place; most plugins rely on print(), even when handling sensitive information example.

A better approach is to adopt a structured logging framework (like Python's logging module) across all plugins, with clear guidelines to avoid logging sensitive information. Some plugins, like Google Drive, partially use logging but still fall back to print(), so practices are inconsistent example.

It would be beneficial to update plugin templates and documentation to enforce best practices for logging and error output, and consider a codebase-wide refactor to replace print() with structured logging—especially in plugins that handle sensitive data. This would improve security, log quality, and operational reliability.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Join Discord Share on X

@dosubot[bot] commented on GitHub (Sep 6, 2025): <!-- Answer --> You're absolutely right—using print() for debugging or error output in plugins is risky, especially since it can leak sensitive data like credentials and file metadata into container logs, and causes parsing errors in the Plugin Daemon logs. This is a widespread issue in the repository, and there isn't a unified logging framework or guideline in place; most plugins rely on print(), even when handling sensitive information [example](https://github.com/langgenius/dify-official-plugins/blob/205d2fb694c9cda6324c0fc66c9c20c05f59b2ae/datasources/aws_s3_storage/datasources/aws_s3_storage.py). A better approach is to adopt a structured logging framework (like Python's logging module) across all plugins, with clear guidelines to avoid logging sensitive information. Some plugins, like Google Drive, partially use logging but still fall back to print(), so practices are inconsistent [example](https://github.com/langgenius/dify-official-plugins/blob/205d2fb694c9cda6324c0fc66c9c20c05f59b2ae/datasources/google_drive/datasources/google_drive.py). It would be beneficial to update plugin templates and documentation to enforce best practices for logging and error output, and consider a codebase-wide refactor to replace print() with structured logging—especially in plugins that handle sensitive data. This would improve security, log quality, and operational reliability. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/73de7004-563c-4f8f-aa5b-98e850e2f956?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/73de7004-563c-4f8f-aa5b-98e850e2f956?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/73de7004-563c-4f8f-aa5b-98e850e2f956?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/73de7004-563c-4f8f-aa5b-98e850e2f956?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/73de7004-563c-4f8f-aa5b-98e850e2f956?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/73de7004-563c-4f8f-aa5b-98e850e2f956?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/73de7004-563c-4f8f-aa5b-98e850e2f956?feedback_type=other)</sup>&nbsp;&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/langgenius/dify-official-plugins/issues/1673)
Author
Owner

@kurokobo commented on GitHub (Sep 6, 2025):

It takes some extra effort, but if we intentionally want to output certain strings to the container logs, I think it’s better to replace everything with logger as described in this page (which I wrote before 😃): https://docs.dify.ai/plugin-dev-en/0222-debugging-logs

@kurokobo commented on GitHub (Sep 6, 2025): It takes some extra effort, but if we intentionally want to output certain strings to the container logs, I think it’s better to replace everything with `logger` as described in this page (which I wrote before 😃): https://docs.dify.ai/plugin-dev-en/0222-debugging-logs
Author
Owner

@fdb02983rhy commented on GitHub (Sep 7, 2025):

Thanks for bringing this up

@fdb02983rhy commented on GitHub (Sep 7, 2025): Thanks for bringing this up
Author
Owner

@dosubot[bot] commented on GitHub (Sep 23, 2025):

Hi, @kurokobo. I'm Dosu, and I'm helping the dify-official-plugins team manage their backlog and am marking this issue as stale.

Issue Summary:

  • You raised a security concern about using print() for debugging leaking sensitive credentials in container logs.
  • This also caused JSON parsing errors in the Plugin Daemon.
  • You suggested replacing print() with structured logging (e.g., Python's logging module).
  • The maintainers agreed to refactor the codebase and update logging guidelines accordingly.
  • The issue was resolved with plans for a codebase-wide refactor and improved logging best practices.

Next Steps:

  • Please confirm if this issue is still relevant with the latest version of dify-official-plugins.
  • If it is, you can keep the discussion open by commenting; otherwise, I will automatically close this issue in 5 days.

Thanks for your understanding and contribution!

@dosubot[bot] commented on GitHub (Sep 23, 2025): Hi, @kurokobo. I'm [Dosu](https://dosu.dev), and I'm helping the dify-official-plugins team manage their backlog and am marking this issue as stale. **Issue Summary:** - You raised a security concern about using print() for debugging leaking sensitive credentials in container logs. - This also caused JSON parsing errors in the Plugin Daemon. - You suggested replacing print() with structured logging (e.g., Python's logging module). - The maintainers agreed to refactor the codebase and update logging guidelines accordingly. - The issue was resolved with plans for a codebase-wide refactor and improved logging best practices. **Next Steps:** - Please confirm if this issue is still relevant with the latest version of dify-official-plugins. - If it is, you can keep the discussion open by commenting; otherwise, I will automatically close this issue in 5 days. Thanks for your understanding and contribution!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify-official-plugins#628