A 124MB travel app was really a 50KB web page

2 months ago

A school group was told to install a hundred-and-twenty-four-megabyte app, just to read their trip itinerary. One developer found that odd, and checked what it was doing.

Ask

Ask about this presentation

Answers are generated from this presentation.

Chapters

  1. 0:00Slide 1
  2. 0:09What the ‘app’ is: a trip itinerary you install.
  3. 0:19He didn't argue. He watched what it downloads.
  4. 0:32The ‘app’ was already sending HTML.
  5. 0:47Slide 5
  6. 0:59Slide 6
  7. 1:13The web app that was meant to make this unnecessary.
  8. 1:26Slide 8
Show transcript

Slide 1

A 124MB travel app was really a 50KB web page
So a developer intercepted its traffic and rebuilt it as a 50 KB web page.
reverse-engineering danq.me

A school group was told to install a hundred-and-twenty-four-megabyte app, just to read their trip itinerary. One developer found that odd, and checked what it was doing.

What the ‘app’ is: a trip itinerary you install.

What the ‘app’ is: a trip itinerary you install.

The travel app's Summary screen on a phone: Your Ferry Crossing / Day 1, 12:20 Check-in at your Hotel, Coach Driver Accommodation, Disney's Hotel Cheyenne, 14:30 Welcome Gala.
The app’s Summary screen — ferry, hotel, coach, welcome gala. A list of where to be, and when.
danq.me

Here's the app: a travel itinerary. The ferry crossing, the hotel, the coach, the welcome gala. A list of where to be, and when. Once, this was a printed sheet.

He didn't argue. He watched what it downloads.

Watch the traffic with an intercept proxy on the app, find it all loads from one JSON endpoint /api/itineraries/{user}-{pass}, then rebuild it as static HTML with a small script on a schedule.
A proxy's request list: repeated GET 200 requests to travelbound.api.vamoos.com /api/itineraries/..., the credentialed rows author-redacted with black bars.
the intercepted traffic · danq.me

He didn't argue. He watched what the app downloaded, with a proxy that reads its network traffic. Within minutes it was clear: everything loads from one web address. And what came back gave the whole thing away.

The ‘app’ was already sending HTML.

The ‘app’ was already sending HTML.

Raw JSON from travelbound.api.vamoos.com/api/itineraries/{username}-{password}. The shortInformation field literally contains HTML: line breaks written as br slash, a bold Irish Ferries heading in strong tags, and an embedded anchor link.
danq.me

The app fetches one block of JSON. Inside, the text already contains HTML: line breaks, bold tags, links, written out in full. The app wasn't building those pages. It was handed web content, over the web, and drawing it.

Slide 5

He wrote a small script: pull the same JSON, render it as a plain web page. The app installs at forty-three megabytes, and swells to a hundred and twenty-four. His page is fifty kilobytes. Same trip.

Slide 6

The app added just two things a page wouldn't: tracking tied to your Google account, and ads for the agency's other trips. Drop those, and you get back copy, paste, print, save, search, and it works on any device.

The web app that was meant to make this unnecessary.

The progressive web app that never quite arrived.
Apps persist for push, tracking, and billing — not the content.

There's a fair objection. We were meant to be in the age of web apps, pages that do all this with no install. But as one engineer put it, apps persist for push notifications, tracking, and billing, not for the content.

Slide 8

Some apps could have been web pages.
The rebuilt static web page at travelunbound.danq.dev, rendering the same Your Ferry Crossing itinerary as plain web content, booking reference author-blurred.
danq.me

Not every app should be a web page. Some genuinely need to be native. But an app that only hands you a document was a web page all along, wearing an install.