Skip to content

Commit 7e4098c

Browse files
RivianTrackrclaude
andcommitted
Fix affiliate links corrupted by ampersand-stripping sanitizer (1.52.1)
validateAndSanitizeCSVRow stripped < > " ' & from every string cell, deleting the & query-param separators in affiliate/image/review URLs. A TireRack link like ?tireMake=…&tireModel=…&partnum=… collapsed into one param, so the retailer couldn't resolve the product and bounced the click to its homepage. Same latent break hit review links (e.g. YouTube watch?v=…&t=…) and any image URL with a query string. Exclude the URL/identifier columns (18 link, 19 image, 22 review_link, 28 slug) from the strip, matching the existing 27 (vehicle_breakdown JSON) exception. Each URL field is still validated by its own strict allowlist helper (safeLinkURL / safeImageURL / safeReviewLinkURL) before use, so <>"' can't slip through. Stored data was never affected — the & were always correct in the DB; only the rendered link was corrupted, so no data repair is needed. Verified the full pipeline (row sanitizer -> safeLinkURL) preserves the URL; build regenerated; 83/83 JS tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 767b19f commit 7e4098c

5 files changed

Lines changed: 17 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ All notable changes to the Rivian Tire Guide plugin will be documented in this f
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
66

7+
## [1.52.1] - 2026-07-02
8+
9+
### Fixed
10+
- **Affiliate/review/image links with query strings were silently broken.** The client-side row sanitizer (`validateAndSanitizeCSVRow`) stripped `< > " ' &` from every string cell, which deleted the `&` separators inside URLs — e.g. `?tireMake=…&tireModel=…&partnum=…` collapsed into a single param, so retailers like TireRack couldn't resolve the product and redirected clicks to their homepage. The affiliate link (index 18), image (19), and review link (22) columns — plus the slug (28) — are now excluded from that strip, matching the existing exception for the JSON `vehicle_breakdown` column (27). These fields are still validated by their own strict allowlist helpers (`safeLinkURL` / `safeImageURL` / `safeReviewLinkURL`) before use, so nothing unsafe slips through. Stored data was never affected — the `&` were always correct in the database; only the rendered link was corrupted.
11+
712
## [1.52.0] - 2026-07-02
813

914
### Added

frontend/js/modules/validation.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,14 @@ export function validateAndSanitizeCSVRow(row) {
211211
const cell = row[i];
212212

213213
if (typeof cell === "string") {
214-
// Index 27 (vehicle_breakdown) contains JSON — preserve quotes.
215-
if (i === 27) {
214+
// Some columns must NOT have <>"'& stripped:
215+
// 18 link, 19 image, 22 review_link — URLs where & separates query
216+
// params (stripping it corrupts the destination); each is validated
217+
// by its own strict allowlist helper (safeLinkURL / safeImageURL /
218+
// safeReviewLinkURL) before use, so <>"' can't slip through.
219+
// 27 vehicle_breakdown — JSON, needs its quotes.
220+
// 28 slug — identifier, url-encoded at use.
221+
if (i === 18 || i === 19 || i === 22 || i === 27 || i === 28) {
216222
sanitized[i] = cell;
217223
} else {
218224
sanitized[i] = cell.replace(/[<>\"'&]/g, "").trim();

frontend/js/rivian-tires.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "rivian-tire-guide",
3-
"version": "1.52.0",
3+
"version": "1.52.1",
44
"private": true,
55
"description": "Interactive tire guide for Rivian vehicles — WordPress plugin",
66
"scripts": {

0 commit comments

Comments
 (0)