Sports PreGame: SSRF, mass assignment, and the New Architecture ad break
What broke in production on a React Native + AWS youth soccer app — and the fixes that actually stuck.
Sports PreGame is live on both stores. That sounds clean. The path there was not.
This is a working log of three issues that showed up after real users started hitting the app: an SSRF footgun in an image proxy, a mass-assignment hole in a venue update endpoint, and Android banner ads dying after we flipped on React Native’s New Architecture.
SSRF in the image proxy
We had a small endpoint that fetched remote images so venue photos could be resized before upload to S3. The URL came from the client.
// before — trust the client URL
app.get('/proxy', async (req, res) => {
const { url } = req.query;
const response = await fetch(String(url));
const buffer = Buffer.from(await response.arrayBuffer());
res.type(response.headers.get('content-type') ?? 'image/jpeg');
res.send(buffer);
});
That is textbook SSRF. An attacker can ask the server to hit internal metadata endpoints, localhost services, or anything else the EC2 role can reach.
Fix: allowlist hostnames, block private/link-local ranges, and only accept https. Prefer signed upload URLs and skip the proxy when you can.
Mass assignment on venue updates
The admin panel sent a partial venue object. The API spread it straight into the Mongo update.
// before
await Venue.findByIdAndUpdate(id, { $set: req.body });
Anything in the body could overwrite fields we never intended clients to touch — including flags that affected visibility and billing-adjacent metadata.
Fix: pick an explicit allowlist with Zod (or similar) and reject unknown keys.
const VenueUpdate = z.object({
name: z.string().min(1).optional(),
address: z.string().optional(),
lat: z.number().optional(),
lng: z.number().optional(),
}).strict();
const data = VenueUpdate.parse(req.body);
await Venue.findByIdAndUpdate(id, { $set: data });
New Architecture broke Android banners
After enabling Fabric / New Architecture, AdMob banner views on Android stopped rendering. iOS was fine. Mediation made debugging slower because failures looked like “no fill” instead of “view never mounted.”
The short version: a third-party ad adapter was not ready for the Fabric view manager lifecycle. We pinned a compatible adapter set, verified banner mount in a minimal RN screen, then re-enabled mediation networks one by one.
Takeaways
- Never fetch arbitrary URLs from your server because a client asked you to.
- Never
$set: req.body. - Treat New Architecture + ads as its own release — not a toggle you flip on Friday.
More PreGame notes coming as we keep shipping.
Related
Author

Fawad Naeem
Full-stack developer in Lahore building React Native apps, Astro sites, and AWS-backed products. This log is where the shipping notes live.
View portfolio ↗Hire
Working on something?
If you want help shipping a mobile or web product, email me — or see past work on the portfolio.
Newsletter
Occasional shipping notes
No spam — just new build logs when they ship. Form is ready; provider wiring comes later.