Security / PHP Security (semgrep) (push) Successful in 1m14s
Lint / Deploy (push) Successful in 3s
Lint / PHP (phpcs PSR-12) (push) Successful in 19s
Lint / JS (eslint) (push) Successful in 8s
Lint / PHP requirements (version + extensions) (push) Successful in 24s
Lint / Notify on failure (push) Has been skipped
XSS / security:
- markdown.js: sanitize footnote labels to a safe slug before using them in
id/href attributes. Labels are captured before the HTML-escape pass, so a
label like x"><img onerror=...> broke out → stored XSS (the earlier quote-
escape fix didn't cover this path). Verified neutralized.
- RateLimitMiddleware: only trust X-Forwarded-For / X-Real-IP when REMOTE_ADDR
is a configured trusted proxy, and use the rightmost (proxy-appended) entry.
Previously any client could rotate XFF to escape the per-IP rate limit.
- .env.example: document TRUSTED_PROXIES so fresh deploys aren't fail-open on
the Authelia forward-auth spoofing protection.
Correctness:
- notifications.php: my previous assigned-to LIKE fix anchored only on '}', so
BULK assignments (logged {"assigned_to":N,"bulk_operation_id":..}) produced
no "assigned to you" notification — now matches both '}' and ',' delimiters.
- notifications.php: implement the documented @mention notifications (query
action_type='mention' rows for the current user); they were never delivered.
- NotificationHelper::notifyWatchers: guard unchecked prepare() so a missing
ticket_watchers table can't fatal the request after its DB write committed.
- AuditLogModel::getTicketTimeline: JSON_UNQUOTE the extracted ticket_id so
comment events actually match (string vs JSON-number comparison never did).
- AuditLogModel/audit_log.php: CSV export no longer silently truncates to the
1000-row UI cap; uses a dedicated higher export limit.
- DashboardView: quick-preview drawer read .ticket-link from the title cell
(which has none), so the title was always blank — use the cell text.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
48 lines
1.7 KiB
Bash
48 lines
1.7 KiB
Bash
# Tinker Tickets Environment Configuration
|
|
# Copy this file to .env and fill in your values
|
|
|
|
# Database Configuration
|
|
DB_HOST=10.10.10.50
|
|
DB_USER=tinkertickets
|
|
DB_PASS=your_password_here
|
|
DB_NAME=ticketing_system
|
|
|
|
# Matrix Webhook (optional - for notifications via matrix-hookshot)
|
|
# Set to your hookshot generic webhook URL, e.g.:
|
|
# https://matrix.lotusguild.org/webhook/<uuid>
|
|
MATRIX_WEBHOOK_URL=
|
|
|
|
# Matrix users to @mention on every new ticket (comma-separated Matrix user IDs)
|
|
# e.g. @jared:matrix.lotusguild.org,@alice:matrix.lotusguild.org
|
|
MATRIX_NOTIFY_USERS=
|
|
|
|
# Application Domain (required for Matrix webhook ticket links)
|
|
# Set this to your public domain (e.g., t.lotusguild.org)
|
|
APP_DOMAIN=
|
|
|
|
# Allowed Hosts for HTTP_HOST validation (comma-separated)
|
|
# Include all domains that can access this application
|
|
ALLOWED_HOSTS=localhost,127.0.0.1
|
|
|
|
# Trusted reverse proxy IP(s), comma-separated (e.g. the Authelia/nginx proxy).
|
|
# STRONGLY RECOMMENDED in production: Authelia forward-auth (Remote-User /
|
|
# Remote-Groups) and forwarded client IPs are only trusted when REMOTE_ADDR is
|
|
# in this list. Leaving it empty disables that protection (relies solely on
|
|
# network topology) and lets anything reaching PHP directly spoof admin login.
|
|
# Exact IP match only (no CIDR). Example: TRUSTED_PROXIES=10.10.10.27
|
|
TRUSTED_PROXIES=
|
|
|
|
# Timezone (default: America/New_York)
|
|
TIMEZONE=America/New_York
|
|
|
|
# LDAP / lldap (for user avatar lookups)
|
|
LDAP_ENABLED=true
|
|
LDAP_HOST=10.10.10.39
|
|
LDAP_PORT=3890
|
|
LDAP_BIND_DN=uid=tinker-tickets,ou=people,dc=example,dc=com
|
|
LDAP_BIND_PW=
|
|
LDAP_BASE_DN=dc=example,dc=com
|
|
LDAP_USER_BASE=ou=people,dc=example,dc=com
|
|
# How long to cache avatar images locally (seconds, default 3600)
|
|
AVATAR_CACHE_TTL=3600
|