Commit Graph

18 Commits

Author SHA1 Message Date
myron 186ac0cb6d security: fix unauthenticated file upload/RCE risk, TLS bypass, XSS, and broken gift-card/review columns
- admin/api/upload-splash.php had NO admin-auth check (included the public
  customer header, not admin/includes/header.php) and both upload endpoints
  trusted the client-supplied MIME type and filename extension, so an
  attacker could name a file "shell.php", spoof Content-Type: image/png,
  and get PHP written into a web-reachable uploads/ directory. Added
  AdminAuth check and centralized real-content validation (getimagesize +
  server-side extension mapping) in a new handleImageUpload() helper used
  by both admin/upload-image.php and admin/api/upload-splash.php.
- Removed CURLOPT_SSL_VERIFYPEER => false from the CyberMail email calls
  in includes/email.php and includes/functions.php (MITM risk on the API
  key). Rewrote functions.php's sendEmail() as a thin wrapper around
  Email::send() so there's one implementation instead of two that could
  drift (this is what had the second copy of the TLS bypass).
- Escaped customer-controlled fields (customer_name, tracking info, reset
  URL) before interpolating into outbound HTML emails — name is free text
  from registration/checkout with no length/char restriction, so it was
  stored-HTML-injectable into every transactional email.
- Fixed api/redeem-gift-card.php referencing a nonexistent `balance` column
  on gift_cards (actual column is current_balance) — gift card redemption
  was completely broken, always returning "no remaining balance".
- Fixed api/submit-review.php inserting into nonexistent `content`/`status`
  columns on reviews (actual columns are `comment`/`is_approved`) — review
  submission was crashing on every request.
- Hardened .htaccess: block /db/*, /.git/*, and *.sql. Live site currently
  serves db/schema.sql and the full .git directory (including .git/config,
  which contains a GitHub PAT with push access) over HTTP — the existing
  config/includes RedirectMatch rules are also not being enforced live,
  see report for details; this needs a server-level fix too.
- Cleaned up README's leftover install instructions pointing at a deleted
  create-admin.php with a documented default password.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 14:22:50 -05:00
myron 06260ed192 fix: move loadCustomerEmails to module scope, wire into switchCTab, add emails to tab loop; drop redundant ?: [] in customer-emails.php 2026-06-23 16:35:11 +00:00
myron 145397ab81 sync: updated admin, assets, new images, composer config, customer email API 2026-06-21 03:46:45 +00:00
myron a2bc87e947 Update admin nav logo to new PNG design
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 20:03:24 +00:00
myron b6d0319be7 Fix admin order page blank redirect after status/note update
Missing ob_start() meant HTML was output before POST handler ran,
so header() redirects silently failed after saving changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 20:50:53 +00:00
myron 29656bd4d7 Add product count column to product types admin page
Shows how many active products are linked to each type, linked to the filtered products list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 19:50:29 +00:00
myron da60888b72 Fix CSV import — convert tags/images to valid JSON before insert (mysql json_valid constraint) 2026-06-14 16:05:42 +00:00
myron 0a6c4508d5 Rebuild product image upload section — fix broken HTML, wrong textarea name, JS quote errors 2026-06-14 15:57:33 +00:00
myron 1609dea8fb Fix product image upload — remove header.php (outputs HTML), auth check directly 2026-06-14 15:48:19 +00:00
myron 5058da704a Fix product image upload — ob_end_clean() before JSON response, fix uploads dir permissions 2026-06-14 15:44:25 +00:00
myron 66cbd3f0d3 Remove prefilled placeholder email from admin login 2026-06-14 15:18:27 +00:00
myron 7eddf9e85d Fix remaining code review findings: email transport errors, metadata payload, from-name, pagination
- Email::send(): add curl_error() check so transport failures (timeout,
  DNS, TLS) return a diagnosable error string instead of Unknown error
- Email::send(): strip metadata key from options before array_merge so
  non-API fields are never sent to CyberMail endpoint
- Email::send() + sendEmail(): include from-name in From field using
  RFC 5322 "Name <email>" format so fromName DB setting takes effect
- email-log.php: replace unbounded page-link loop with a windowed
  paginator (first/last 2 pages + ±2 around current) with ellipsis
  gaps — prevents hundreds of anchors rendering at scale
2026-06-03 06:01:44 +00:00
myron 76bf967bd0 Switch email to CyberMail API; integrations page manages API key via DB 2026-05-29 18:49:15 +00:00
myron 6b71828199 Fix integrations.php: handle POST before HTML output to fix blank screen on save 2026-05-29 18:31:16 +00:00
myron 0d481f8feb Simplify admin login to email/password only; remove Google OAuth 2026-05-29 15:33:16 +00:00
myron e344e52d70 Add Google OAuth admin login; fix header comment; both auth methods active 2026-05-29 15:13:38 +00:00
myron 53f9f3e4da Replace all SendGrid references with CyberMail in admin UI 2026-05-29 15:06:43 +00:00
myron 996ca0d621 Initial commit 2026-05-22 12:52:44 +00:00