This repository hosts the WMS used by the Dakshin Vrindavan cow-care trust for their internal warehouse. It is published in the open so a successor admin can re-install it, but it is operationally a single-tenant install — there is no SaaS, no multi-tenant deployment, no public bug-bounty programme.
If you discover a security issue that could affect this codebase, please email office.dakshinvrindavan@gmail.com with:
- a brief description of the issue
- the smallest reproduction you can construct
- whether the fix appears to touch backup, restore, ACLs, or the audit trail
Please do not open a public GitHub issue for security defects. The trust
will acknowledge within seven days and ship a fix (or a documented mitigation)
on the same release cadence as functional work — see CHANGELOG.md and the
v19.0.<release> tags.
In scope:
- The seven custom addons (
addons/wms_*) - The deployment scripts (
scripts/*.ps1) - The
/wms/*controllers and JSON endpoints - The backup + restore + off-site copy pipeline
Out of scope:
- Defects in upstream Odoo 19 CE (report those at https://github.com/odoo/odoo)
- Defects in PostgreSQL, Windows, or the host OS
- Issues that require physical access to the prod machine
- Speculation about the trust's specific deployment topology
Only the latest v19.0.<release> tag is supported. Older tags are kept for
historical reference but do not receive security backports — upgrade.
The following controls are live in the current release. Internal hardening
notes live in docs/08-security.md; this section is the externally-facing
summary.
- Database manager UI hard-disabled. The Odoo database manager is shut
off at three layers:
list_db=Falseanddb_listing=Falsein the runtime config, and/web/database/*requests are redirected to/web/login?error=manager_disabled. There is no path to create, drop, duplicate, or back up a database through the web UI. - Role model. Three named base roles —
WMS / Store Keeper(group_wms_user),WMS / Manager(group_wms_manager),WMS / Repair Tech(group_repair_tech) — plus an optionalWMS / Buyer(group_buyer). Five capability sub-groups, all in thewms_locationnamespace:group_wms_can_scan_receive,group_wms_can_scan_issue,group_wms_can_file_damage,group_wms_can_submit_audit,group_wms_can_manage_catalog. - Health endpoint is token-gated.
/wms/healthis declaredauth='public'but gated by their.config_parameterwms_reports.health_token— a 32-hex secret auto-generated byinstall-native.ps1at install time. Tokens are compared viaodoo.tools.consteqand accepted either as?token=<value>or via theX-Health-Tokenheader. Missing or wrong token returns HTTP 401 with body{"status":"unauthorized"}. - Backups are encrypted and integrity-checked. Backups use
gpg --symmetric --cipher-algo AES256, with the passphrase supplied via a short-lived--passphrase-fileinvoked throughcmd /c(this avoids the PowerShell 5.1NativeCommandErrortriggered bygpg-agentstderr). Every artefact ships with a SHA-256 integrity checksum, and the weekly restore drill requirespg_restore --listto return ≥100 TOC entries before the drill is considered a pass. Every run writes an audit row towms_backup_audit. - Off-site copy is opt-in and failure-safe.
BACKUP_OFFSITE_DIRis read only from.env. If blank, off-site is disabled and the local backup still succeeds. If set, the destination is created if missing, the.gpgartefact is copied, the SHA-256 is re-verified at the destination, and a mirrored retention pass runs (-Retaindefaults to 14). Any off-site failure is logged but never fails the local backup. - Scheduled tasks run as SYSTEM.
WMS Daily Backup(4:30 PM daily),WMS Weekly Restore Drill(3:00 AM Sunday), andWMS Manual Backup(no trigger; run on demand by the in-app Backup Now wizard) run underNT AUTHORITY\SYSTEMwithLogonType=ServiceAccountandRunLevel=Highest. This meansBACKUP_OFFSITE_DIR, if set, must be a path reachable bySYSTEM(local disk or a UNC share with a SYSTEM-level credential). - Placeholder password deny-list at install.
install-native.ps1rejects obvious placeholder admin passwords —changeme,changeme123,admin,password, and similar — before bootstrapping the database, so a fresh install cannot accidentally ship to production with a known-bad credential. - Google Drive uploads use the minimal
drive.filescope. The optional Drive integration requests exactly one OAuth scope — the app can see and touch only files it created (theInventory_Backupstree), never the rest of the Drive or the Google account. The artefacts it uploads remain GPG AES256 ciphertext; the passphrase never leaves the box. - The Drive refresh token is DPAPI machine-scope. The OAuth refresh
token is stored at
config\gdrive-token.json.dpapi, encrypted with DPAPI LocalMachine scope so theNT AUTHORITY\SYSTEMscheduled tasks can read it but an exfiltrated copy is useless off-box. The file is gitignored; rotate it by re-runningscripts\setup-gdrive-auth.ps1. - Drive uploads are checksum-verified. Every upload must report a
Drive-side
sha256Checksummatching the local SHA-256 of the artefact before it counts as success; a mismatch deletes the remote file and the upload is retried. Drive errors never fail the local backup. - Drive restore into production is double-gated.
gdrive-restore.ps1refuses to restore into the livewmsdatabase unless BOTH-ForceAND the literal-ConfirmTarget wmsare passed — otherwise it exits 5 (PROD_GUARD) before any side effect.