← back to Codex Review 2026 04 30
resize-it/review.md
36 lines
## Snapshot
- Flask web UI for resizing Spoonflower/wallcovering images to 24" wide at 150 DPI, with Spoonflower download/upload automation.
- Stack: Python, Flask, Pillow, Playwright, static HTML/JS/Tailwind CDN; no datastore.
- How it's run: manual `python3 server.py`; no pm2/systemd/launchd/cron observed.
- Status: stale/prototype; hardcoded paths, no deps file.
## Top Risks (P0 — fix this week)
- [server.py:21](/Users/stevestudio2/Projects/resize-it/server.py:21), [server.py:22](/Users/stevestudio2/Projects/resize-it/server.py:22), [.env:1](/Users/stevestudio2/Projects/resize-it/.env:1), [.env:2](/Users/stevestudio2/Projects/resize-it/.env:2): Spoonflower credentials are committed/hardcoded defaults. Rotate password, remove defaults, require env vars at startup.
- [SKILL.md:89](/Users/stevestudio2/Projects/resize-it/SKILL.md:89): Gemini API key is embedded in docs/source. Revoke it, move to secret storage, scrub history if this was ever shared.
- [server.py:270](/Users/stevestudio2/Projects/resize-it/server.py:270)-[274](/Users/stevestudio2/Projects/resize-it/server.py:274): Flask debug server binds `0.0.0.0` and advertises a public IP. Disable debug, bind localhost or put behind authenticated production WSGI.
- [server.py:29](/Users/stevestudio2/Projects/resize-it/server.py:29), [server.py:103](/Users/stevestudio2/Projects/resize-it/server.py:103), [server.py:155](/Users/stevestudio2/Projects/resize-it/server.py:155): no auth on endpoints that use stored Spoonflower credentials. Add owner auth/token gate; especially block public `/api/upload-to-spoonflower`.
- [server.py:165](/Users/stevestudio2/Projects/resize-it/server.py:165)-[167](/Users/stevestudio2/Projects/resize-it/server.py:167): URL validation is substring-only; `http://internal/?spoonflower.com` passes to Playwright. Use `urlparse`, require HTTPS and exact Spoonflower host suffix.
- [server.py:190](/Users/stevestudio2/Projects/resize-it/server.py:190)-[197](/Users/stevestudio2/Projects/resize-it/server.py:197): picks newest image from global `/tmp`; concurrent requests can resize/download the wrong customer file. Use per-request temp dirs and explicit script output paths.
## Notable Issues (P1 — fix this month)
- [server.py:54](/Users/stevestudio2/Projects/resize-it/server.py:54), [server.py:139](/Users/stevestudio2/Projects/resize-it/server.py:139), [server.py:179](/Users/stevestudio2/Projects/resize-it/server.py:179), [server.py:208](/Users/stevestudio2/Projects/resize-it/server.py:208): hardcoded `cwd='/root/.claude/skills/resize-it'` breaks this checkout. Derive from `Path(__file__).parent`.
- [server.py:107](/Users/stevestudio2/Projects/resize-it/server.py:107), [server.py:159](/Users/stevestudio2/Projects/resize-it/server.py:159): `request.json` can be `None`, causing 500s for malformed JSON. Use `request.get_json(silent=True) or {}` and return 400.
- [server.py:40](/Users/stevestudio2/Projects/resize-it/server.py:40)-[43](/Users/stevestudio2/Projects/resize-it/server.py:43): uploaded files overwrite same sanitized filename. Generate UUID filenames or per-request directories.
- [server.py:259](/Users/stevestudio2/Projects/resize-it/server.py:259)-[266](/Users/stevestudio2/Projects/resize-it/server.py:266): download route exposes any matching filename in `/tmp`. Keep an allowlist/session mapping of generated files.
- [scripts/spoonflower_full_workflow.py:201](/Users/stevestudio2/Projects/resize-it/scripts/spoonflower_full_workflow.py:201)-[205](/Users/stevestudio2/Projects/resize-it/scripts/spoonflower_full_workflow.py:205): reports upload success after sleep/screenshot, not confirmed save state. Assert visible success or network response.
- [web-interface.html:263](/Users/stevestudio2/Projects/resize-it/web-interface.html:263)-[265](/Users/stevestudio2/Projects/resize-it/web-interface.html:265): frontend reads `error.message`, but server returns `error`; users see generic failures. Use `error.error`.
## Polish (P2 — when convenient)
- No dependency manifest observed; add `requirements.txt` or `pyproject.toml` for Flask/Pillow/Playwright.
- Debug screenshots and downloads accumulate in `/tmp`; add cleanup.
- [web-interface.html:7](/Users/stevestudio2/Projects/resize-it/web-interface.html:7): Tailwind CDN makes runtime depend on internet access.
## Strengths
- Uses `subprocess.run([...])` without `shell=True`, reducing command injection risk.
- `secure_filename()` is used for local uploads.
- Resize code keeps aspect ratio and embeds DPI metadata cleanly.
## Open questions for the owner
- Is this ever reachable from the public internet?
- Should upload-to-Spoonflower exist, or only download/resize?
- Are Spoonflower credentials personal, shared business, or service-account credentials?