01The challenge
A software house had built a store and inventory management system for the organisation: an Angular front end, a .NET 8 web API and SQL Server. The request was to host it on the internal network and give the developer remote access to keep working on it. Saying yes the usual way would have put unreviewed code next to production data, with an outside party holding a way in.
02Review before hosting
The review started before any access was granted. The vendor's demo instance published its API description and its compiled front end, which was enough to map every endpoint and spot risky defaults without logging in. A read-only view of the source followed.
The verdict was fair to the vendor: the application was well built. Permissions were checked per action, passwords were hashed properly, one-time codes came from a secure random source and data access was parameterised. Some alarming behaviour on the demo turned out to be switched on only in development mode, behind two separate gates.
- The real critical issue was secrets committed to the repository: database, token-signing and mail credentials. The fix is to rotate them, not just move them.
- Plain HTTP in the production configuration, no rate limit on login, scripts loaded from a public CDN at runtime, and long-lived tokens in browser storage made up the must-fix list sent to the developer.
03The environment
- Development, test and production on five separate virtual machines, each tier in its own network segment and its own firewall zone, with default deny between them.
- New segments routed at the firewall, not the core switch, so isolation is enforced where the policy lives. The specific deny rules sit above the older broad rules, or they would never fire.
- The developer reaches development only, through the organisation's existing SSL VPN on a dedicated gateway, from a small address pool, as a member of a vendors-only group. Test and production are unreachable from that path by design.
- IT builds and deploys from tagged releases. The vendor never deploys to test or production.
04The release gate
A blocking gate runs before anything is promoted: automated code review, a secrets scan, a dependency audit, and a scan of the built output for regressions that only appear after compilation. The first build it saw was refused with eleven findings, which is exactly what a gate is for. Nothing is deployed until it passes.
05Outcome
06What I would tell another organisation
The vendor's first login attempts all failed with that message, and every credential test came back clean. One line in the firewall log showed the gateway had refused the connection by source address before authentication was ever attempted. A second surprise followed: on this firewall, tunnel traffic does not carry the user's identity into policy matching, so a rule that names a user never matches. The control that works is the dedicated address pool combined with a gateway role that only the vendors group receives.
The client and vendor are not named, and network details are generalised.