Security · Multi-vendor · Food halls

The sold-out sheet read other people’s stock lists

Marking a dish sold out answered with its name whatever kitchen owned it, and the same route walked another company’s stock list by number. Three fences now.


In a food hall ten kitchens share one system, and the thing that makes that safe is a set of fences nobody sees: your till can only reach your dishes, your stock, your settings. Most of our fences are checked by one gate that reads the venue out of the request. Last week we finished sweeping the places where a request names a thing by its number in the body instead, and the sharpest finding was on the pass.

The sold-out sheet

When a kitchen runs out of something, the person on the pass marks it sold out. That can be a dish, an ingredient or a modifier, and the till sends the number of the thing. The route looked it up with a bare lookup by number across the three tables and answered with its name.

Send it a dish number from another kitchen and it answered with that dish’s name. Send it an ingredient number and it answered with the ingredient’s name, out of another company’s stock list, the very list our purchasing screens treat as a competitor’s private information. A till account can call this route, because the sold-out sheet is for every counter. So every counter in the hall could read every other kitchen’s dishes and stock by counting upwards.

Three tables, three fences

Inventing one rule would have been wrong for at least two of the three. A dish belongs to a venue, so the test is that it is active and this venue’s or shared with everyone, the same test the rest of that file already uses. An ingredient does not belong to a venue at all, it belongs to a company, so the test is the company that owns this venue, read from our own records rather than from the caller. A modifier option carries neither, but its group carries both, so it is asked through the group.

The control that mattered most

The fix we were most careful about is the one that keeps the pass working. On the live system no venue has a company record yet and every ingredient’s company is blank, so the new company test had to resolve to exactly the old behaviour there. A fence that quietly stopped the pass from marking things off in the middle of service would be worse than the disclosure it closed. We asserted that for all three kinds rather than assuming it, and asserted that a dish shared with every kitchen can still be marked.

What a refusal says

Every refusal carries the same sentence an unused number gets, so the answer cannot be used to find out which numbers are real. The tests check the names are absent from the body, not that a status code is present. With that route done, every write in the product that takes the number of an owned thing from a request body has now been driven, and the earlier sweep that asked about venues is matched by one that asks about companies.


Try it on tonight’s service.

Nothing to install, no card. Not better by the weekend? Close the tab.


This is about stock control — see how it works.