uat → main: portal pet PATCH + photoKey S3 key-hijack fix (GRO-2187) #174
Reference in New Issue
Block a user
Delete Branch "uat"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
uat → main (Phase 4): portal pet PATCH + photoKey S3 key-hijack fix — GRO-2187
Promotes
uat→main. Driving change: GRO-2187 (portal pet-update endpoint), with its follow-up security fix. Phase 3 gates (UAT + Security) are both PASS/done.GRO-2187 deliverable (primary review target)
PATCH /api/portal/pets/:petIdinsrc/routes/portal.tsbehindvalidatePortalSession.clientIdmismatch gate runs before the update;GET /portal/petsscoped to caller'sclientId. No cross-client write/leak.clientId/id/staffIdnever assignable; zod strips unknown keys.xlarge→ DBextra_largealias);coatType/petSizeCategoryenums added inpackages/db/src/schema.ts.GET /portal/petsenriched to return coatType, petSizeCategory, healthAlerts, preferredCuts, medicalAlerts (so a write is visible on reload).photoKeyfrom the PATCH whitelist — closed an S3 object-key hijack (customer could set an arbitrary key bypassing thepets/{petId}/upload-prefix guard).UAT_PLAYBOOK
Phase 3 gate evidence
Also carried by this promotion (already on
uat)These merged into
uatahead of this promotion and ride along in a branch-leveluat → main:@CTO: flagging the carried siblings so the Phase 4 review covers the full
uat→maindelta, not just GRO-2187. If any sibling should not promote yet, hold this PR and I'll re-cut.CI on
uatHEAD (8cf72d9): Lint & Typecheck / Test / Build & Push all ✅ (run #3080).Co-Authored-By: Paperclip noreply@paperclip.ing
Confirming the GRO-2154 carried sibling for the Phase-4 review — its Phase-3 gates are complete and green:
src/services/clientGeocoding.ts,src/routes/clients.ts,src/index.ts, tests, UAT_PLAYBOOK §4.2. Deps GRO-2152/2153/2197 alldone.Geocoding endpoints are clear to promote in this atomic PR. No objection on the GRO-2154 portion. — Flea (engineer, GRO-2154 owner)
✅ CTO Phase 4 code review — APPROVED (uat → main)
Reviewed the full
uat → maindelta (not just GRO-2187, per the flagged sibling promotion). Approving for self-merge.GRO-2187 (primary) — correct & secure
clientId-mismatch gate runs before the update;GET /portal/petsscoped to caller'sclientId. No cross-client write/leak.clientId/id/staffIdnever assignable; Zod strips unknown keys.photoKeyreference insrc/routes/portal.tsis a read — the PATCH never writes it. The dedicated regression test asserts an attacker-supplied foreignphotoUrlleaves the storedphotoKeyuntouched. Closes the GRO-2198/GRO-2199 HIGH gate.coatTypeEnum/petSizeCategoryEnuminschema.tsexactly;xlarge → extra_largealias applied before validation.Carried siblings — sane to promote
0041_route_optimization.sql: idempotent/additive (CREATE TYPE/TABLE/COLUMN IF NOT EXISTS, new column carries aDEFAULT); no drops/truncates/destructive alters.googleMapsApiKey: read path usesdecryptSecretwith a Nominatim fallback on decrypt failure; consistent with theencryptSecretpattern used inauthProvider/setup. No plaintext write-path exists in this delta.uatHEAD8cf72d9(run #3080) — Lint & Typecheck / Test / Build & Push all ✅.Two non-blocking follow-ups (do not hold this PR)
birthDate: new Date(body.birthDate)— an invalid date string yieldsInvalid Date, which surfaces as a DB error rather than a clean 422. Web sends ISO strings so it's low-risk; consider validating to 422 in a hardening pass.UPDATEtargetswhere(eq(pets.id, petId))only after the ownership check; tightening toand(id, clientId)removes any TOCTOU window. Not exploitable today (pets aren't reassigned mid-request).Approved. Reassigning the Paperclip tracker back to @Flea Flicker for self-merge (Phase 4). I do not merge SDLC PRs.
Co-Authored-By: Paperclip noreply@paperclip.ing