diff --git a/apps/lubelogger/1.7.0/.env.sample b/apps/lubelogger/1.7.0/.env.sample new file mode 100644 index 000000000..30ea2f982 --- /dev/null +++ b/apps/lubelogger/1.7.0/.env.sample @@ -0,0 +1,6 @@ +PANEL_APP_PORT_HTTP=8080 +LUBELOGGER_ROOT_USERNAME=admin +LUBELOGGER_ROOT_PASSWORD=LubeLogger_Admin_2026! +TIME_ZONE=Etc/UTC +APP_DATA_DIR=./data +CONTAINER_NAME= diff --git a/apps/lubelogger/1.7.0/data.yml b/apps/lubelogger/1.7.0/data.yml new file mode 100644 index 000000000..53a507e42 --- /dev/null +++ b/apps/lubelogger/1.7.0/data.yml @@ -0,0 +1,86 @@ +additionalProperties: + formFields: + - default: 8080 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Port + labelZh: 端口 + label: + en: Port + zh: 端口 + zh-Hant: 埠 + ja: ポート + ko: 포트 + ru: Порт + ms: Port + pt-br: Porta + required: true + rule: paramPort + type: number + - default: admin + edit: true + envKey: LUBELOGGER_ROOT_USERNAME + labelEn: Root Username + labelZh: 根管理员用户名 + label: + en: Root Username + zh: 根管理员用户名 + zh-Hant: 根管理員使用者名稱 + ja: ルート管理者ユーザー名 + ko: 루트 관리자 사용자 이름 + ru: Имя корневого администратора + ms: Nama Pengguna Pentadbir Root + pt-br: Nome do Administrador Raiz + required: true + rule: paramCommon + type: text + - default: LubeLogger_Admin_2026! + edit: true + envKey: LUBELOGGER_ROOT_PASSWORD + labelEn: Root Password + labelZh: 根管理员密码 + label: + en: Root Password + zh: 根管理员密码 + zh-Hant: 根管理員密碼 + ja: ルート管理者パスワード + ko: 루트 관리자 비밀번호 + ru: Пароль корневого администратора + ms: Kata Laluan Pentadbir Root + pt-br: Senha do Administrador Raiz + random: true + required: true + rule: paramComplexity + type: password + - default: Etc/UTC + edit: true + envKey: TIME_ZONE + labelEn: Time Zone + labelZh: 时区 + label: + en: Time Zone + zh: 时区 + zh-Hant: 時區 + ja: タイムゾーン + ko: 시간대 + ru: Часовой пояс + ms: Zon Masa + pt-br: Fuso Horario + required: true + type: text + - default: ./data + edit: true + envKey: APP_DATA_DIR + labelEn: Data Directory + labelZh: 数据目录 + label: + en: Data Directory + zh: 数据目录 + zh-Hant: 資料目錄 + ja: データディレクトリ + ko: 데이터 디렉터리 + ru: Каталог данных + ms: Direktori Data + pt-br: Diretorio de Dados + required: true + type: text diff --git a/apps/lubelogger/1.7.0/data/.gitkeep b/apps/lubelogger/1.7.0/data/.gitkeep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/apps/lubelogger/1.7.0/data/.gitkeep @@ -0,0 +1 @@ + diff --git a/apps/lubelogger/1.7.0/docker-compose.yml b/apps/lubelogger/1.7.0/docker-compose.yml new file mode 100644 index 000000000..edcdaa6f1 --- /dev/null +++ b/apps/lubelogger/1.7.0/docker-compose.yml @@ -0,0 +1,46 @@ +services: + lubelogger: + image: "ghcr.io/hargata/lubelogger:v1.7.0@sha256:01bdb486af71e641c3ae41499e0412a21f2e04fa31b25c5c6531b42c112938e5" + container_name: ${CONTAINER_NAME} + restart: unless-stopped + init: true + user: "1000:1000" + networks: + - 1panel-network + ports: + - "${PANEL_APP_PORT_HTTP}:8080" + env_file: + - path: "${APP_DATA_DIR}/.lubelogger-auth.env" + required: false + environment: + - HOME=/App/data + - TZ=${TIME_ZONE} + - ASPNETCORE_HTTP_PORTS=8080 + - Kestrel__EndpointDefaults__Protocols=Http1 + - DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2SUPPORT=false + - LUBELOGGER_LOCALE_OVERRIDE=en_US + - LUBELOGGER_LOCALE_DT_OVERRIDE=en_US + read_only: true + tmpfs: + - /tmp:size=64m,mode=1777 + security_opt: + - no-new-privileges:true + cap_drop: + - ALL + healthcheck: + test: + - CMD-SHELL + - >- + bash -lc 'exec 3<>/dev/tcp/127.0.0.1/8080; exec 3>&-; exec 3<&-' + interval: 30s + timeout: 5s + start_period: 15s + retries: 3 + volumes: + - "${APP_DATA_DIR}:/App/data" + labels: + createdBy: "Apps" + +networks: + 1panel-network: + external: true diff --git a/apps/lubelogger/1.7.0/scripts/init.sh b/apps/lubelogger/1.7.0/scripts/init.sh new file mode 100755 index 000000000..144ab4632 --- /dev/null +++ b/apps/lubelogger/1.7.0/scripts/init.sh @@ -0,0 +1,123 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" +ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}" + +read_env_value() { + local key="$1" + [[ -f "$ENV_FILE" ]] || return 0 + local value + value="$(sed -n "s/^${key}=//p" "$ENV_FILE" | tail -n 1)" + case "$value" in + \"*\") value="${value#\"}"; value="${value%\"}" ;; + \'*\') value="${value#\'}"; value="${value%\'}" ;; + esac + printf '%s\n' "$value" +} + +configured_value() { + local key="$1" + local default_value="$2" + local value="${!key:-}" + if [[ -z "$value" ]]; then + value="$(read_env_value "$key")" + fi + printf '%s\n' "${value:-$default_value}" +} + +reject_control_characters() { + local name="$1" + local value="$2" + if [[ "$value" == *$'\n'* || "$value" == *$'\r'* ]]; then + printf '%s must not contain line breaks\n' "$name" >&2 + exit 1 + fi +} + +prepare_lubelogger() { + local raw path username password username_hash password_hash auth_file temp_file + + raw="$(configured_value APP_DATA_DIR ./data)" + username="$(configured_value LUBELOGGER_ROOT_USERNAME admin)" + password="$(configured_value LUBELOGGER_ROOT_PASSWORD '')" + + [[ -n "$raw" ]] || { + printf '%s\n' 'APP_DATA_DIR must not be empty' >&2 + exit 1 + } + if [[ "$raw" = /* ]]; then + printf '%s\n' 'APP_DATA_DIR must be relative to the application version directory' >&2 + exit 1 + fi + + path="$(realpath -m -- "$ROOT_DIR/${raw#./}")" + case "$path" in + "$ROOT_DIR"/*) ;; + *) + printf '%s\n' 'APP_DATA_DIR must remain inside the application version directory' >&2 + exit 1 + ;; + esac + + install -d -m 0750 "$path" + path="$(realpath -e -- "$path")" + case "$path" in + "$ROOT_DIR"/*) ;; + *) + printf '%s\n' 'APP_DATA_DIR resolves outside the application version directory' >&2 + exit 1 + ;; + esac + + [[ -n "$username" && ${#username} -le 128 ]] || { + printf '%s\n' 'LUBELOGGER_ROOT_USERNAME must contain 1 to 128 characters' >&2 + exit 1 + } + [[ ${#password} -ge 12 && ${#password} -le 256 ]] || { + printf '%s\n' 'LUBELOGGER_ROOT_PASSWORD must contain 12 to 256 characters' >&2 + exit 1 + } + reject_control_characters LUBELOGGER_ROOT_USERNAME "$username" + reject_control_characters LUBELOGGER_ROOT_PASSWORD "$password" + + username_hash="$(printf '%s' "$username" | sha256sum | cut -d ' ' -f 1)" + password_hash="$(printf '%s' "$password" | sha256sum | cut -d ' ' -f 1)" + [[ "$username_hash" =~ ^[0-9a-f]{64}$ && "$password_hash" =~ ^[0-9a-f]{64}$ ]] || { + printf '%s\n' 'Failed to generate LubeLogger credential hashes' >&2 + exit 1 + } + + auth_file="$path/.lubelogger-auth.env" + if [[ -L "$auth_file" ]]; then + printf '%s\n' 'LubeLogger authentication file must not be a symbolic link' >&2 + exit 1 + fi + if [[ -e "$auth_file" && ! -f "$auth_file" ]]; then + printf '%s\n' 'LubeLogger authentication path must be a regular file' >&2 + exit 1 + fi + + umask 077 + temp_file="$(mktemp "$path/.lubelogger-auth.env.tmp.XXXXXX")" + trap 'rm -f -- "${temp_file:-}"' EXIT + printf '%s\n' \ + 'EnableAuth=true' \ + "UserNameHash=$username_hash" \ + "UserPasswordHash=$password_hash" \ + 'DisableRegistration=true' \ + 'LUBELOGGER_OPEN_REGISTRATION=false' >"$temp_file" + chmod 0600 "$temp_file" + chown 1000:1000 "$temp_file" + mv -f -- "$temp_file" "$auth_file" + trap - EXIT + + chown 1000:1000 "$path" + chmod 0750 "$path" + [[ "$(stat -c '%a' -- "$auth_file")" = 600 ]] || { + printf '%s\n' 'LubeLogger authentication file permissions must be 0600' >&2 + exit 1 + } +} + +prepare_lubelogger diff --git a/apps/lubelogger/1.7.0/scripts/uninstall.sh b/apps/lubelogger/1.7.0/scripts/uninstall.sh new file mode 100755 index 000000000..ab8a8d674 --- /dev/null +++ b/apps/lubelogger/1.7.0/scripts/uninstall.sh @@ -0,0 +1,2 @@ +#!/bin/bash +docker-compose down --volumes diff --git a/apps/lubelogger/1.7.0/scripts/upgrade.sh b/apps/lubelogger/1.7.0/scripts/upgrade.sh new file mode 100755 index 000000000..692e341e2 --- /dev/null +++ b/apps/lubelogger/1.7.0/scripts/upgrade.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail + +"$(dirname "$0")/init.sh" diff --git a/apps/lubelogger/README.md b/apps/lubelogger/README.md new file mode 100644 index 000000000..874bce09b --- /dev/null +++ b/apps/lubelogger/README.md @@ -0,0 +1,71 @@ +# LubeLogger + +## 产品介绍 + +LubeLogger 是一个自托管的车辆管理工具,用于记录车辆保养、维修、加油、里程、提醒、升级、税费、碰撞和相关文档。 + +## 主要功能 + +- 管理多辆车辆及其里程、燃油和费用记录 +- 维护保养计划、提醒和历史记录 +- 保存车辆图片、票据和其他文档 +- 支持 CSV 导入导出、报表和可选的通知集成 + +## 访问说明 + +安装后通过 `http://<服务器 IP>:<端口>` 访问,并使用安装时设置的根管理员用户名和密码登录。安装脚本只把凭据的 SHA-256 哈希传给应用,默认启用认证并关闭开放注册和邀请注册页面。 + +上游根用户认证使用普通 SHA-256,而不是专用密码哈希算法;必须保留 1Panel 自动生成的高强度随机密码,不要使用短密码或复用密码。LubeLogger 1.7.0 的登录接口没有请求限速,认证 Cookie 也没有显式设置 `Secure`、`HttpOnly` 或 `SameSite`。明文 HTTP 端口只适合可信局域网;公网访问必须使用可信 HTTPS 反向代理、阻止公网直接访问应用端口,并在代理层增加登录限速。 + +## 数据持久化 + +`APP_DATA_DIR` 挂载到 `/App/data`,保存 LiteDB 数据库、图片、文档、配置和会话 DataProtection 密钥。该路径必须位于应用版本目录内,默认值为 `./data`;初始化脚本拒绝绝对路径、目录逃逸和认证文件符号链接,并把目录交给 UID/GID `1000:1000`。卸载脚本不会删除绑定目录中的用户数据,升级或迁移前仍应单独备份。 + +## 安全与漏洞说明 + +- 容器以 UID/GID `1000:1000` 运行,根文件系统只读,丢弃全部 Linux capabilities,并启用 `no-new-privileges`;CPU、内存和进程上限由 1Panel 的应用资源设置统一管理。应用只监听内部明文 HTTP/1;TLS 应由 1Panel 或其他可信反向代理终止。可选 WebHook、OIDC、SMTP 和通知集成默认未配置,包内同时禁用 .NET HTTP 客户端的 HTTP/2 支持。 +- 对固定镜像执行的 2026-07-28 Trivy 扫描发现 `0` 个 Critical 和 `5` 个 High,均来自镜像中的 .NET 10.0.9,修复版本为 10.0.10。当前上游 v1.7.0 镜像尚未包含修复,应在上游发布使用 .NET 10.0.10 或更高版本的镜像后尽快更新。 +- `CVE-2026-47302` 是 XML 加密解析导致的资源耗尽。LubeLogger 源码和默认依赖路径没有使用 `System.Security.Cryptography.Xml`、`System.Xml` 或 `EncryptedXml`,默认部署未发现可达入口。 +- `CVE-2026-50524` 是畸形 TLS 握手导致的拒绝服务,`CVE-2026-50528` 是 `SslStream` 授权绕过。此包内 Kestrel 只提供 HTTP/1 明文服务,不处理入站 TLS;默认也未配置 OIDC、Webhook、SMTP 或通知等外部 TLS 集成。用户启用这些集成后应把远端视为额外风险边界。 +- `CVE-2026-50651` 是 .NET HTTP/2 客户端处理 SETTINGS/PING ACK flood 时可能内存耗尽。LubeLogger 有可选的出站 HTTP 客户端路径,但此包通过 `DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2SUPPORT=false` 禁用 HTTP/2,并默认不配置相关集成。 +- `CVE-2026-57108` 是解析特制 X.509 证书时的类型混淆拒绝服务。默认内部 HTTP 服务不解析入站证书;打开 Sponsors 页面或启用外部 TLS 集成时会产生出站证书解析路径,因此该项不能视为完全不可达。只连接可信端点,并在修复镜像可用后立即升级。 + +## Introduction + +LubeLogger is a self-hosted vehicle management application for tracking maintenance, repairs, fuel, mileage, reminders, upgrades, taxes, collisions, and related documents. + +## Features + +- Manage multiple vehicles and their mileage, fuel, and cost records +- Track maintenance plans, reminders, and service history +- Store vehicle images, receipts, and other documents +- Import and export CSV data, generate reports, and configure optional notifications + +## Access And Authentication + +Access the service at `http://:` and sign in with the root username and password selected during installation. The initialization script passes only SHA-256 credential hashes to the application. Authentication is enabled by default, while open registration and the invitation registration page are disabled. + +Upstream root authentication uses plain SHA-256 rather than a password-specific KDF. Keep the high-entropy password generated by 1Panel; do not use a short or reused password. LubeLogger 1.7.0 does not rate-limit login requests, and its authentication cookie does not explicitly set `Secure`, `HttpOnly`, or `SameSite`. Direct plain-HTTP access is suitable only on a trusted LAN. For public access, use a trusted HTTPS reverse proxy, block public access to the application port, and add login rate limiting at the proxy. + +## Data Persistence + +`APP_DATA_DIR` is mounted at `/App/data` and stores the LiteDB database, images, documents, configuration, and DataProtection session keys. It must remain inside the application version directory and defaults to `./data`. The initializer rejects absolute paths, directory escapes, and a symlinked authentication file, then assigns the directory to UID/GID `1000:1000`. Uninstall does not remove bind-mounted user data; back it up before upgrades or migration. + +## Security And Vulnerability Notes + +- The container runs as UID/GID `1000:1000`, uses a read-only root filesystem, drops all Linux capabilities, and enables `no-new-privileges`. CPU, memory, and process limits are managed through 1Panel's application resource settings. The application serves internal plain HTTP/1 only; terminate TLS at 1Panel or another trusted reverse proxy. Optional webhook, OIDC, SMTP, and notification integrations are not configured, and .NET HTTP client HTTP/2 support is disabled. +- A 2026-07-28 Trivy scan of the pinned image found 0 Critical and 5 High findings, all in .NET 10.0.9. The fixes are in .NET 10.0.10. Upstream v1.7.0 has not yet published an image with those fixes; update promptly when it does. +- `CVE-2026-47302` is an XML-encryption parsing resource-exhaustion issue. LubeLogger source and default dependencies do not use `System.Security.Cryptography.Xml`, `System.Xml`, or `EncryptedXml`, so no default reachable entry point was found. +- `CVE-2026-50524` is a malformed TLS-handshake denial of service, and `CVE-2026-50528` is an `SslStream` authorization bypass. Kestrel serves only internal plain HTTP/1 in this package and does not process inbound TLS. OIDC, webhook, SMTP, and notification integrations are also unconfigured by default. Enabling them adds a separate outbound TLS risk boundary. +- `CVE-2026-50651` is an HTTP/2 client SETTINGS/PING ACK flood that may cause an out-of-memory condition. LubeLogger has optional outbound HTTP client paths, but this package sets `DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2SUPPORT=false` and leaves those integrations unconfigured. +- `CVE-2026-57108` is a type-confusion denial of service while parsing a crafted X.509 certificate. The internal HTTP service does not parse inbound certificates. Opening the Sponsors view or enabling outbound TLS integrations does create certificate-parsing paths, so this finding is not considered completely unreachable. Connect only to trusted endpoints and upgrade as soon as a fixed image is available. + +## References + +- Project: +- Release: +- Container source: +- Deployment documentation: +- Configuration documentation: +- License: (MIT) +- .NET advisories: , , , , diff --git a/apps/lubelogger/data.yml b/apps/lubelogger/data.yml new file mode 100644 index 000000000..60a0f08dc --- /dev/null +++ b/apps/lubelogger/data.yml @@ -0,0 +1,30 @@ +name: LubeLogger +tags: + - Tool +title: 车辆维护、保养与油耗记录工具 +description: 车辆维护、保养与油耗记录工具 +additionalProperties: + key: lubelogger + name: LubeLogger + tags: + - Tool + shortDescZh: 车辆维护、保养与油耗记录工具 + shortDescEn: Vehicle maintenance, service, and fuel mileage tracking + description: + en: Vehicle maintenance, service, and fuel mileage tracking + zh: 车辆维护、保养与油耗记录工具 + zh-Hant: 車輛維護、保養與油耗記錄工具 + ja: 車両の整備、サービス、燃費を記録するツール + ko: 차량 정비, 서비스 및 연비 기록 도구 + ru: Учет обслуживания, ремонта и расхода топлива автомобилей + ms: Penjejakan penyelenggaraan, servis dan penggunaan bahan api kenderaan + pt-br: Controle de manutencao, servicos e consumo de veiculos + type: website + crossVersionUpdate: true + limit: 0 + website: https://lubelogger.com/ + github: https://github.com/hargata/lubelog + document: https://docs.lubelogger.com/ + architectures: + - amd64 + - arm64 diff --git a/apps/lubelogger/logo-LICENSE.txt b/apps/lubelogger/logo-LICENSE.txt new file mode 100644 index 000000000..0cb339f3b --- /dev/null +++ b/apps/lubelogger/logo-LICENSE.txt @@ -0,0 +1,25 @@ +LubeLogger logo + +Source: https://github.com/hargata/lubelog/blob/v1.7.0/wwwroot/defaults/lubelogger_icon_192.png +License: MIT +Copyright (c) 2024 Hargata Softworks + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/apps/lubelogger/logo.png b/apps/lubelogger/logo.png new file mode 100644 index 000000000..97494140b Binary files /dev/null and b/apps/lubelogger/logo.png differ