Best and simplest tool for website change detection, web page monitoring, and website change alerts. Perfect for tracking content changes, price drops, restock alerts, and website defacement monitoring—all for free or enjoy our SaaS plan!
2045 matches across 16 categories. Click a row to expand file-level details.
| Severity | File | Line | Snippet |
|---|---|---|---|
| LOW | changedetectionio/pluggy_interface.py | 280 | def inject_datastore_into_plugins(datastore): |
| LOW | changedetectionio/pluggy_interface.py | 296 | def register_builtin_fetchers(): |
| LOW | changedetectionio/pluggy_interface.py | 64 | def get_itemprop_availability_override(self, content, fetcher_name, fetcher_instance, url, llm_intent=None): |
| LOW | changedetectionio/pluggy_interface.py | 244 | def load_plugins_from_directories(): |
| LOW | changedetectionio/pluggy_interface.py | 318 | def register_builtin_restock_plugins(): |
| LOW | changedetectionio/pluggy_interface.py | 336 | def collect_ui_edit_stats_extras(watch): |
| LOW | changedetectionio/pluggy_interface.py | 351 | def collect_fetcher_status_icons(fetcher_name): |
| LOW | changedetectionio/pluggy_interface.py | 371 | def get_itemprop_availability_from_plugin(content, fetcher_name, fetcher_instance, url, llm_intent=None): |
| LOW | changedetectionio/pluggy_interface.py | 576 | def get_plugin_template_paths(): |
| LOW | changedetectionio/pluggy_interface.py | 632 | def apply_update_handler_alter(update_handler, watch, datastore): |
| LOW | changedetectionio/worker.py | 771 | async def send_content_changed_notification(watch_uuid, notification_q, datastore): |
| LOW | changedetectionio/worker.py | 784 | async def send_filter_failure_notification(watch_uuid, notification_q, datastore): |
| LOW | changedetectionio/worker.py | 797 | async def send_step_failure_notification(watch_uuid, step_n, notification_q, datastore): |
| LOW | changedetectionio/worker.py | 31 | def set_watch_minitext_status(watch, status): |
| LOW | changedetectionio/rss_tools.py | 9 | def cdata_in_document_to_text(html_content: str, render_anchor_tag_content=False) -> str: |
| LOW | changedetectionio/worker_pool.py | 129 | async def start_single_async_worker(worker_id, update_q, notification_q, app, datastore, executor=None): |
| LOW | changedetectionio/worker_pool.py | 218 | def claim_uuid_for_processing(uuid, worker_id): |
| LOW | changedetectionio/worker_pool.py | 243 | def release_uuid_from_processing(uuid, worker_id): |
| LOW | changedetectionio/worker_pool.py | 281 | def is_watch_running_by_another_worker(watch_uuid, current_worker_id): |
| LOW | changedetectionio/worker_pool.py | 377 | def adjust_async_worker_count(new_count, update_q=None, notification_q=None, app=None, datastore=None): |
| LOW | changedetectionio/queue_handlers.py | 540 | def _emit_notification_signal(self, item: Dict[str, Any]): |
| LOW | changedetectionio/notification_service.py | 240 | def set_random_for_validation(self): |
| LOW | changedetectionio/notification_service.py | 258 | def add_rendered_diff_to_notification_vars(notification_scan_text:str, prev_snapshot:str, current_snapshot:str, word_dif |
| LOW | changedetectionio/notification_service.py | 323 | def set_basic_notification_vars(current_snapshot, prev_snapshot, watch, triggered_text, timestamp_changed=None): |
| LOW | changedetectionio/notification_service.py | 354 | def queue_notification_for_watch(self, n_object: NotificationContextData, watch, date_index_from=-2, date_index_to=- |
| LOW | changedetectionio/notification_service.py | 411 | def send_content_changed_notification(self, watch_uuid): |
| LOW | changedetectionio/notification_service.py | 455 | def send_filter_failure_notification(self, watch_uuid): |
| LOW | changedetectionio/notification_service.py | 502 | def send_step_failure_notification(self, watch_uuid, step_n): |
| LOW | changedetectionio/notification_service.py | 550 | def create_notification_service(datastore, notification_q): |
| LOW | changedetectionio/validate_url.py | 112 | def is_url_private_or_parser_confused(url): |
| LOW | changedetectionio/__init__.py | 516 | def queue_watches_for_recheck(datastore, iteration): |
| LOW | changedetectionio/forms.py | 223 | def validate_time_between_check_has_values(form): |
| LOW | changedetectionio/forms.py | 802 | # def validate_notification_urls(self, field): |
| LOW | changedetectionio/html_tools.py | 122 | def perl_style_slash_enclosed_regex_to_options(regex): |
| LOW | changedetectionio/html_tools.py | 171 | def subtractive_xpath_selector(selectors: List[str], html_content: str) -> str: |
| LOW | changedetectionio/html_tools.py | 440 | def _get_stripped_text_from_json_match(match): |
| LOW | changedetectionio/html_tools.py | 461 | def extract_json_blob_from_html(content, ensure_is_ldjson_info_type, json_filter): |
| LOW | changedetectionio/html_tools.py | 638 | def cdata_in_document_to_text(html_content: str, render_anchor_tag_content=False) -> str: |
| LOW | changedetectionio/html_tools.py | 728 | def workarounds_for_obfuscations(content): |
| LOW | changedetectionio/auth_decorator.py | 16 | def login_optionally_required(func): |
| LOW | changedetectionio/flask_app.py | 139 | def _configure_plugin_templates(): |
| LOW | changedetectionio/flask_app.py | 238 | def _get_watch_queue_position(watch_obj): |
| LOW | changedetectionio/flask_app.py | 244 | def _get_current_worker_count(): |
| LOW | changedetectionio/flask_app.py | 526 | def inject_llm_features_disabled(): |
| LOW | changedetectionio/flask_app.py | 704 | def before_request_handle_cookie_x_settings(): |
| LOW | changedetectionio/flask_app.py | 1112 | def ticker_thread_check_time_launch_checks(): |
| LOW | changedetectionio/llm/prompt_builder.py | 117 | def build_preview_system_prompt() -> str: |
| LOW | changedetectionio/llm/prompt_builder.py | 134 | def build_change_summary_prompt(diff: str, custom_prompt: str, |
| LOW | changedetectionio/llm/prompt_builder.py | 158 | def build_change_summary_system_prompt() -> str: |
| LOW | changedetectionio/llm/prompt_builder.py | 200 | def build_setup_system_prompt() -> str: |
| LOW | changedetectionio/llm/evaluator.py | 298 | def get_global_token_budget_month(datastore=None) -> int: |
| LOW | changedetectionio/llm/evaluator.py | 490 | def get_effective_summary_prompt(watch, datastore) -> str: |
| LOW | changedetectionio/llm/evaluator.py | 153 | def apply_local_token_multiplier(base_max_tokens: int, llm_cfg: dict) -> int: |
| LOW | changedetectionio/llm/evaluator.py | 378 | def is_global_token_budget_exceeded(datastore) -> bool: |
| LOW | changedetectionio/llm/evaluator.py | 502 | def compute_summary_cache_key(diff_text: str, prompt: str) -> str: |
| LOW | changedetectionio/llm/evaluator.py | 543 | def build_summary_cache_prompt(effective_prompt: str, max_summary_tokens: int, |
| LOW | changedetectionio/browser_steps/browser_steps.py | 11 | def browser_steps_get_valid_steps(browser_steps: list): |
| LOW | changedetectionio/browser_steps/browser_steps.py | 148 | async def action_click_element_containing_text(self, selector=None, value=''): |
| LOW | changedetectionio/browser_steps/browser_steps.py | 158 | async def action_click_element_containing_text_if_exists(self, selector=None, value=''): |
| LOW | changedetectionio/browser_steps/browser_steps.py | 170 | async def action_enter_text_in_field(self, selector, value): |
| 736 more matches not shown… | |||
| Severity | File | Line | Snippet |
|---|---|---|---|
| MEDIUM | changedetectionio/__init__.py | 24 | # ============================================================================== |
| MEDIUM | changedetectionio/__init__.py | 26 | # ============================================================================== |
| MEDIUM | changedetectionio/__init__.py | 61 | # ============================================================================== |
| MEDIUM | changedetectionio/test_cli_opts.sh | 55 | # ============================================================================= |
| MEDIUM | changedetectionio/test_cli_opts.sh | 57 | # ============================================================================= |
| MEDIUM | changedetectionio/test_cli_opts.sh | 198 | # ============================================================================= |
| MEDIUM | changedetectionio/test_cli_opts.sh | 200 | # ============================================================================= |
| MEDIUM | changedetectionio/llm/evaluator.py | 289 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/llm/evaluator.py | 291 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/llm/evaluator.py | 486 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/llm/evaluator.py | 488 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/llm/evaluator.py | 647 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/llm/evaluator.py | 649 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/llm/evaluator.py | 703 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/llm/evaluator.py | 705 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/llm/evaluator.py | 187 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/llm/evaluator.py | 189 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/llm/evaluator.py | 230 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/llm/evaluator.py | 232 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/llm/evaluator.py | 396 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/llm/evaluator.py | 398 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_security.py | 729 | # ------------------------------------------------------------------ |
| MEDIUM | changedetectionio/tests/test_security.py | 732 | # ------------------------------------------------------------------ |
| MEDIUM | changedetectionio/tests/test_security.py | 741 | # ------------------------------------------------------------------ |
| MEDIUM | changedetectionio/tests/test_security.py | 744 | # ------------------------------------------------------------------ |
| MEDIUM | changedetectionio/tests/test_security.py | 754 | # ------------------------------------------------------------------ |
| MEDIUM | changedetectionio/tests/test_security.py | 758 | # ------------------------------------------------------------------ |
| MEDIUM | changedetectionio/tests/test_security.py | 775 | # ------------------------------------------------------------------ |
| MEDIUM | changedetectionio/tests/test_security.py | 778 | # ------------------------------------------------------------------ |
| MEDIUM | changedetectionio/tests/test_security.py | 865 | # --------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_security.py | 867 | # --------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_security.py | 874 | # --------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_security.py | 876 | # --------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_security.py | 888 | # --------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_security.py | 890 | # --------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_security.py | 894 | # --------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_security.py | 896 | # --------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_security.py | 906 | # --------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_security.py | 908 | # --------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_security.py | 692 | # ------------------------------------------------------------------ |
| MEDIUM | changedetectionio/tests/test_security.py | 694 | # ------------------------------------------------------------------ |
| MEDIUM | changedetectionio/tests/test_security.py | 711 | # ------------------------------------------------------------------ |
| MEDIUM | changedetectionio/tests/test_security.py | 714 | # ------------------------------------------------------------------ |
| MEDIUM | changedetectionio/tests/test_security.py | 921 | # --------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_security.py | 924 | # --------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_llm_group_overrides.py | 74 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_llm_group_overrides.py | 76 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_llm_group_overrides.py | 144 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_llm_group_overrides.py | 146 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_llm_group_overrides.py | 210 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_llm_group_overrides.py | 212 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_llm_group_overrides.py | 244 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_llm_group_overrides.py | 246 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_llm_group_overrides.py | 299 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_llm_group_overrides.py | 301 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_llm_group_overrides.py | 348 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_llm_group_overrides.py | 350 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_llm_group_overrides.py | 23 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_llm_group_overrides.py | 25 | # --------------------------------------------------------------------------- |
| MEDIUM | changedetectionio/tests/test_llm_group_overrides.py | 50 | # --------------------------------------------------------------------------- |
| 124 more matches not shown… | |||
| Severity | File | Line | Snippet |
|---|---|---|---|
| HIGH | docs/api-spec.yaml | 1311 | -H "x-api-key: YOUR_API_KEY" |
| HIGH | docs/api-spec.yaml | 1315 | -H "x-api-key: YOUR_API_KEY" |
| HIGH | docs/api-spec.yaml | 1319 | -H "x-api-key: YOUR_API_KEY" |
| HIGH | docs/api-spec.yaml | 1324 | headers = {'x-api-key': 'YOUR_API_KEY'} |
| HIGH | docs/api-spec.yaml | 2023 | -H "x-api-key: YOUR_API_KEY" \ |
| HIGH | docs/api-spec.yaml | 2029 | -H "x-api-key: YOUR_API_KEY" \ |
| HIGH | docs/api-spec.yaml | 2035 | -H "x-api-key: YOUR_API_KEY" \ |
| HIGH | docs/api-spec.yaml | 2043 | 'x-api-key': 'YOUR_API_KEY', |
| HIGH | docs/api-spec.yaml | 29 | For example: `x-api-key: YOUR_API_KEY` |
| HIGH | docs/api-spec.yaml | 162 | -H "x-api-key: YOUR_API_KEY" \ |
| HIGH | docs/api-spec.yaml | 196 | -H "x-api-key: YOUR_API_KEY" \ |
| HIGH | docs/api-spec.yaml | 215 | -H "x-api-key: YOUR_API_KEY" |
| HIGH | docs/api-spec.yaml | 239 | -H "x-api-key: YOUR_API_KEY" \ |
| HIGH | docs/api-spec.yaml | 255 | -H "x-api-key: YOUR_API_KEY" |
| HIGH | docs/api-spec.yaml | 895 | -H "x-api-key: YOUR_API_KEY" |
| HIGH | docs/api-spec.yaml | 900 | headers = {'x-api-key': 'YOUR_API_KEY'} |
| HIGH | docs/api-spec.yaml | 968 | -H "x-api-key: YOUR_API_KEY" \ |
| HIGH | docs/api-spec.yaml | 983 | 'x-api-key': 'YOUR_API_KEY', |
| HIGH | docs/api-spec.yaml | 1032 | -H "x-api-key: YOUR_API_KEY" |
| HIGH | docs/api-spec.yaml | 1037 | headers = {'x-api-key': 'YOUR_API_KEY'} |
| HIGH | docs/api-spec.yaml | 1094 | -H "x-api-key: YOUR_API_KEY" \ |
| HIGH | docs/api-spec.yaml | 1106 | 'x-api-key': 'YOUR_API_KEY', |
| HIGH | docs/api-spec.yaml | 1152 | -H "x-api-key: YOUR_API_KEY" |
| HIGH | docs/api-spec.yaml | 1157 | headers = {'x-api-key': 'YOUR_API_KEY'} |
| HIGH | docs/api-spec.yaml | 1190 | -H "x-api-key: YOUR_API_KEY" |
| HIGH | docs/api-spec.yaml | 1195 | headers = {'x-api-key': 'YOUR_API_KEY'} |
| HIGH | docs/api-spec.yaml | 1232 | -H "x-api-key: YOUR_API_KEY" |
| HIGH | docs/api-spec.yaml | 1237 | headers = {'x-api-key': 'YOUR_API_KEY'} |
| HIGH | docs/api-spec.yaml | 1515 | -H "x-api-key: YOUR_API_KEY" \ |
| HIGH | docs/api-spec.yaml | 1521 | headers = {'x-api-key': 'YOUR_API_KEY'} |
| HIGH | docs/api-spec.yaml | 1555 | -H "x-api-key: YOUR_API_KEY" |
| HIGH | docs/api-spec.yaml | 1560 | headers = {'x-api-key': 'YOUR_API_KEY'} |
| HIGH | docs/api-spec.yaml | 1594 | -H "x-api-key: YOUR_API_KEY" \ |
| HIGH | docs/api-spec.yaml | 1604 | 'x-api-key': 'YOUR_API_KEY', |
| HIGH | docs/api-spec.yaml | 1644 | -H "x-api-key: YOUR_API_KEY" |
| HIGH | docs/api-spec.yaml | 1649 | headers = {'x-api-key': 'YOUR_API_KEY'} |
| HIGH | docs/api-spec.yaml | 1696 | -H "x-api-key: YOUR_API_KEY" \ |
| HIGH | docs/api-spec.yaml | 1707 | 'x-api-key': 'YOUR_API_KEY', |
| HIGH | docs/api-spec.yaml | 1747 | -H "x-api-key: YOUR_API_KEY" |
| HIGH | docs/api-spec.yaml | 1752 | headers = {'x-api-key': 'YOUR_API_KEY'} |
| HIGH | docs/api-spec.yaml | 1779 | -H "x-api-key: YOUR_API_KEY" |
| HIGH | docs/api-spec.yaml | 1784 | headers = {'x-api-key': 'YOUR_API_KEY'} |
| HIGH | docs/api-spec.yaml | 1804 | -H "x-api-key: YOUR_API_KEY" \ |
| HIGH | docs/api-spec.yaml | 1817 | 'x-api-key': 'YOUR_API_KEY', |
| HIGH | docs/api-spec.yaml | 1858 | -H "x-api-key: YOUR_API_KEY" \ |
| HIGH | docs/api-spec.yaml | 1870 | 'x-api-key': 'YOUR_API_KEY', |
| HIGH | docs/api-spec.yaml | 1906 | -H "x-api-key: YOUR_API_KEY" \ |
| HIGH | docs/api-spec.yaml | 1918 | 'x-api-key': 'YOUR_API_KEY', |
| HIGH | docs/api-spec.yaml | 1951 | -H "x-api-key: YOUR_API_KEY" |
| HIGH | docs/api-spec.yaml | 1956 | headers = {'x-api-key': 'YOUR_API_KEY'} |
| HIGH | docs/api-spec.yaml | 2122 | -H "x-api-key: YOUR_API_KEY" |
| HIGH | docs/api-spec.yaml | 2127 | headers = {'x-api-key': 'YOUR_API_KEY'} |
| HIGH | docs/api_v1/index.html | 974 | <span class="token operator">-</span>H <span class="token string">"x-api-key: YOUR_API_KEY"</span> |
| HIGH | docs/api_v1/index.html | 978 | <span class="token operator">-</span>H <span class="token string">"x-api-key: YOUR_API_KEY"</span> |
| HIGH | docs/api_v1/index.html | 982 | <span class="token operator">-</span>H <span class="token string">"x-api-key: YOUR_API_KEY"</span> |
| HIGH | docs/api_v1/index.html | 471 | <p>For example: <code>x-api-key: YOUR_API_KEY</code></p> |
| HIGH | docs/api_v1/index.html | 473 | <p>For example: <code>x-api-key: YOUR_API_KEY</code></p> |
| HIGH | docs/api_v1/index.html | 495 | <span class="token operator">-</span>H <span class="token string">"x-api-key: YOUR_API_KEY"</span> |
| HIGH | docs/api_v1/index.html | 659 | <span class="token operator">-</span>H <span class="token string">"x-api-key: YOUR_API_KEY"</span> |
| HIGH | docs/api_v1/index.html | 803 | <span class="token operator">-</span>H <span class="token string">"x-api-key: YOUR_API_KEY"</span> |
| 27 more matches not shown… | |||
| Severity | File | Line | Snippet |
|---|---|---|---|
| MEDIUM | changedetectionio/pluggy_interface.py | 271 | print(f"Error loading plugin {module_name}: {e}") |
| LOW | changedetectionio/pluggy_interface.py | 332 | except Exception as e: |
| LOW | changedetectionio/pluggy_interface.py | 547 | except Exception as e: |
| LOW | changedetectionio/pluggy_interface.py | 571 | except Exception as e: |
| LOW | changedetectionio/pluggy_interface.py | 688 | except Exception as e: |
| LOW | changedetectionio/worker.py | 780 | except Exception as e: |
| LOW | changedetectionio/worker.py | 793 | except Exception as e: |
| LOW | changedetectionio/worker.py | 806 | except Exception as e: |
| LOW | changedetectionio/worker.py | 120 | except Exception as e: |
| LOW | changedetectionio/worker.py | 135 | except Exception as health_e: |
| LOW | changedetectionio/worker.py | 403 | except Exception as e: |
| LOW | changedetectionio/worker.py | 511 | except Exception as e: |
| LOW | changedetectionio/worker.py | 567 | except Exception as _fe: |
| LOW | changedetectionio/worker.py | 584 | except Exception as e: |
| LOW | changedetectionio/worker.py | 602 | except Exception as e: |
| LOW | changedetectionio/worker.py | 615 | except Exception as e: |
| LOW | changedetectionio/worker.py | 642 | except Exception as e: |
| LOW | changedetectionio/worker.py | 665 | except Exception as e: |
| LOW | changedetectionio/worker.py | 689 | except Exception as cleanup_error: |
| LOW | changedetectionio/worker.py | 702 | except Exception as finalize_error: |
| LOW | changedetectionio/worker.py | 714 | except Exception as release_error: |
| LOW | changedetectionio/is_safe_url.py | 110 | except Exception as e: |
| LOW | changedetectionio/rss_tools.py | 201 | except Exception as e: |
| LOW | changedetectionio/worker_pool.py | 78 | except Exception as e: |
| LOW | changedetectionio/worker_pool.py | 124 | except Exception as e: |
| LOW | changedetectionio/worker_pool.py | 157 | except Exception as e: |
| LOW | changedetectionio/worker_pool.py | 188 | except Exception as e: |
| LOW | changedetectionio/worker_pool.py | 298 | except Exception as uuid_e: |
| LOW | changedetectionio/worker_pool.py | 322 | except Exception as e: |
| LOW | changedetectionio/worker_pool.py | 330 | except Exception as health_e: |
| LOW | changedetectionio/worker_pool.py | 336 | except Exception: |
| LOW | changedetectionio/worker_pool.py | 367 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 248 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 257 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 267 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 537 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 549 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 60 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 79 | except Exception as notif_e: |
| LOW | changedetectionio/queue_handlers.py | 91 | except Exception as signal_e: |
| LOW | changedetectionio/queue_handlers.py | 97 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 121 | except Exception as signal_e: |
| LOW | changedetectionio/queue_handlers.py | 131 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 157 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 200 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 210 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 223 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 297 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 332 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 373 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 384 | except Exception: |
| LOW | changedetectionio/queue_handlers.py | 401 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 409 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 435 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 457 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 480 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 495 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 515 | except Exception as e: |
| LOW | changedetectionio/queue_handlers.py | 524 | except Exception as e: |
| LOW | changedetectionio/favicon_utils.py | 31 | except Exception: |
| 257 more matches not shown… | |||
| Severity | File | Line | Snippet |
|---|---|---|---|
| LOW | changedetectionio/worker.py | 328 | |
| LOW | changedetectionio/worker.py | 404 | |
| LOW | changedetectionio/worker.py | 451 | |
| LOW | changedetectionio/queue_handlers.py | 3 | |
| LOW | changedetectionio/gc_cleanup.py | 9 | |
| LOW | changedetectionio/validate_url.py | 3 | |
| LOW | changedetectionio/forms.py | 15 | |
| LOW | changedetectionio/forms.py | 508 | |
| LOW | changedetectionio/auth_decorator.py | 3 | |
| LOW | changedetectionio/auth_decorator.py | 4 | |
| LOW | changedetectionio/time_handler.py | 1 | |
| LOW | changedetectionio/languages.py | 5 | |
| LOW | changedetectionio/llm/evaluator.py | 34 | |
| LOW | …angedetectionio/content_fetchers/screenshot_handler.py | 9 | |
| LOW | changedetectionio/content_fetchers/__init__.py | 4 | |
| LOW | changedetectionio/content_fetchers/__init__.py | 11 | |
| LOW | changedetectionio/content_fetchers/__init__.py | 30 | |
| LOW | changedetectionio/content_fetchers/__init__.py | 105 | |
| LOW | changedetectionio/content_fetchers/__init__.py | 98 | |
| LOW | changedetectionio/content_fetchers/__init__.py | 101 | |
| LOW | changedetectionio/content_fetchers/puppeteer.py | 10 | |
| LOW | changedetectionio/content_fetchers/requests.py | 3 | |
| LOW | changedetectionio/content_fetchers/requests.py | 12 | |
| LOW | changedetectionio/content_fetchers/requests.py | 40 | |
| LOW | changedetectionio/content_fetchers/requests.py | 40 | |
| LOW | changedetectionio/content_fetchers/requests.py | 40 | |
| LOW | …angedetectionio/content_fetchers/webdriver_selenium.py | 4 | |
| LOW | …angedetectionio/content_fetchers/webdriver_selenium.py | 33 | |
| LOW | …angedetectionio/content_fetchers/webdriver_selenium.py | 34 | |
| LOW | changedetectionio/notification/handler.py | 309 | |
| LOW | changedetectionio/notification/handler.py | 311 | |
| LOW | …angedetectionio/notification/apprise_plugin/discord.py | 61 | |
| LOW | …angedetectionio/notification/apprise_plugin/discord.py | 61 | |
| LOW | …ctionio/notification/apprise_plugin/custom_handlers.py | 53 | |
| LOW | …ctionio/notification/apprise_plugin/custom_handlers.py | 63 | |
| LOW | changedetectionio/tests/test_rss_reader_mode.py | 3 | |
| LOW | changedetectionio/tests/test_rss_reader_mode.py | 7 | |
| LOW | changedetectionio/tests/test_rss_reader_mode.py | 7 | |
| LOW | changedetectionio/tests/test_rss_reader_mode.py | 7 | |
| LOW | changedetectionio/tests/test_rss_reader_mode.py | 7 | |
| LOW | changedetectionio/tests/test_rss_reader_mode.py | 7 | |
| LOW | changedetectionio/tests/test_queue_handler.py | 4 | |
| LOW | changedetectionio/tests/test_queue_handler.py | 4 | |
| LOW | changedetectionio/tests/test_queue_handler.py | 5 | |
| LOW | changedetectionio/tests/test_preview_endpoints.py | 3 | |
| LOW | changedetectionio/tests/test_preview_endpoints.py | 5 | |
| LOW | changedetectionio/tests/test_preview_endpoints.py | 5 | |
| LOW | changedetectionio/tests/test_preview_endpoints.py | 5 | |
| LOW | changedetectionio/tests/test_backend.py | 6 | |
| LOW | changedetectionio/tests/test_backend.py | 6 | |
| LOW | changedetectionio/tests/test_api_openapi.py | 9 | |
| LOW | changedetectionio/tests/test_api_openapi.py | 12 | |
| LOW | changedetectionio/tests/test_api_openapi.py | 12 | |
| LOW | changedetectionio/tests/test_access_control.py | 1 | |
| LOW | changedetectionio/tests/test_access_control.py | 3 | |
| LOW | changedetectionio/tests/test_ignore_regex_text.py | 3 | |
| LOW | changedetectionio/tests/test_security.py | 3 | |
| LOW | changedetectionio/tests/test_security.py | 11 | |
| LOW | changedetectionio/tests/test_security.py | 390 | |
| LOW | changedetectionio/tests/test_ignore.py | 3 | |
| 239 more matches not shown… | |||
| Severity | File | Line | Snippet |
|---|---|---|---|
| MEDIUM | .github/workflows/test-stack-reusable-workflow.yml | 416 | # Create a watch via API through nginx proxy subpath |
| MEDIUM | .github/workflows/test-stack-reusable-workflow.yml | 741 | # Create a watch with tag "github-group-test" via API |
| MEDIUM | .github/workflows/test-stack-reusable-workflow.yml | 755 | # Create a specific test URL watch |
| MEDIUM | changedetectionio/is_safe_url.py | 93 | # Create a URL adapter bound to the server name |
| MEDIUM | changedetectionio/worker_pool.py | 52 | # Create a new event loop for this thread |
| MEDIUM | changedetectionio/gc_cleanup.py | 53 | # Create a new thread local object to encourage cleanup of old ones |
| MEDIUM | changedetectionio/__init__.py | 309 | # Create the datadir if it doesnt exist |
| MEDIUM | changedetectionio/test_cli_opts.sh | 148 | # Create a watch using CLI, then recheck it |
| MEDIUM | changedetectionio/flask_app.py | 148 | # Create a ChoiceLoader that searches app templates first, then plugin templates |
| MEDIUM | changedetectionio/notification/handler.py | 110 | # Define the mapping between your placeholders and markdown markers |
| MEDIUM | changedetectionio/notification/handler.py | 134 | # Define the mapping between your placeholders and markdown markers |
| MEDIUM | changedetectionio/tests/test_security.py | 960 | # Create a real watch and trigger a check so we have a valid backup structure |
| MEDIUM | changedetectionio/tests/test_rss_group.py | 47 | # Create a tag/group |
| MEDIUM | changedetectionio/tests/test_rss_group.py | 160 | # Create a tag with no watches |
| MEDIUM | changedetectionio/tests/test_rss_group.py | 197 | # Create a tag |
| MEDIUM | changedetectionio/tests/test_api_security.py | 50 | # Create a valid watch first |
| MEDIUM | changedetectionio/tests/test_api_security.py | 333 | # Create a watch |
| MEDIUM | changedetectionio/tests/test_basic_socketio.py | 24 | # Create a test client for SocketIO |
| MEDIUM | changedetectionio/tests/test_commit_persistence.py | 28 | # Create a watch |
| MEDIUM | changedetectionio/tests/test_commit_persistence.py | 519 | # Create a tag |
| MEDIUM | …ctionio/tests/test_api_notification_urls_validation.py | 128 | # Create a tag |
| MEDIUM | changedetectionio/tests/test_backup.py | 138 | # Create a full backup |
| MEDIUM | changedetectionio/tests/test_llm_api_key_security.py | 618 | # Create a real watch — required to exercise llm_clear_summary_cache's |
| MEDIUM | changedetectionio/tests/test_llm_token_budget.py | 67 | # Create a watch via API |
| MEDIUM | changedetectionio/tests/test_tag_url_match.py | 22 | # Create a tag with a URL match pattern |
| MEDIUM | changedetectionio/tests/test_api.py | 65 | # Create a watch |
| MEDIUM | changedetectionio/tests/test_api.py | 557 | # Create a watch |
| MEDIUM | changedetectionio/tests/test_api.py | 936 | # Create a watch in restock_diff mode WITH processor_config in the POST body (matches the API docs example) |
| MEDIUM | changedetectionio/tests/test_api.py | 1120 | # Create a watch |
| MEDIUM | …detectionio/tests/test_settings_tag_force_reprocess.py | 99 | # Create a tag |
| MEDIUM | …detectionio/tests/test_settings_tag_force_reprocess.py | 169 | # Create a tag |
| MEDIUM | changedetectionio/tests/test_jinja2.py | 250 | # Create a large input string (over 10MB) |
| MEDIUM | changedetectionio/tests/test_jinja2.py | 286 | # Create a template with the dangerous pattern |
| MEDIUM | changedetectionio/tests/test_api_tags.py | 100 | # Create a watch with the tag and check it matches UUID |
| MEDIUM | changedetectionio/tests/test_api_tags.py | 188 | # Create a tag with processor_config_restock_diff in a single POST (issue #3966) |
| MEDIUM | changedetectionio/tests/test_llm_change_summary.py | 78 | # Create a tag with llm_change_summary |
| MEDIUM | changedetectionio/tests/unit/test_watch_model.py | 224 | # Create a watch with large datastore (many watches) |
| MEDIUM | changedetectionio/tests/unit/test_conditions.py | 14 | # Create a temporary directory for the test datastore |
| MEDIUM | changedetectionio/realtime/socket_server.py | 158 | # Create a simplified watch data object to send to clients |
| MEDIUM | changedetectionio/realtime/socket_server.py | 345 | # Create a dedicated signal handler that will receive signals and emit them to clients |
| MEDIUM | changedetectionio/processors/__init__.py | 457 | # Create a processor instance to access config methods |
| MEDIUM | changedetectionio/processors/base.py | 33 | # Create a stable snapshot of the watch for processing |
| MEDIUM | changedetectionio/conditions/blueprint.py | 43 | # Create a temporary watch data structure with this single rule |
| MEDIUM | changedetectionio/conditions/blueprint.py | 54 | # Create a temporary application data structure for the rule check |
| MEDIUM | changedetectionio/conditions/__init__.py | 29 | # Define the extended operations dictionary |
| MEDIUM | changedetectionio/conditions/__init__.py | 131 | # Create the ruleset |
| MEDIUM | changedetectionio/model/__init__.py | 440 | # Create a cached version if it doesn't exist |
| MEDIUM | changedetectionio/model/Watch.py | 943 | # Create a smaller intermediate image (to reduce memory usage) |
| MEDIUM | changedetectionio/api/Watch.py | 73 | # Create a dict copy for JSON response (with lock for thread safety) |
| MEDIUM | changedetectionio/blueprint/ui/edit.py | 135 | # Create a processor instance to access config methods |
| MEDIUM | changedetectionio/blueprint/browser_steps/__init__.py | 408 | # Create the response with ETag |
| MEDIUM | changedetectionio/blueprint/backups/__init__.py | 61 | # Create a list file with just the URLs, so it's easier to port somewhere else in the future |
| MEDIUM | changedetectionio/store/__init__.py | 54 | # Initialize parent class |
| Severity | File | Line | Snippet |
|---|---|---|---|
| LOW | changedetectionio/pluggy_interface.py | 244 | |
| LOW | changedetectionio/pluggy_interface.py | 371 | |
| LOW | changedetectionio/pluggy_interface.py | 576 | |
| LOW | changedetectionio/worker.py | 46 | |
| LOW | changedetectionio/worker_pool.py | 129 | |
| LOW | changedetectionio/worker_pool.py | 449 | |
| LOW | changedetectionio/queue_handlers.py | 227 | |
| LOW | changedetectionio/queue_handlers.py | 271 | |
| LOW | changedetectionio/queue_handlers.py | 301 | |
| LOW | changedetectionio/queue_handlers.py | 336 | |
| LOW | changedetectionio/gc_cleanup.py | 12 | |
| LOW | changedetectionio/__init__.py | 181 | |
| LOW | changedetectionio/forms.py | 124 | |
| LOW | changedetectionio/html_tools.py | 226 | |
| LOW | changedetectionio/html_tools.py | 268 | |
| LOW | changedetectionio/html_tools.py | 461 | |
| LOW | changedetectionio/html_tools.py | 571 | |
| LOW | changedetectionio/html_tools.py | 759 | |
| LOW | changedetectionio/auth_decorator.py | 16 | |
| LOW | changedetectionio/auth_decorator.py | 23 | |
| LOW | changedetectionio/custom_queue.py | 91 | |
| LOW | changedetectionio/custom_queue.py | 155 | |
| LOW | changedetectionio/custom_queue.py | 249 | |
| LOW | changedetectionio/custom_queue.py | 414 | |
| LOW | changedetectionio/custom_queue.py | 496 | |
| LOW | changedetectionio/languages.py | 78 | |
| LOW | changedetectionio/flask_app.py | 464 | |
| LOW | changedetectionio/flask_app.py | 1058 | |
| LOW | changedetectionio/flask_app.py | 1112 | |
| LOW | changedetectionio/flask_app.py | 532 | |
| LOW | changedetectionio/flask_app.py | 746 | |
| LOW | changedetectionio/flask_app.py | 947 | |
| LOW | changedetectionio/llm/client.py | 57 | |
| LOW | changedetectionio/content_fetchers/__init__.py | 39 | |
| LOW | changedetectionio/content_fetchers/requests.py | 24 | |
| LOW | …angedetectionio/content_fetchers/webdriver_selenium.py | 63 | |
| LOW | …angedetectionio/content_fetchers/webdriver_selenium.py | 81 | |
| LOW | changedetectionio/content_fetchers/base.py | 165 | |
| LOW | changedetectionio/notification/handler.py | 153 | |
| LOW | changedetectionio/notification/handler.py | 209 | |
| LOW | changedetectionio/notification/handler.py | 307 | |
| LOW | …angedetectionio/notification/apprise_plugin/discord.py | 56 | |
| LOW | …angedetectionio/notification/apprise_plugin/discord.py | 200 | |
| LOW | changedetectionio/tests/conftest.py | 43 | |
| LOW | changedetectionio/tests/conftest.py | 404 | |
| LOW | changedetectionio/tests/conftest.py | 439 | |
| LOW | changedetectionio/tests/util.py | 245 | |
| LOW | changedetectionio/tests/util.py | 257 | |
| LOW | changedetectionio/tests/test_history_consistency.py | 13 | |
| LOW | changedetectionio/tests/test_basic_socketio.py | 13 | |
| LOW | …ngedetectionio/tests/unit/test_auth_decorator_order.py | 43 | |
| LOW | changedetectionio/tests/smtp/smtp-test-server.py | 17 | |
| LOW | changedetectionio/diff/__init__.py | 79 | |
| LOW | changedetectionio/diff/__init__.py | 309 | |
| LOW | changedetectionio/diff/tokenizers/words_and_html.py | 13 | |
| LOW | changedetectionio/realtime/events.py | 6 | |
| LOW | changedetectionio/realtime/events.py | 10 | |
| LOW | changedetectionio/realtime/socket_server.py | 62 | |
| LOW | changedetectionio/processors/magic.py | 59 | |
| LOW | changedetectionio/processors/__init__.py | 21 | |
| 79 more matches not shown… | |||
| Severity | File | Line | Snippet |
|---|---|---|---|
| LOW | .github/workflows/test-stack-reusable-workflow.yml | 143 | # Check if RSS is less than 100MB |
| LOW | changedetectionio/pluggy_interface.py | 289 | # Check if plugin has datastore attribute and it's not set |
| LOW | changedetectionio/pluggy_interface.py | 399 | # Check if the result has any meaningful data |
| LOW | changedetectionio/pluggy_interface.py | 609 | # Check if plugin has a templates directory |
| LOW | changedetectionio/worker.py | 738 | # Check if we should restart (only when idle, between jobs) |
| LOW | changedetectionio/worker.py | 747 | # Check if we should exit |
| LOW | changedetectionio/worker.py | 751 | # Check if we're in pytest environment - if so, be more gentle with logging |
| LOW | changedetectionio/worker_pool.py | 133 | # Check if we're in pytest environment - if so, be more gentle with logging |
| LOW | changedetectionio/worker_pool.py | 346 | # Check if we're in pytest environment - if so, be more gentle with logging |
| LOW | changedetectionio/queue_handlers.py | 447 | # Check if all notifications are muted |
| LOW | changedetectionio/queue_handlers.py | 471 | # Check if all notifications are muted |
| LOW | changedetectionio/gc_cleanup.py | 68 | # Check if lxml.etree is in use |
| LOW | changedetectionio/gc_cleanup.py | 95 | # Check if lxml.html is in use |
| LOW | changedetectionio/gc_cleanup.py | 117 | # Check if json module is being used and try to clear its cache |
| LOW | changedetectionio/__init__.py | 575 | # Check if we need to repeat |
| LOW | changedetectionio/html_tools.py | 179 | # Iterate over the list of XPath selectors |
| LOW | changedetectionio/time_handler.py | 55 | # Check if the current day matches the target day or overlaps due to duration |
| LOW | changedetectionio/languages.py | 91 | # Check if messages.po exists |
| LOW | changedetectionio/flask_app.py | 370 | # Check if it's a built-in fetcher |
| LOW | changedetectionio/flask_app.py | 623 | # Check if there's a redirect parameter to return to after re-login |
| LOW | changedetectionio/flask_app.py | 656 | # Check if there's a redirect parameter to return to the same page |
| LOW | changedetectionio/flask_app.py | 839 | # Check if file exists in plugin's static directory |
| LOW | changedetectionio/flask_app.py | 1145 | # Check if all checks are paused |
| LOW | changedetectionio/browser_steps/browser_steps.py | 90 | # Check if action handler exists |
| LOW | changedetectionio/browser_steps/browser_steps.py | 112 | # Check if navigation actually occurred |
| LOW | changedetectionio/browser_steps/browser_steps.py | 433 | # Check if session has expired based on age |
| LOW | changedetectionio/content_fetchers/playwright.py | 57 | # Set viewport to a larger size to capture more content at once |
| LOW | changedetectionio/content_fetchers/puppeteer.py | 383 | # Check if page still exists (might have been closed due to error during sleep) |
| LOW | changedetectionio/content_fetchers/puppeteer.py | 413 | # Check if page still exists before sending command |
| LOW | …angedetectionio/notification/apprise_plugin/discord.py | 43 | # Check if body contains our diff placeholders |
| LOW | …angedetectionio/notification/apprise_plugin/discord.py | 116 | # Check if we're approaching the embed count limit |
| LOW | …angedetectionio/notification/apprise_plugin/discord.py | 127 | # Check if adding this embed would exceed total character limit |
| LOW | changedetectionio/tests/test_commit_persistence.py | 437 | # Set browser_steps to meaningless values |
| LOW | changedetectionio/tests/test_i18n.py | 169 | # Set language to Italian |
| LOW | changedetectionio/tests/test_i18n.py | 651 | # Set language to German |
| LOW | changedetectionio/tests/unit/test_time_handler.py | 94 | # Set schedule to start 23:30 with 120 minute duration (crosses midnight) |
| LOW | changedetectionio/tests/unit/test_time_handler.py | 177 | # Set time to current hour |
| LOW | changedetectionio/tests/unit/test_time_handler.py | 513 | # Set time to 3 hours ago |
| LOW | changedetectionio/diff/__init__.py | 135 | # Check if there are any changes |
| LOW | changedetectionio/diff/__init__.py | 141 | # Check if the whole line is replaced (no unchanged content) |
| LOW | changedetectionio/diff/__init__.py | 270 | # Check if there are any changes |
| LOW | changedetectionio/diff/__init__.py | 406 | # Check if there are any actual changes (not just whitespace when ignore_junk is enabled) |
| LOW | changedetectionio/realtime/events.py | 22 | # Check if watch exists |
| LOW | changedetectionio/realtime/socket_server.py | 319 | # Check if authentication is required and user is not authenticated |
| LOW | changedetectionio/processors/__init__.py | 204 | # Check if DISABLED_PROCESSORS env var is set |
| LOW | changedetectionio/processors/__init__.py | 221 | # Check if this is a plugin processor |
| LOW | …ngedetectionio/processors/image_ssim_diff/processor.py | 62 | # Check if bounding box is set (for drawn area mode) |
| LOW | …ngedetectionio/processors/image_ssim_diff/processor.py | 146 | # Check if this is the first check (no previous history) |
| LOW | …ngedetectionio/processors/image_ssim_diff/edit_hook.py | 38 | # Check if template matching is globally enabled via ENV var |
| LOW | …ssors/image_ssim_diff/image_handler/isolated_opencv.py | 45 | # Check if decoding succeeded |
| LOW | …ssors/image_ssim_diff/image_handler/isolated_opencv.py | 150 | # Check if result is an error dict |
| LOW | …ssors/image_ssim_diff/image_handler/isolated_opencv.py | 306 | # Check if result is an error dict |
| LOW | …ssors/image_ssim_diff/image_handler/isolated_opencv.py | 436 | # Check if result is an error dict |
| LOW | …ssors/image_ssim_diff/image_handler/isolated_opencv.py | 581 | # Check if result is an error dict |
| LOW | …ssors/image_ssim_diff/image_handler/libvips_handler.py | 285 | # Check if match is good enough (80% confidence threshold) |
| LOW | …ngedetectionio/processors/text_json_diff/difference.py | 168 | # Check if this is a user submission (any diff pref param exists in query string) |
| LOW | …angedetectionio/processors/text_json_diff/processor.py | 184 | # Check if it's perl-style regex /.../ |
| LOW | …ionio/processors/restock_diff/pure_python_extractor.py | 37 | # Check if this is a JSON-LD script tag |
| LOW | changedetectionio/model/__init__.py | 310 | # Check if we're being initialized from an existing watch object |
| LOW | changedetectionio/model/__init__.py | 452 | # Check if it's a property descriptor |
| 12 more matches not shown… | |||
| Severity | File | Line | Snippet |
|---|---|---|---|
| HIGH | changedetectionio/forms.py | 563 | f"The following tokens used in the notification are not valid: {undefined}" |
| HIGH | changedetectionio/notification/handler.py | 475 | #@todo on null:// (only if its a 1 url with null) probably doesnt need to actually .add/setup/etc |
| HIGH | changedetectionio/tests/test_api_security.py | 499 | # Should accept (empty is valid as null) |
| HIGH | changedetectionio/tests/test_api.py | 1153 | - CREATE endpoint rejects null, empty, and invalid URLs |
| HIGH | changedetectionio/tests/test_api.py | 1154 | - UPDATE endpoint rejects attempts to change URL to null, empty, or invalid |
| HIGH | changedetectionio/tests/test_xpath_selector_unit.py | 142 | ("manager[1]/@name || manager[2]/@name", "GodotFreya"), |
| HIGH | changedetectionio/tests/test_llm_change_summary.py | 158 | return JSON {"summary": null, "error": "<readable message>"} with a 500 |
| HIGH | changedetectionio/tests/llm/test_response_parser.py | 93 | raw = '{"needs_prefilter": false, "selector": null, "reason": "intent is global"}' |
| HIGH | changedetectionio/tests/llm/test_llm_restock_plugin.py | 128 | llm_json = '{"price": null, "currency": null, "availability": "instock"}' |
| HIGH | changedetectionio/tests/llm/test_llm_restock_plugin.py | 138 | llm_json = '{"price": 19.95, "currency": "GBP", "availability": null}' |
| HIGH | changedetectionio/tests/llm/test_llm_restock_plugin.py | 148 | llm_json = '{"price": null, "currency": null, "availability": null}' |
| HIGH | changedetectionio/tests/llm/test_llm_restock_plugin.py | 200 | llm_json = '{"price": null, "currency": null, "availability": null}' |
| HIGH | changedetectionio/api/Import.py | 39 | - anyOf: [{type: string}, {type: null}] (anyOf format) |
| HIGH | changedetectionio/blueprint/ui/diff.py | 180 | Returns JSON: {"summary": "...", "error": null} or {"summary": null, "error": "..."} |
| Severity | File | Line | Snippet |
|---|---|---|---|
| HIGH | …ngedetectionio/tests/test_trigger_regex_with_filter.py | 0 | <html> <body> some initial text<br> <p>which is across multiple lines</p> <br> so let's see what happens. <br> </body> < |
| HIGH | changedetectionio/tests/test_ignorestatuscode.py | 0 | <html> <body> some initial text<br> <p>which is across multiple lines</p> <br> so let's see what happens. <br> </body> < |
| HIGH | …angedetectionio/tests/test_block_while_text_present.py | 0 | <html> <body> some initial text<br> <p>which is across multiple lines</p> <br> so let's see what happens. <br> </body> < |
| HIGH | changedetectionio/tests/test_conditions.py | 0 | <html> <body> some initial text<br> <p>which is across multiple lines</p> <br> so let's see what happens. <br> </body> < |
| HIGH | changedetectionio/tests/test_conditions.py | 0 | <html> <body> some initial text<br> <p>which is across multiple lines</p> <br> so let's see what happens. <br> </body> < |
| HIGH | changedetectionio/tests/test_ignorewhitespace.py | 0 | <html> <body> some initial text<br> <p>which is across multiple lines</p> <br> so let's see what happens. <br> </body> < |
| HIGH | changedetectionio/tests/test_trigger_regex.py | 0 | <html> <body> some initial text<br> <p>which is across multiple lines</p> <br> so let's see what happens. <br> </body> < |
| HIGH | changedetectionio/tests/test_conditions.py | 0 | <html> <body> <h1>test page for conditions</h1> <p>this page contains a number that will be tested with conditions.</p> |
| HIGH | changedetectionio/tests/test_conditions.py | 0 | <html> <body> <h1>test page for conditions</h1> <p>this page contains a number that will be tested with conditions.</p> |
| HIGH | changedetectionio/tests/test_conditions.py | 0 | <html> <body> <h1>test page for conditions</h1> <p>this page contains a number that will be tested with conditions.</p> |
| HIGH | changedetectionio/tests/smtp/test_notification_smtp.py | 0 | when following a plaintext document, notification in plain text format is sent correctly |
| HIGH | changedetectionio/tests/smtp/test_notification_smtp.py | 0 | when following a plaintext document, notification in plain text format is sent correctly |
| HIGH | changedetectionio/tests/smtp/test_notification_smtp.py | 0 | when following a plaintext document, notification in plain text format is sent correctly |
| Severity | File | Line | Snippet |
|---|---|---|---|
| HIGH | changedetectionio/is_safe_url.py | 22 | Validate that a redirect URL is safe to prevent open redirect vulnerabilities. This follows Flask/Werkzeug bes |
| HIGH | changedetectionio/queue_handlers.py | 162 | Efficient async get using executor for blocking call. HYBRID APPROACH: Best of both worlds - U |
| HIGH | changedetectionio/diff/tokenizers/natural_text.py | 12 | Split text into words using simple whitespace boundaries. This is a simpler tokenizer that treats all whitespa |
| HIGH | changedetectionio/diff/tokenizers/words_and_html.py | 14 | Split text into words and boundaries (spaces, HTML tags). This tokenizer preserves HTML tags as atomic units w |
| HIGH | changedetectionio/processors/restock_diff/processor.py | 204 | Extract itemprop availability with hybrid approach for memory efficiency. Strategy (fastest to slowest, least |
| HIGH | changedetectionio/model/persistence.py | 13 | Determine entity type from class hierarchy (cached at class level). Args: cls: The class to inspect |
| HIGH | changedetectionio/model/Watch.py | 55 | Save compressed data using native brotli with streaming compression. Uses chunked compression to minimize peak |
| Severity | File | Line | Snippet |
|---|---|---|---|
| LOW | requirements.txt | 61 | beautifulsoup4>=4.0.0,<=4.14.3 |
| LOW | docker-entrypoint.sh | 1 | #!/bin/bash |
| LOW | docker-compose.yml | 1 | services: |
| LOW | docker-compose.yml | 21 | # Example: Install the OSINT reconnaissance processor plugin |
| LOW | docker-compose.yml | 41 | # Playwright proxy settings playwright_proxy_server, playwright_proxy_bypass, playwright_proxy_username, playwri |
| LOW | docker-compose.yml | 61 | # Default number of parallel/concurrent fetchers |
| LOW | docker-compose.yml | 81 | # |
| LOW | docker-compose.yml | 101 | |
| LOW | docker-compose.yml | 121 | # restart: unless-stopped |
| LOW | docker-compose.yml | 141 | # --headless |
| LOW | docs/api-spec.yaml | 801 | - null: Not decided yet / inherit default behavior |
| LOW | .github/workflows/codeql-analysis.yml | 1 | # For most projects, this workflow file will not need changing; you simply need |
| LOW | .github/workflows/codeql-analysis.yml | 41 | # By default, queries listed here will override any specified in a config file. |
| LOW | .github/workflows/test-only.yml | 61 | run: | |
| LOW | .github/actions/extract-memory-report/action.yml | 41 | # sed 's/.*Peak memory: //' | \ |
| LOW | changedetectionio/__init__.py | 21 | # Note: store and changedetection_app are imported inside main() to avoid |
| LOW | changedetectionio/__init__.py | 41 | # - Consistent across all platforms (Windows already uses spawn by default) |
| LOW | changedetectionio/forms.py | 461 | # some_object = klass() |
| LOW | changedetectionio/html_tools.py | 361 | # - local-name(): //*[local-name()='title']/text() |
| LOW | changedetectionio/notification/handler.py | 381 | if _llm_change_summary and _override_diff: |
| LOW | …etectionio/tests/test_automatic_follow_ldjson_price.py | 181 | </body></html> |
| LOW | …etectionio/tests/test_automatic_follow_ldjson_price.py | 201 | # "offeredBy": { |
| LOW | changedetectionio/tests/proxy_list/conftest.py | 1 | #!/usr/bin/env python3 |
| LOW | changedetectionio/tests/custom_browser_url/__init__.py | 1 | # placeholder |
| LOW | changedetectionio/processors/restock_diff/processor.py | 61 | # MEMORY MANAGEMENT: Why We Use Multiprocessing (Linux Only) |
| LOW | changedetectionio/processors/restock_diff/processor.py | 81 | # When a subprocess exits, the OS forcibly reclaims ALL memory including C-level |
| LOW | changedetectionio/processors/restock_diff/processor.py | 101 | # - The leak is specifically from lxml's document parsing, not the JSONPath queries |
| LOW | changedetectionio/processors/restock_diff/processor.py | 441 | # from ...html_tools import html_to_text |
| LOW | …ngedetectionio/static/styles/scss/parts/_sub_tabs.scss | 1 | // ── Vertical sub-tab layout ─────────────────────────────────────────────────── |
| LOW | changedetectionio/conditions/plugins/__init__.py | 1 | # Import plugins package to make them discoverable |
| LOW | changedetectionio/api/Watch.py | 281 | if content: |
| LOW | changedetectionio/blueprint/browser_steps/__init__.py | 1 | |
| LOW | changedetectionio/store/file_saving_datastore.py | 121 | try: |
| Severity | File | Line | Snippet |
|---|---|---|---|
| CRITICAL | changedetectionio/static/js/jquery-3.6.0.min.js | 2 | !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):f |
| CRITICAL | changedetectionio/blueprint/settings/__init__.py | 62 | form.application.form.notification_format.choices.pop() |
| CRITICAL | changedetectionio/blueprint/settings/__init__.py | 70 | form.requests.form.proxy.choices.append(tuple((p, datastore.proxy_list[p]['label']))) |
| Severity | File | Line | Snippet |
|---|---|---|---|
| LOW | changedetectionio/worker.py | 479 | # Step 1: AI Change Intent — may suppress notification |
| LOW | changedetectionio/worker.py | 500 | # Step 2: AI Change Summary — runs for any LLM-configured watch with a change |
| LOW | changedetectionio/__init__.py | 410 | # Step 1: Add URLs with their options (if provided via -u flags) |
| LOW | changedetectionio/__init__.py | 430 | # Step 2: Queue newly added watches (if -u was provided in batch mode) |
| LOW | changedetectionio/__init__.py | 447 | # Step 3: Queue watches for recheck (if -r was provided) |
| LOW | changedetectionio/__init__.py | 486 | # Step 4: Setup batch mode monitor (if -b was provided) |
| LOW | changedetectionio/tests/test_extract_regex.py | 477 | # Step 1: keep lines containing "price" (excludes Stock count and Shipping cost) |
| LOW | changedetectionio/tests/test_extract_regex.py | 479 | # Step 2: from those lines extract only dollar amounts |
| LOW | changedetectionio/tests/test_i18n.py | 83 | # Step 1: Set the language to Italian using the /set-language endpoint |
| LOW | changedetectionio/tests/test_i18n.py | 91 | # Step 2: Request the index page - should be in Italian |
| LOW | changedetectionio/tests/test_i18n.py | 105 | # Step 3: Switch back to English |
| LOW | changedetectionio/tests/test_i18n.py | 560 | # Step 1: Clear session and make first request with zh-TW header (auto-detect) |
| LOW | changedetectionio/tests/test_i18n.py | 578 | # Step 2: User explicitly selects Korean language |
| LOW | changedetectionio/tests/test_i18n.py | 587 | # Step 3: Make another request with same zh-TW header |
| LOW | changedetectionio/processors/restock_diff/processor.py | 223 | # Step 1: Try pure Python extraction first (fast, no lxml, no memory leak) |
| LOW | changedetectionio/processors/restock_diff/processor.py | 244 | # Step 2: Fall back to extruct (uses lxml, needs subprocess on Linux) |
| LOW | changedetectionio/blueprint/ui/diff.py | 59 | # Step 1: Escape everything like Jinja2 would (this makes it XSS-safe) |
| LOW | changedetectionio/blueprint/ui/diff.py | 62 | # Step 2: Unescape only our exact diff spans generated by apply_html_color_to_body() |
| Severity | File | Line | Snippet |
|---|---|---|---|
| MEDIUM | changedetectionio/worker_pool.py | 291 | """Bulletproof queue operation with comprehensive error handling""" |
| LOW | changedetectionio/html_tools.py | 465 | # Foreach <script json></script> blob.. just return the first that matches json_filter |
| LOW | changedetectionio/content_fetchers/requests.py | 198 | # Binary files just return their checksum until we add something smarter |
| LOW | changedetectionio/notification/__init__.py | 8 | # But to avoid importing the whole heavy module just use the same strings here. |
| LOW | changedetectionio/tests/test_request.py | 9 | # Hard to just add more live server URLs when one test is already running (I think) |
| MEDIUM | changedetectionio/tests/test_history_consistency.py | 49 | # Essentially just triggers the DB write/update |
| LOW | changedetectionio/tests/test_notification.py | 23 | # Hard to just add more live server URLs when one test is already running (I think) |
| MEDIUM | changedetectionio/processors/magic.py | 64 | # Remove whitespace between < and tag name for robust detection (handles '< html', '<\nhtml', etc.) |
| LOW | changedetectionio/conditions/blueprint.py | 35 | # We'll ignore the returned response and just use the datastore which is modified by the function |
| Severity | File | Line | Snippet |
|---|---|---|---|
| LOW | changedetectionio/content_fetchers/__init__.py | 48 | # In this case, make sure to edit the default one in store.py and fetch_site_status.py |