This is an example written for a fictional company. It shows the format and the level of detail of an audit report. It does not describe a real client or a real system.
The code audit page explains what an audit covers and how it runs.
- Client: Example Wholesale Ltd (fictional)
- System: order processing system, used by about 40 staff
- Report date: October 2026
Summary for decision-makers
The order processing system works, and the code behind it is in better condition than its age suggests. The risk lies in what it runs on and in how little could be recovered after a failure. The database software stopped receiving security fixes in July 2026 and the server’s operating system follows in January 2027. Backups never leave the server room and nobody has tested restoring one. The source code and the account that sends the emailed reports are held in the name of the developer who left in 2023. None of this calls for a replacement: we recommend that Example Wholesale Ltd modernises the system in stages, starting with recovery and ownership, then moving it onto supported software.
What we looked at
- The source code: an ASP.NET Web Forms application of about 85,000 lines, written around 2017.
- The SQL Server 2016 database, 38 GB in size.
- The single Windows Server 2016 machine in the server room that runs both.
- The nightly import from the accounting package and the six reports sent by email.
- Backups, scheduled jobs and the way a change is released.
- Who holds the accounts the system depends on.
Findings in priority order
| No. | Finding | Why it matters | Priority |
|---|---|---|---|
| 1 | Backups stay in the server room. No restore has been tested. | A fire or a theft could take the system and its backups together. | Now |
| 2 | SQL Server 2016 stopped receiving security fixes on 14 July 2026. | New weaknesses in the database software will not be fixed. | Now |
| 3 | Windows Server 2016 reaches the end of support on 12 January 2027. | The server has three months of security fixes left. | Now |
| 4 | Three pages on the live server differ from the source code. Releases are made by hand with no written steps. | A release from the source code would undo those changes. | Now |
| 5 | The code repository and the account that sends the emailed reports are personal accounts of the former developer. | The company could lose access to its own code and reports. | Now |
| 6 | The application targets .NET Framework 4.6.1, a version that left support on 26 April 2022. | It runs today on the newer .NET Framework installed on the server, but it cannot use current versions of its libraries until it is rebuilt for 4.8. | This quarter |
| 7 | The database password sits in a readable settings file, for an account with full administrative rights. | Anyone who can read the file controls every record. | This quarter |
| 8 | Two search screens build database queries from the text a user types. | A user could read or change data they should not see. | This quarter |
| 9 | The nightly accounting import failed on nine nights in three months and alerted nobody. | Orders are priced from out-of-date figures until someone notices. | This quarter |
| 10 | There are no automated tests. Pricing rules sit in four very large files. | Changes to pricing are slow and easy to get wrong. | Later |
| 11 | The application builds from the source code in the repository. | Any competent team can work on it. | In good order |
| 12 | The database is well designed and grows by about 4 GB a year. | It can move to a newer version without redesign. | In good order |
The three things to do first
1. Make the system recoverable
What we saw: a backup runs every night to a second disk in the same server, and a weekly copy goes to a storage device in the same room. We found no record of a restore.
What we recommend: send an encrypted copy off site each night. Restore one backup to a separate machine, and record how long it takes and how old the data is.
Size: 2 to 4 days.
2. Take ownership of the code and the accounts
What we saw: the repository and the mail account are personal accounts of the former developer. Three pages were edited directly on the live server after the last recorded change.
What we recommend: move the repository and the mail account to accounts owned by Example Wholesale Ltd. Bring the three pages back into the repository, and write down the release steps.
Size: 3 to 5 days.
3. Move to a supported server and database
What we saw: SQL Server 2016 and Windows Server 2016 share one machine bought in 2017. Microsoft sells paid Extended Security Updates for SQL Server 2016 until 17 July 2029, but the operating system has its own date.
What we recommend: build a new server on Windows Server 2022 and SQL Server 2022, supported until 14 October 2031 and 11 January 2033. Rebuild the application for .NET Framework 4.8 as part of the move. Rehearse the move with a copy of the data before switching.
Size: 10 to 15 days.
A plan for the next 90 days
First 30 days. Off-site backups and a tested restore. Repository and mail account in the company’s name. Live server and source code matching. Release steps written down.
Days 31 to 60. New server built. Application rebuilt for .NET Framework 4.8 and tested on it with a copy of the data. Named staff check order entry, the nightly import and each emailed report. Database password and the two search screens fixed.
Days 61 to 90. Switch to the new server at a quiet time, keeping the old one as a fallback for two weeks. Add an alert for a failed import. Agree the next stage.
What can wait
- Replacing the Web Forms screens. Web Forms remains supported on .NET Framework 4.8, so there is no deadline.
- Automated tests for the pricing rules. Add them when those rules next change.
- Two slow queries behind the order search. They cost users a few seconds.
- Five third-party libraries that are old but have no published vulnerabilities.
What is in good order
- The code is consistent and readable, with clear names and one style throughout.
- The application builds from source. Two libraries were missing from the repository and had to be copied from the live server.
- The database has sensible keys and constraints, which protect the data from many kinds of error.
- Staff sign in with their Windows accounts, so the system stores no passwords of its own. It can be reached only from the office network.
How we worked
- We had read-only access to the source code, the server and a copy of the database. Nothing on the live system was changed.
- We built the application from source on a clean machine.
- We ran automated analysis for known vulnerabilities and for the size and complexity of the code.
- We read by hand the parts that matter: login, order entry, pricing, the import and the reports.
- We could not see the accounting package’s side of the import or the former developer’s own machine. An audit is not a penetration test.