Skip to content

fix(deps): bump pillow and selenium minimum floors to patched versions - #5

Closed
dominicci13 wants to merge 36 commits into
mainfrom
chore/security-bumps-202607
Closed

fix(deps): bump pillow and selenium minimum floors to patched versions#5
dominicci13 wants to merge 36 commits into
mainfrom
chore/security-bumps-202607

Conversation

@dominicci13

Copy link
Copy Markdown
Owner

Summary

Monthly dependency security sweep (2026-07). Two direct dependencies in pyproject.toml have minimum-version floors that permit installation of versions with known CVEs.


Vulnerable pins → fixed pins

Package Old floor New floor Advisories Worst fix required
pillow >=10.0.0 >=12.3.0 PYSEC-2023-175, PYSEC-2026-165, PYSEC-2026-457, PYSEC-2026-1793, PYSEC-2026-1794, PYSEC-2026-2253, PYSEC-2026-2254, PYSEC-2026-2255, PYSEC-2026-2256, PYSEC-2026-2257, PYSEC-2026-2874 12.3.0
selenium >=4.0.0 >=4.14.0 PYSEC-2023-206 4.14.0

Notes

  • pywin32 could not be audited (Windows-only; no Linux distribution available for pip-audit).
  • seleniumbase>=4.0.0 pulls in stale transitive dependencies (cryptography, urllib3, requests, idna, h11, pymysql, pyopenssl, ipython, pygments, soupsieve, pytest) with many known CVEs when resolved at its minimum version 4.0.0. These are not direct deps in this file and are not changed here; a follow-up to raise the seleniumbase floor or pin transitive deps is recommended.
  • Only shared-python-utils was accessible in this session. The other fleet repos (amzn-*, ebay-*, bb-*, all-dashboards-report, sellercloud-sync) were denied by the session's GitHub scope — see the tracking issue for next steps.

Audit tool: pip-audit 2.10.1 against PyPI/OSV
Do not merge to main without verifying compatibility with the Windows runtime environment.


Generated by Claude Code

dominicci13 added 30 commits May 4, 2026 19:26
- Added database_utils, excel_utils, schedule_utils, screenshot_utils,
  ui_utils, file_utils modules
- Added upsert_dataframe(), get_verification_code(), run_on_schedule(),
  crop_to_element(), crop_to_box(), paste_to_excel(), load_config_safe()
- Moved hardcoded account data to config/accounts.json (gitignored)
- Moved SMTP sender and SellerCloud URLs to env vars via get_env()
- Fixed kill_app() command injection, temp file paths, files_info() bug
- Replaced quit() with raise RuntimeError in insert_dataframe()
- Merged safe_start_browser() into start_browser() with retry_count param
- Removed firefox.py, legacy schedule sleep helpers
- Full type hints and Args/Returns/Raises docstrings across all modules
- Added LICENSE (MIT), README.md, updated CHANGELOG.md and .gitignore
- Removed egg-info from version control
Removed:
- logging_utils module (setup_logger) — suite uses rich.print
- alert_utils.send_error_email — handle_crash covers alerting via Outlook
- config_utils.load_env — every consumer uses python-dotenv directly
- custom_functions: download_finished, find_file, files_info, tomorrow,
  yesterday
- database_utils.upsert_dataframe — added in 0.2.0 but never adopted
- python-dotenv from pyproject.toml deps (no fc_utils module imports it)

Added:
- accounts.iter_amazon_accounts() generator yielding (key, name, url)
- file_utils.latest_modified_date(path) returning the latest mtime as
  datetime, or None

Improvements:
- accounts: config/accounts.json resolved relative to sys.argv[0] entry
  script, falling back to CWD (robust against Task Scheduler launches)
- custom_functions.shadow_element: fixed broken by_map[True] dispatch with
  explicit if/elif cascade
- accounts.amazon_login: delegates OTP polling to get_verification_code;
  new retry_url parameter replaces unbounded retry loops at call sites
  (capped at 5 attempts)
- outlook.get_verification_code: new consume=True flag marks the matched
  message as read and deletes it after extraction
- schedule_utils.run_on_schedule: SIGINT handler shuts down the scheduler
  immediately on Windows (BlockingScheduler.Event.wait was blocking SIGINT
  until the next fire)

Packaging:
- Version bumped to 0.3.0
- __init__.py __all__ reduced to actually-used symbols
Single entry point that wires a Rich console handler (colorized output,
markup rendering, rich tracebacks) plus a 1 MB rotating file handler
writing plain-text logs to logs/<name>.log. Safe to call multiple times
in one process; handlers are only installed on the first call.

Consumers replace ad-hoc rich.print imports plus custom logging blocks
with a single line:

    from fc_utils.logging_utils import setup_logging
    log = setup_logging("my_automation")
Previous implementation queried sheet.range(f"{column}{row}").value once
per row inside a Python loop — one COM round-trip per cell. For a table
with N rows that was N+1 COM calls.

This rewrite reads the whole column in a single COM call and scans the
resulting list in pure Python, so the cost is always 2 COM calls
regardless of table size. The win scales linearly with row count.

Signature and return semantics are unchanged so existing callers
(eBay-Pending-Offers and other automations) keep working.
BlockingScheduler.start() on Windows blocks in a C-level
threading.Event.wait() whose timeout is sized to the next job — which can
be many hours away. Python signal delivery (SIGINT) is queued while that
wait is in progress and only handled when the wait returns, so Ctrl+C is
effectively swallowed until the next job runs.

Switch to BackgroundScheduler plus a `while True: time.sleep(1)` loop in
the main thread. time.sleep on Windows IS interruptible by Ctrl+C, so
KeyboardInterrupt propagates immediately, the scheduler shuts down
cleanly in `finally`, and the process exits. The scheduler's own daemon
thread continues to block efficiently until the next fire time, so the
heartbeat tick costs near-zero CPU.

The previous custom SIGINT handler is removed — KeyboardInterrupt
propagation handles shutdown directly.
- Register SUCCESS=25 custom log level + Logger.success() method bound at import.
- Add RichLevelFormatter that prepends colored [LEVELNAME] tag per message
  (cyan/INFO, green/SUCCESS, yellow/WARNING, red/ERROR, bold red/CRITICAL, dim/DEBUG).
- setup_logging() now wires RichHandler with show_level=False and the new formatter
  so the level appears exactly once, regardless of whether callers also embed
  [LEVEL] markup in their messages. File handler unchanged.
- Bump version to 0.4.0.
Every fc_utils submodule now uses the standard logging API instead of
rich.print:

- Each module declares `log = logging.getLogger(__name__)` at module scope
  (or relies on it via the existing `setup_logging` consumer for log
  handler config).
- All 47 print() call sites across 12 modules were converted to the
  matching log.info / log.success / log.warning / log.error.
- The `from rich import print` shadowing import was removed everywhere.
- Inline [cyan][INFO][/cyan] / [bold red][ERROR][/bold red] markup was
  stripped from each log call — the formatter from v0.4.0 supplies the
  colored level tag, so the previous inline markers were redundant.
- Library code now writes silently when called from a context without a
  configured logger (tests, REPL) instead of unconditionally rendering
  Rich markup to stdout.

Bumped version to 0.5.0.
…download_report

New fc_utils.sellercloud module provides reusable SellerCloud automations:

- request_custom_export(driver, custom_template, sku_list=None, product_group=None)
  drives the Manage Catalog grid through the Export Products wizard with a named
  Custom Export template. Filters the grid by URL (SKU CSV or product group id,
  never both). Returns the notify-download URL.

  Validation raises ValueError if neither/both of sku_list/product_group are
  supplied, if sku_list is empty, if more than 100 SKUs are passed, or if the
  template name is not in the wizard dropdown.

- download_report(driver, download_url, download_path, output_path, ...) polls
  the notify-download URL, clicks the download button when SellerCloud finishes
  generating the report, waits for the .xlsx to land in the local downloads
  directory, and moves it to the caller-supplied output_path.

Both functions read DOM selectors and URLs from config/selectors.json and
config/paths.json (resolved relative to the entry script, like accounts.py).
Consumers own those JSON files in their own repo and typically gitignore them.

Both exported at the package root: from fc_utils import request_custom_export,
download_report.

Bumped version to 0.6.0.
sellercloud.download_report previously hardcoded `.xlsx` when constructing
the expected filename in download_path. That broke CSV and TSV exports
because the file Chrome dropped never matched the polled name.

Now the function reads `output_path.suffix` and uses that for the
download filename, so .csv, .xlsx, and .tsv outputs all work with no
caller changes. Falls back to .xlsx only if output_path has no suffix.
- chrome.py: move 'import logging' up to the stdlib import block (was
  sandwiched between the third-party imports and the first-party
  fc_utils.custom_functions import).
- .gitignore: ignore ruvector.db (Ruflo plugin artifact).
Centralizes browser-debug screenshot capture under screenshots/<root>/
<section>/<description>_<timestamp>.png with filesystem-safe sanitization.
Lets consumer repos drop ad-hoc desktop-rooted save_screenshot() calls.
win32com.Dispatch needs CoInitialize on the calling thread. Under
APScheduler the job runs on a worker thread that never had COM set up;
xlwings-based jobs only worked because opening Excel initialized COM as a
side effect. openpyxl-only jobs (and any crash-alert before the first
Excel write) hit com_error -2147221008 at send_email and lost the alert
path. send_email/get_account now call a thread-local-guarded _ensure_com()
before any Dispatch.
…rsions

pillow>=10.0.0 allows installs with 12 known CVEs; bump floor to 12.3.0.
selenium>=4.0.0 allows PYSEC-2023-206; bump floor to 4.14.0.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant