Skip to content

How RentnRide is secured

What this platform actually enforces to keep one rental company data separate from another, and to keep a staff account from becoming somebody else. Written from the code, and deliberately silent where the code is silent.

In effect from
Last updated

Section 1One company cannot see another company data

This is the guarantee everything else rests on, and it is the failure that would matter most, so it is enforced in three places rather than trusted once.

The company is derived from the address, never sent by the client
Every request resolves to a company by looking up the web address it arrived on. Not a field in the request body, not a query parameter, not a forwarded-host header a client can set, and not a token claim on its own. A client cannot name the company whose data it wants, because naming it is not an input the server reads.
The signed token is cross-checked against that address
Every staff token carries the company it was issued for. If a token issued for one company arrives on another company address the request is refused outright and an audit row is written, so an attempt is not merely blocked — it leaves a trace somebody can find later.
Every query carries the company key, and a build check proves it
Every read and write against business data is scoped by `company_id`, all of them go through a single database seam rather than talking to the database directly, and a check that runs on every change fails the build if a handler reads a company identifier from client input. A missed scope is caught before it can ship, not after.
A suspended company stops at the door
Account status is resolved in the same step as the company itself, so suspending a tenant takes effect on the next request rather than depending on every handler remembering to check.

Section 2Staff sign-in

Staff sign in with a phone number and a PIN on a device the company owner paired. A PIN is a short secret, so the design assumes it is guessable and makes the guess useless.

PIN hashes are salted per staff member
The PIN itself is never stored. What is stored is a SHA-256 hash of the staff member own account identifier combined with the PIN, so the same four digits chosen by two people produce two unrelated hashes and one precomputed table cannot open every account on the platform. An unsalted PIN hash is treated as a build failure here, not a code-review note.
Access tokens last fifteen minutes
The token a signed-in staff member carries expires in fifteen minutes. A copied token is therefore useful for minutes, not for months, and revoking access does not depend on the thief cooperating.
Refresh tokens are device-bound and rotate on every use
Each paired device holds its own refresh token, and only a hash of it — salted with the device identifier — is stored, so a leaked table cannot be replayed as-is. Every successful refresh issues a new token and invalidates the old one in the same conditional write.
A reused refresh token revokes the device
If a superseded token is ever presented — by a thief, or by the real device after a thief has used it — the device is revoked rather than the request quietly failing. The staff member signs in again with their PIN; whoever copied the token has nothing. A silent failure would leave the attacker copy working, which is the entire reason this check exists.

Section 3Uploaded photographs and documents

Handover photographs, damage photographs and vehicle documents are stored as files in object storage. Four things are enforced on the way in.

The file name is built by the server, never by the client
Every stored object is named with the owning company identifier as its first path segment, and the rest is generated. The client supplies no part of the name and the file extension comes from the verified content type rather than from the uploaded filename — a filename is untrusted input, and a path that climbs out of a directory is also a filename.
The size cap is applied before the file is held
A declared length over the ceiling is refused without reading a byte, and one that lies costs at most the ceiling before the upload is abandoned. Reading the whole file and then measuring it means already having paid for it.
Counts and request rates are capped, and refusals are the safe direction
The number of objects per booking is capped, counted from the storage itself rather than from a number that could drift, and upload requests are capped per address and per company. An upload path is a spending path, so every cap here fails closed and each one emits a record when it trips.
How this differs from the intended design, plainly
The intended design has the browser upload straight to storage using a pre-signed link, so the bytes never pass through our servers. That needs a storage access key pair which is not provisioned, so today the bytes DO pass through the server that applies the checks above. Every guarantee in this section holds either way; the change when it lands is about cost and throughput, not about what is enforced.

Section 4The audit log

Actions that change records are written to an audit log: which staff account, which record, which action, when, and the request identifier that ties it to the server logs for that moment.

The actor is taken from the verified session token and never from the request body, so it cannot be forged by whoever is making the request. The rows are not deleted, by anyone, including us — a log the subject of an entry can remove is not a log. What is stored alongside an entry passes an allowlist filter first, so an audit row never becomes a copy of a request body with customer details in it.

Section 5Failures, and what a failure is allowed to reveal

Errors are typed with stable codes rather than thrown as raw messages, and a stack trace never reaches a user. What a person sees is a message in their own language and a request identifier they can quote; what we see is the same identifier attached to the stored fault.

Fault records are deduplicated so a crash loop increments a counter instead of writing a row per occurrence, and every payload passes an allowlist filter before storage that removes phone numbers, names, identity-document values, tokens, PINs and file addresses. That filter is tested against realistically shaped data, because a redactor nobody has watched fail is not a redactor.

Section 6This website in particular

The site you are reading has no database, no storage, no key-value store and no secret of any kind attached to it. It cannot reach tenant data, so a flaw in it cannot expose any — the strongest form of the isolation rule is having nothing to isolate.

It also collects nothing. There is no form on any page, no address that accepts a submission, and its content security policy forbids the browser from submitting a form at all — three independent layers, so that one mistake does not quietly create an intake path. Everything it loads comes from this site alone.

Section 7Reporting something you have found

If you have found a problem, tell us before you tell anyone else, and we will not take any legal action against you for having looked, provided you did not access, alter or keep anybody data beyond what was needed to demonstrate it.

Send it to the security address below where one is published. This site also serves a machine-readable contact file at the standard well-known address when a contact has been configured. We acknowledge within three working days, tell you what we found, and are glad to name you when it is fixed if you would like that. There is no paid reward programme, and saying so is fairer than letting you find out after the work.

Section 8What this page does not claim

No external security audit or penetration test has been carried out on this platform, and it holds no security certification. Saying otherwise is common on pages like this one and is checkable, which is why it is not said here.

Everything above describes the platform. It cannot describe the phone a staff member left unlocked on a counter, a PIN written on the wall, or an account shared between four people — and those are where real losses at a rental counter actually start. The terms of service ask each company to give every staff member their own account for exactly that reason.

A published contact address for this domain is not live yet. Until it is, renters should contact the rental company they booked with, and rental companies should use the channel their account was opened through.

About this document

Every mechanism on this page was read out of the source before it was described, and the one place the implementation falls short of the intended design is written into section 3 rather than left out. This page has not been reviewed by an external security assessor or by a lawyer qualified in Bangladesh.

Back to top