Skip to content

Trust & legal

Security

AVRA decides whether a product is genuine. That answer is only worth something if the machine behind it can be described. This page describes it.

Every claim below names the mechanism that makes it true and where to check it. We do not hold a security certification. When we start one, it will appear in In progress at the bottom of this page with a date, and it will stay there until a certificate exists.

What the platform does, and how you can check it

Tenancy and access

  • One customer can never read another customer's data.

    Mechanism
    Every query is scoped to the caller's tenant before it runs. A request for another tenant's record answers 404, never 403 — a 403 would confirm the record exists.
    Check it
    Ask us for a login on a second tenant and try, or ask us for the test name.
  • Console access is invite-only. There is no public sign-up.

    Mechanism
    Every login is invited by email and the person invited chooses their own password. A login is disabled from the same screen, and its session dies with it.
    Check it
    Visit /login. There is no sign-up link, and the page says why.
  • The company that prints your labels cannot take over your account.

    Mechanism
    Your brand's owner login is invited by email and you set its password yourself, so the printer never holds it. The owner invites your employees; the printer runs no part of your team.
    Check it
    Ask us for the test name.
  • Passwords are hashed, and resetting one ends every session issued before it.

    Mechanism
    bcrypt at cost 12 in production, enforced by a startup guard that refuses to boot below it. Reset tokens are single-use, hashed at rest, and expire in 60 minutes. Sessions issued before a reset or change are rejected by a tokens_valid_from check.
    Check it
    Reset your password on one browser and refresh another.
  • The forgot-password screen never tells an attacker whether an email exists.

    Mechanism
    One neutral response for every address, rate-limited to 5 requests a minute per IP.
    Check it
    Try it with an address that is not ours.

The codes themselves

  • A code cannot be guessed.

    Mechanism
    10 characters from a 31-character alphabet with no look-alikes, drawn from the operating system's cryptographic random source — roughly 8 × 10¹⁴ possible codes, against a rate limit of 120 scans a minute.
    Check it
    Ask us for the test name.
  • Batch Activation — a stolen print file verifies nothing.

    Mechanism
    Codes are created dead. A batch moves generated → exported → activated, and only the console's Activate step, taken after printing QC, makes a code answer anything but We can't verify this code. An overrun, a leaked file or a stolen roll all scan that way.
    Check it
    Generate a batch in a sandbox tenant, download the file, and scan a code before activating.
  • Dual Code — a photographed shelf label cannot be replayed.

    Mechanism
    Two factors on one label. The visible QR answers "this label is real" and is meant to be scanned by anyone. The hidden code under the scratch panel claims the unit exactly once. Photographing the shelf QR copies the half that claims nothing.
    Check it
    Ask us for the test name.
  • Two people scanning the same code at the same instant cannot both be told "genuine".

    Mechanism
    The claim is one atomic conditional UPDATE — the count is raised only where it is still below the limit — not a read-then-write. The reward claim on top of it has race tests that only run on PostgreSQL; the scan claim's own race is not separately tested, and we say so.
    Check it
    Ask us for the test name.
  • The scratch code under the scratch panel is not stored anywhere, in any form.

    Mechanism
    It is derived: HMAC-SHA256(per-batch secret, label number), where the secret is encrypted with the brand's own data key. Verification re-derives and compares in constant time; the export re-derives the same way. There is no column to leak.
    Check it
    Ask us for the test name.
  • Five wrong attempts at a hidden code lock that label for a day on that phone or network — and a wrong code is recorded as a counterfeit signal, not a typo.

    Mechanism
    A fake pack carries a fake code. scratch_wrong is its own scan result and feeds the alert engine; the lock is its own result, scratch_locked.
    Check it
    Ask us for the test name.
  • Print files stop being downloadable once the batch is live.

    Mechanism
    Partners download freely until activation. Afterwards the file is platform-admin only, every download is audited, and the file is purged 30 days after activation. For Dual Code batches, the in-console QR preview follows the same rule and audits every look.
    Check it
    Ask us for the test name. Each look at hidden codes is the batch.codes_view action in your audit extract.

Money and the ledger

  • The credit ledger cannot be edited. Only appended.

    Mechanism
    credit_ledger is insert-only. A refund is a second row against the same batch, never an edit of the first, so a balance cannot drift from its history.
    Check it
    Open the Wallet page and reconcile the balance against the rows yourself.
  • A retried upload can never generate the same batches twice.

    Mechanism
    Batch generation from an upload is idempotent on a request_key; the same key returns the existing batch instead of generating a second one.
    Check it
    Ask us for the test name.
  • Two batches generated at the same instant cannot overspend a balance.

    Mechanism
    One atomic conditional UPDATE deducts the credits; the generation that loses the race is refused.
    Check it
    Ask us for the test name.
  • Reward money moves on the brand's own payment account, never through AVRA's.

    Mechanism
    Each brand connects its own Razorpay X or Cashfree account. AVRA holds no float and is not in the money's path. If AVRA disappears tomorrow, the account is still the brand's.
    Check it
    The gateway's webhook points at a route of your brand's own, /api/public/payouts/{provider}/webhook/{brand_id}. Ask us for the test name.
  • The wallet is an append-only ledger with one writer.

    Mechanism
    Every movement — earn, redeem, payout, reversal, adjust, expire — goes through a single ledger.post() that locks the membership row before it writes.
    Check it
    Ask us for the test name.
  • Payout credentials cannot be read back out of the system, by anyone, including us.

    Mechanism
    Credentials are envelope-encrypted per brand under a master key that is not in the database backups. They reach the payment adapter as an object whose repr prints no value, and the Settings screen says they cannot be read back.
    Check it
    Save a key, then try to read it.

The scan path

  • The consumer verdict page makes no third-party request.

    Mechanism
    The typeface is self-hosted, the logo is inline SVG, the city lookup is an offline database file on our own disk, and the India map is a local GeoJSON with no tile provider. Nothing on /s/, /b/, /c/ or /me/ reaches another company's server.
    Check it
    Open the verdict page with your network tab recording and count the origins. There is one.
  • A buyer's location is approximated from their IP against a file we hold — their IP is never sent to a geolocation service.

    Mechanism
    An offline DB-IP City Lite database, refreshed monthly: the city and the point the database gives for it, never the phone's GPS. If the lookup fails it never fails the scan.
    Check it
    Ask us for the test name.
  • The scan endpoint is rate-limited without breaking shared mobile networks.

    Mechanism
    120 requests a minute per IP — high on purpose, because Indian mobile carriers put thousands of real buyers behind one address, and a naive limit would block a market.
    Check it
    Ask us for the test name.
  • Our error tracking cannot leak your codes.

    Mechanism
    The error tracker is scrubbed at the source: stack-frame locals are never attached, URLs and query strings are redacted, request bodies never leave the server, and the scrubber fails closed — a partially scrubbed event is dropped. The reason is specific: a dual-mode label's hidden code can appear in a URL.
    Check it
    Ask us for the test name.

Data handling

  • Every sensitive action is written to an insert-only audit log.

    Mechanism
    Logins, credit issues, batch generations, activations, blocks and cancellations, print-file downloads, code previews, payout-account changes, claim voids, exports, and member searches.
    Check it
    Ask us for an audit extract for your own tenant.
  • No raw SQL in the application.

    Mechanism
    Queries go through the ORM; only database migrations run SQL directly. Every string input is length-limited by a schema at the edge.
    Check it
    It is our written engineering standard. Ask us for it.
  • A spreadsheet we produce cannot execute a formula on your machine.

    Mechanism
    Every CSV data cell we emit passes one guard that neutralises a leading =, +, -, @, tab, CR or LF — print files included. Excel exports write every data cell as a string. The gaps are listed under In progress.
    Check it
    Ask us for the test name: it generates a batch named =cmd|' /c calc'!A1.
  • An uploaded image cannot carry anything but pixels.

    Mechanism
    Images are re-encoded server-side to WebP with camera metadata stripped, and capped at 12 megapixels.
    Check it
    Upload a photo with GPS EXIF and read the stored file.
  • Timestamps are stored in UTC, everywhere, and displayed in IST.

    Mechanism
    One utcnow() helper server-side; one lib/ist.ts on the display side.
    Check it
    Ask us for the test name.
  • The database is not reachable from the internet.

    Mechanism
    PostgreSQL runs in a private subnet, reached over a peered network, with SSL required by the database server. It has no public endpoint.
    Check it
    Ask us for the deployment notes.
  • Backups run nightly and can be restored to a point in time.

    Mechanism
    Managed automated backups with a 7-day point-in-time window, plus our own nightly pg_dump to object storage with the restore recipe in the script's own header.
    Check it
    Ask us for the deployment notes.

What GENUINE actually means

When the verdict page says GENUINE, it is asserting four things and nothing more:

  1. This code was generated by AVRA for this brand, and is not a string that happens to look like one.
  2. Its batch was activated by a person after printing QC. Before that moment this code answered We can't verify this code.
  3. This verification is within the batch's verification limit — the label has not already been claimed by someone else.
  4. Nobody has blocked the batch since.

It is not asserting that the physical object in your hand is the one the label was stuck to, or that the pack has not been opened. No QR code can assert either. Those are jobs for something physical — a hologram or OVD foil, a destructible face stock, a VOID-release adhesive, a tamper band, a seal that tears — and it is why AVRA is sold alongside the pack rather than instead of it. Which formats can carry which is stated per substrate for printers and packaging companies.

Suspicious scans, named as rules

  • One code verified from many distinct networks, beyond its limit, inside a week

    What it usually means
    A code was photographed off a shelf label and reprinted onto a run of fakes
    What happens
    A clone-attack alert on your dashboard naming the code and the cities
  • Ten or more of your not-yet-activated labels scanned in a week

    What it usually means
    Your print file leaked, or a roll left the print floor early
    What happens
    An unactivated-codes alert — the earliest warning in the system, because those codes have not shipped
  • Five or more scans a week of codes AVRA never generated

    What it usually means
    Somebody is printing invented codes onto packaging that imitates yours
    What happens
    A fake-sighting alert to the platform admin, who routes it to the brand
  • A wrong hidden code typed under a real shelf QR

    What it usually means
    A fake pack with a guessed code under the panel
    What happens
    Recorded as a counterfeit signal, not a typo. Five wrong tries lock that label for 24 hours on that phone or network
  • A reward claim that breaks a rolling 24-hour cap

    What it usually means
    One person working a pile of packs, or a recycled-code scheme
    What happens
    The claim is held, not rejected — money stops before it leaves, and a person releases or rejects it
  • A reward campaign that has spent its budget

    What it usually means
    Not fraud — but the same stop
    What happens
    No claim card is shown at all, and the brand is emailed at 80% and 100%

What we do not claim to catch: a counterfeiter who buys genuine product, scrapes the codes from the labels and never sells the originals. No code-based system catches that, ours included. Batch Activation and per-unit claiming raise the cost of a fake from “photograph one label” to “buy every unit you intend to copy”, which is the honest description of what this defends.

What happens with no signal

A phone with no signal cannot verify anything, and we will not pretend otherwise. The verdict comes from our server, because the answer depends on facts that cannot live on the label: whether the batch was activated, whether this code has been claimed already, and whether the same code is being scanned in four cities at once. A label that could answer offline would be a label a counterfeiter could answer with too.

What we do instead: the verdict page is built to load on a slow connection on a cheap Android phone, with no third-party requests, and a buyer in a basement can walk outside and scan again. Re-scanning your own product never consumes a verification.

Your data: ownership, residency, retention

The scan data is the brand's

Every scan of your labels, every warranty registration, every reward claim and every fake report belongs to you. AVRA processes it on your instruction. We do not sell it, do not license it, do not aggregate it into a market report, and do not show it to another brand — including a brand that shares your partner.

What you can take as a file today, without asking us: warranty registrations, payout statements, the TDS file and your print files, from the console, and an Excel of each rewards list — members (with their wallet balances), claims, redemptions, disputes and payouts — as the list with your filters and search, up to 200 rows, phone numbers masked. Scan history, the credit ledger, fake reports and batch states are on screen but not yet a file — the export list says which is which, and until those exist we produce them on request.

If you leave, we close your account when you ask. You have 30 days to take your files. Sixty days after closing, your shoppers' personal details are erased (a warranty in force holds them until it ends, plus one year) and your own account's KYC documents are deleted; today a partner's KYC documents are deleted by hand on request. The reward, redemption and payout records stay, without your shoppers' details. Those are financial records, not marketing data.

And no label on a shelf is ever called fake. Every code verifies for three years from the day its batch is switched on, whatever happens to your plan. After that it shows a neutral “verification period has ended” page with your care number — never “fake” or “expired”. A person holding a real product must not be told it is fake because two companies stopped doing business. The rest is on what happens if you leave.

We process your data in India

The database, the application servers and the print files run in AWS Mumbai (ap-south-1). The database has no public endpoint. Nothing is replicated outside India by us.

One caveat we state rather than bury: if you download a statement of your own payouts and your parent company is outside India, you have made that transfer, not us — and you are responsible for it. The statements carry masked phone numbers and no PANs.

  • Amazon Web Services

    What it handles
    Application servers, database, backups, print-file storage
    Where
    India (ap-south-1)
  • Meta / WhatsApp Business Platform

    What it handles
    The one-time code that signs a member in, and the transactional message templates
    Where
    Meta's own infrastructure
  • Your own payment gateway (Razorpay X or Cashfree)

    What it handles
    Reward payouts, on your account and under your contract. AVRA never holds the funds.
    Where
    India
  • Our email provider

    What it handles
    Password-reset and alert email
    Where
    Not yet confirmed in writing — see In progress
  • Sentry, when error tracking is switched on

    What it handles
    Error reports, scrubbed before they leave our server
    Where
    Not yet confirmed in writing — see In progress

The city lookup is not a sub-processor. We do not call a geolocation service. We hold a database file and read it. Your buyers' IP addresses never leave our servers.

How long we keep it

  • A scan: the full IP address

    Kept
    30 days
    Then
    Truncated to the network prefix. The counterfeit rule counts networks over a week, and a prefix serves that as well as a host address.
  • A scan: the browser user-agent

    Kept
    90 days
    Then
    Reduced to a family, such as Chrome/Android.
  • A scan: the browser identifier

    Kept
    400 days
    Then
    Cleared. The cookie itself lasts a year; the column outlives it by a month.
  • A scan: the row itself

    Kept
    For ever
    Then
    It is the product. After the sweeps above it holds no personal data.
  • A reward claim: the full IP address

    Kept
    30 days
    Then
    Truncated to the network prefix, as a scan's.
  • A reward claim: the browser identifier

    Kept
    400 days
    Then
    Cleared, as a scan's.
  • A reward claim: the location the buyer chose to share

    Kept
    30 days
    Then
    Erased.
  • A fake report: the reporter's phone number

    Kept
    90 days
    Then
    Erased.
  • A fake report: the location the reporter chose to share

    Kept
    90 days
    Then
    Erased.
  • A print file, after the batch is activated

    Kept
    30 days
    Then
    Purged.
  • Rewards, redemptions, payouts

    Kept
    8 years
    Then
    Financial record — Indian tax law.
  • A member's profile (name, UPI id, PAN)

    Kept
    Until they close the account
    Then
    Erased on close; the phone number stays on the financial record.
  • A brand that leaves: its shoppers' details (name, UPI id, PAN, the shop they named)

    Kept
    60 days after the account is closed
    Then
    Erased. The money records stay, without them.
  • A warranty registered with a brand that leaves

    Kept
    Until the warranty ends, plus one year
    Then
    Then erased as above.
  • A brand's KYC documents, on its own account

    Kept
    60 days after the account is closed
    Then
    Deleted.

These sweeps run daily on a background worker and each one is idempotent. They are a job, not a promise on a page. Ask us for the test name.

What your partner can and cannot see

The company that prints your labels can see:

  • The brands, products and batches it created for you, and the labels it printed.
  • How many credits it bought and spent on your account, and when each batch was generated and by whom.
  • Your scan counts, your genuine rate, your scans by city, and your alerts.
  • Fake reports filed against your products — it works them on your behalf, and every status change is audited.
  • Print files for your batches, until the batch is activated. After that, only a platform admin can download them, and every download is audited.
  • Your rewards member list, claims and ledger — only if you admit it. This is a switch you own and it is off by default.

It cannot see:

  • Any other partner's anything. The request answers 404.
  • Your payout credentials, or your members' PANs. Both are encrypted and are not readable by staff of any kind.
  • Your hidden or scratch codes after activation. For Dual Code batches, the console's QR preview follows the same download rule and audits every look.
  • Your rewards programme at all, unless you admitted it.

Your buyers are told this too. Our consumer notice states, in the consent a member ticks, that the partner who prints your labels may administer the programme for you. We do not disclose to you something we hide from them.

How we count visits to this website

This site runs no analytics today. When we switch on our own copy of Umami it will be described here, and it will never load on the verification pages.

Reporting a vulnerability

Email connect@avrascan.com. We do not run a PGP key, and we would rather say so than publish one nobody reads.

What you get from us: an acknowledgement from a person, an assessment, and word when it is fixed. If you want credit, we will name you here. If you want to stay anonymous, that is fine too.

What we ask: give us a reasonable window before publishing, and test against your own tenant and your own codes. Do not run scanners against the consumer verdict path — a live scan burns a real buyer's verification, and we would rather give you a sandbox tenant. Ask and you will have one the same day.

We do not pay bounties. We would rather say so than let you spend a weekend expecting one.

In scope: avrascan.com and every subdomain, the console, the consumer verdict pages, and the public brand report links. Out of scope: our customers' own websites, our partners' own systems, the payment gateways (report those to the gateway), and anything requiring physical access to a print floor. Machine-readable: /.well-known/security.txt.

In progress, not yet true

No target date is set for any of these yet. When one is, it appears here, and the item stays until it is done.

  • Two-factor authentication on console logins

    Why it matters
    Today a console account is a password. For a platform that can block a live batch, that is one factor too few.
    Target
    Not set
  • Rate limiting that survives more than one server

    Why it matters
    The limiter holds its counters in one process's memory. It works, and it will stop working the day we run two application servers.
    Target
    Not set
  • Uptime monitoring, backup-failure alerting, and a restore drill we have actually run

    Why it matters
    Backups run. We have not yet proven a restore under time pressure, and an untested backup is a hope.
    Target
    Not set
  • An independent penetration test

    Why it matters
    Everything on this page is our own account of our own system.
    Target
    Not set
  • A signed data-processing agreement template, and a partner agreement

    Why it matters
    Today these are negotiated per deal. They should be downloadable.
    Target
    Not set
  • Naming the hosting region of our error tracker and email provider

    Why it matters
    Both are listed below without a region, because we have not confirmed it in writing.
    Target
    Not set
  • The formula guard on every header row

    Why it matters
    A certificate batch's column names are typed by its issuer, and the print file writes them as its header row, in the CSV and in each Excel part, without the guard. The masked phone column of the payout statement skips it too.
    Target
    Not set
  • The QR-preview lock on single-code batches

    Why it matters
    On a single-code label the visible code is the one that verifies. After activation its print file is platform-admin only, but the console's QR preview still shows a partner or brand login up to 100 of its codes, and the look is not audited.
    Target
    Not set
  • Two-way payout reconciliation on Cashfree

    Why it matters
    Cashfree publishes no list-transfers API, so our nightly both-ways payout check cannot run for a brand on that gateway. We say so on the Settings screen when the gateway is chosen.
    Target
    Not fixable by us; it needs the gateway

Not on this list, deliberately: ISO 27001 and SOC 2. It will appear when an auditor is engaged, with the auditor's name and the expected certificate date.

Print one batch and scan it yourself.

The fastest way to judge this is a sheet of real labels and a phone.

Trust, made visible.