b9a737419cd135fea499e24480d9bdf9b651a33f
Found while auditing the owner-scope SQL fix from the last commit:
getQrcode() queried purely by id with no scope applied at all (not even
the buggy old form), and editQrcode()/deleteQrcode() both call
getQrcode() first but then run their own unscoped where('id', $id) for
the actual update/delete. Net effect: any authenticated admin/user with
edit or delete rights could view, edit, or delete *any other tenant's*
qr code just by guessing/incrementing the id - in the static/dynamic
edit forms, the bulk download/delete endpoint, and the single delete
flow alike.
Fixed by applying qr_apply_owner_scope() in getQrcode() (covers the
edit-prefill and delete-lookup paths, and exits via failure() before
reaching the actual write query if out of scope) and adding it directly
to the update/delete queries in editQrcode()/deleteQrcode() too, for
defense in depth rather than relying solely on the earlier check.
Verified with a two-tenant scenario (separate admin accounts): before
the fix admin B could view/edit-prefill/delete admin A's qr code, after
the fix all three are correctly blocked (404 / "not found" / delete is
silently a no-op) and admin A's code is untouched.
Users.php and presets.php were checked too and already scope correctly
via different, unaffected patterns - this was isolated to the two
Qrcode classes.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fo3DiRRpmz2DXjD7Uzhc8u
Self-hosted, open-source QR code generator.
QRForge creates and manages static and dynamic QR codes from a clean, responsive control panel. It's a security-hardened, actively maintained fork of the original PHP Dynamic Qr code project by Giandonato Inverso, built on AdminLTE.
- Try it free: qr.ensembia.com - fully functional OSS test
instance. Self-service signup isn't live yet, so log in with the temporary shared demo
account
admin/adminin the meantime. - Commercial VIP edition (self-service create-rights, logo-embedded QR codes): www.qrforge.eu.
- Self-host it yourself: this repository, MIT-licensed.
Features
- Dynamic QR codes with a database-backed URL shortener
- Create, edit, delete, enable/disable the redirect
- Download any time, bulk download/delete
- Batch-generate from a CSV file
- 16 static QR code types: Text, Email, Phone, SMS, WhatsApp, Skype, Location, vCard, Event/calendar, Bookmark, WiFi (incl. WPA3), PayPal, Bitcoin, 2FA, App Link (Android intent / universal links), Bluetooth
- QR code styling: 6 export formats, foreground/background color, 4 precision levels, 10 sizes, optional label text below the code (custom font + size), optional icon shown above the code, save/load your own style presets
- Address search (OpenStreetMap Nominatim) for Location QR codes
- Built-in QR scanner (camera or image upload, decodes entirely client-side)
- Installable as a PWA
- Role-based access:
super(full access + user management),admin(scoped to their own codes and sub-users),user(read-only, with optional per-account create rights and view toggles set by an admin) - Dashboard with QR/scan statistics and a 7-day activity chart
- CSRF protection, login rate limiting, session hardening, audit log
- Docker Compose setup, both a dev image and a production Nginx + PHP-FPM image
What is included
- PHP 8.4 application source
- Database schema + migrations
- Docker Compose files (dev and production)
- CSS/JS assets
Setup with Docker Compose
- Clone this repository.
- Copy
.env.exampleto.envand set a realDATABASE_PASSWORD/MYSQL_ROOT_PASSWORD. - Start the stack:
docker compose up -d --build - Open
http://localhostand log in withsuperadmin/superadmin. You'll be required to set a new password on first login.
For a production deployment behind a reverse proxy, use
docker-compose.prod.yml (Nginx + PHP-FPM) instead of the dev stack.
Credits
- Originally forked from PHP Dynamic Qr code by Giandonato Inverso.
- QR code rendering powered by chillerlan/php-qrcode.
- Admin panel UI built on AdminLTE.
License
MIT - see LICENSE.
Languages
JavaScript
79.3%
PHP
12.3%
CSS
5.1%
HTML
3.2%
Dockerfile
0.1%