Blog / Billing software security: I audited my own app first
Journey · Security · Building
Billing software security: I audited my own app first

Before I showed DukaanKit to strangers, I tried to break it.
A shop's billing data is its sales, its staff and its customers. If I am going to ask shop owners to trust us with that, billing software security cannot be something I look at after the first complaint. So in the week before we started telling people about the product, I ran an audit of our own website, our server and our till apps against a 20-point checklist.
I used AI tools to do the checking faster, and I read every finding myself. The audit was read-only. Fixes came after, one at a time.
Here is what it found.
What a billing software security audit looks at
The checklist is not exotic. In plain words, it asks:
- Can someone guess their way into a login?
- Are passwords and PINs stored in a form nobody can read?
- Can a form on the website be tricked into sending data somewhere else?
- When the payment provider says "this shop has paid", do we check that the message really came from them?
- What is the browser allowed to load on our pages?
- Does the privacy policy tell the truth?
We ran it three times: once on the website, once on the server and back-office, once on the till apps.
What passed
Some things were already right:
- The common ways of attacking a website through its forms and its database did not work.
- Passwords and PINs are stored as salted hashes. Nobody can read them back, including us.
- Payment messages are checked against the payment provider's signature before a plan changes.
- There were no secret keys sitting inside the apps we ship.
- A forged admin login was refused.
What failed, and what we fixed first
Guessing a PIN was too easy. The limit on wrong tries was counted for each network, and kept in the server's memory. Change network, or wait for a restart, and the count started again. That is not good enough for a short PIN. Wrong tries are now counted for the shop and the person, saved properly, and each lockout lasts longer than the last. I wrote more about this in the post on 4-digit staff PINs.
A developer shortcut was left in our forms. The sign-up, payment and CRM request forms accepted a hidden setting in the page link that changed which server the form talked to. It was useful while testing. In the wrong hands, a specially made link could have sent what a shop owner typed, including a password, to someone else's server. It has been removed. The payment page now also refuses to follow any payment link that is not on our payment provider's own addresses.
The browser rules were too loose. A web page can tell the browser what it is allowed to load, where its forms may send data, and whether another site may show it inside a frame. Ours said too little. It now says all of it.
The privacy policy was not straight. It named the operator differently in different places. It did not name a person to complain to. It did not list the outside services that handle data for us, or say where the servers are. It has been rewritten. The operator is me, by name. There is a grievance contact. The service providers are listed. And it says plainly that our servers are in Europe, not in India.
The same kind of rule once broke our own sign-up
Security rules can also hurt you if you do not test them.
About two weeks before this audit, the browser rule on our site said a page could only talk to the website itself. But our sign-up and payment forms talk to our server, which lives at a different address. So the browser quietly blocked every one of those calls.
Nothing crashed. No error reached me. The page just told the person to check their internet. For a short while after self sign-up opened, nobody could sign up from the website, and I did not know.
I found it by loading the page in an automated browser and watching the request get blocked. The rule was fixed and tested again on the live page.
The lesson I took: a security rule is not finished when it is written. It is finished when the real sign-up, on the real site, still works with the rule switched on.
The habits that came out of it
The audit changed how changes go out:
- A backup before every change to the server. An earlier check in September had found there were no database backups at all. There are now nightly backups, plus a named one before each release.
- Fixes are built away from the live code and run through the full set of automated tests before they are released.
- The previous version is kept ready, so a bad release can be rolled back.
What is still on the list
The audit produced a longer list than this post. Some items are fixed. Some are in progress. I am not going to describe the open ones until they are closed. That is the whole point of fixing first and writing second.
If you run a shop: five questions to ask any billing software
You do not need to be technical to ask these.
- Who operates the service, by name, and how do I reach them?
- In which country is my data stored?
- Can anyone at your company see my staff's PINs or my password?
- When a staff member leaves, how do I switch off their access?
- If I stop using it, will you delete my data, and how soon?
If the answers are slow or vague, that tells you something. Most of ours are in the privacy policy, and you can ask me directly at support@dukaankit.in.
About the author. Arsalan Ahmed is building DukaanKit in Bengaluru and writes here about how it is going, including the parts that go wrong. Questions: WhatsApp +91 99165 16507 or support@dukaankit.in.