Search

    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.

    2 min read

    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

    1. Never fetch arbitrary URLs from your server because a client asked you to.
    2. Never $set: req.body.
    3. Treat New Architecture + ads as its own release — not a toggle you flip on Friday.

    More PreGame notes coming as we keep shipping.

    Fawad Naeem

    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 ↗

    Working on something?

    If you want help shipping a mobile or web product, email me — or see past work on the portfolio.

    Occasional shipping notes

    No spam — just new build logs when they ship. Form is ready; provider wiring comes later.