Compare commits

...

7 commits

Author SHA1 Message Date
Jan Böhmer
57a0dfdbdb Fixed phpstan issue
Some checks failed
Build assets artifact / Build assets artifact (push) Has been cancelled
Docker Image Build / build (linux/amd64, amd64, ubuntu-latest) (push) Has been cancelled
Docker Image Build / build (linux/arm/v7, armv7, ubuntu-24.04-arm) (push) Has been cancelled
Docker Image Build / build (linux/arm64, arm64, ubuntu-24.04-arm) (push) Has been cancelled
Docker Image Build (FrankenPHP) / build (linux/amd64, amd64, ubuntu-latest) (push) Has been cancelled
Docker Image Build (FrankenPHP) / build (linux/arm/v7, armv7, ubuntu-24.04-arm) (push) Has been cancelled
Docker Image Build (FrankenPHP) / build (linux/arm64, arm64, ubuntu-24.04-arm) (push) Has been cancelled
Static analysis / Static analysis (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, mysql) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, mysql) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, mysql) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.5, mysql) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, postgres) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, postgres) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, postgres) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.5, postgres) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, sqlite) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, sqlite) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, sqlite) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.5, sqlite) (push) Has been cancelled
Docker Image Build / merge (push) Has been cancelled
Docker Image Build (FrankenPHP) / merge (push) Has been cancelled
2026-06-07 22:49:41 +02:00
Jan Böhmer
61dcc99597
New Crowdin updates (#1383)
* New translations messages.en.xlf (German)

[ci skip]

* New translations messages.en.xlf (German)

[ci skip]

* New translations messages.en.xlf (German)

[ci skip]

* New translations messages.en.xlf (English)

[ci skip]

* New translations messages.en.xlf (German)

[ci skip]

* New translations messages.en.xlf (English)

[ci skip]
2026-06-07 22:47:22 +02:00
Jan Böhmer
cf8826a906 Bumped version to 2.12.1 2026-06-07 22:43:33 +02:00
Jan Böhmer
4b00541dd6 Improved APP_SECRET warning message 2026-06-07 22:43:06 +02:00
Jan Böhmer
93ab410857 Added documentation about changing the APP_SECRET env on installation 2026-06-07 22:37:47 +02:00
Jan Böhmer
cb28afcdf5 Moved APP_SECRET value to the top of .env 2026-06-07 22:28:29 +02:00
Jan Böhmer
f888e10827 Show a warning if using the default APP_SECRET value 2026-06-07 22:26:45 +02:00
11 changed files with 184 additions and 20 deletions

5
.env
View file

@ -1,6 +1,10 @@
#### Part-DB Configuration
# See https://docs.part-db.de/configuration.html for documentation of available options
# Change this to a random value to secure your installation! You can generate a random string with "openssl rand -hex 16"
# Share that value with nobody and keep it secret
APP_SECRET=a03498528f5a5fc089273ec9ae5b2849
###################################################################################
# Database settings
###################################################################################
@ -158,7 +162,6 @@ CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$'
###> symfony/framework-bundle ###
APP_ENV=prod
APP_SECRET=a03498528f5a5fc089273ec9ae5b2849
APP_SHARE_DIR=var/share
###< symfony/framework-bundle ###

View file

@ -1 +1 @@
2.12.0
2.12.1

View file

@ -114,10 +114,21 @@ bundled with Part-DB. Set `DATABASE_MYSQL_SSL_VERIFY_CERT` if you want to accept
* `datastructure_create`: Creation of a new data structure (e.g. category, manufacturer, ...)
* `CHECK_FOR_UPDATES` (default `1`): Set this to 0 if you do not want Part-DB to connect to GitHub to check for new
versions, or if your server cannot connect to the internet.
* `APP_SECRET` (env only): This variable is a configuration parameter used for various security-related purposes,
particularly for securing and protecting various aspects of your application. It's a secret key that is used for
cryptographic operations and security measures (session management, CSRF protection, etc..). Therefore this
value should be handled as confidential data and not shared publicly.
* `APP_SECRET` (env only): A secret key used by Symfony for cryptographic operations — signing cookies, generating
CSRF tokens, and other security-sensitive tasks. **You must change this from the default value before exposing
Part-DB to any network.** The default value shipped with Part-DB is publicly known; leaving it in place would allow
an attacker to forge signed cookies and bypass CSRF protection.
Generate a secure value and add it to `.env.local`:
```bash
echo "APP_SECRET=$(openssl rand -hex 32)" >> .env.local
```
For Docker, pass it in the `environment` section of your `docker-compose.yaml`:
```yaml
environment:
- APP_SECRET=<output of: openssl rand -hex 32>
```
Part-DB displays a warning on the homepage (visible to administrators only) as long as the default value is in use.
* `SHOW_PART_IMAGE_OVERLAY`: Set to 0 to disable the part image overlay, which appears if you hover over an image in the
part image gallery
* `IPN_SUGGEST_REGEX`: A global regular expression, that part IPNs have to fulfill. Enforce your own format for your users.

View file

@ -47,7 +47,10 @@ services:
- DATABASE_URL=sqlite:///%kernel.project_dir%/var/db/app.db
# In docker env logs will be redirected to stderr
- APP_ENV=docker
# Secret key used to sign cookies and CSRF tokens. MUST be changed to a unique random value before going live!
# Generate one with: openssl rand -hex 32
- APP_SECRET=CHANGE_ME
# Uncomment this, if you want to use the automatic database migration feature. With this you have you do not have to
# run the doctrine:migrations:migrate commands on installation or upgrade. A database backup is written to the uploads/
# folder (under .automigration-backup), so you can restore it, if the migration fails.
@ -89,7 +92,11 @@ services:
4. Customize the settings by changing the environment variables (or adding new ones). See [Configuration]({% link
configuration.md %}) for more information.
5. Inside the folder, run
5. Make sure to change the `APP_SECRET` variable to a unique random value (32 characters). You can generate one with the following command:
```bash
openssl rand -hex 32
```
6. Inside the folder, run
```bash
docker-compose up -d
@ -100,7 +107,7 @@ services:
> Otherwise Part-DB console might use the wrong configuration to execute commands.
6. Create the initial database with
7. Create the initial database with
```bash
docker exec --user=www-data partdb php bin/console doctrine:migrations:migrate
@ -108,7 +115,7 @@ docker exec --user=www-data partdb php bin/console doctrine:migrations:migrate
and watch for the password output
6. Part-DB is available under `http://localhost:8080` and you can log in with the username `admin` and the password shown
8. Part-DB is available under `http://localhost:8080` and you can log in with the username `admin` and the password shown
before
The docker image uses a SQLite database and all data (database, uploads, and other media) is put into folders relative to
@ -121,6 +128,7 @@ If you want to use MySQL as a database, you can use the following docker-compose
{: .warning }
> You have to replace the values for MYSQL_ROOT_PASSWORD and MYSQL_PASSWORD with your own passwords!!
> You have to change MYSQL_PASSWORD in the database section and for the DATABASE_URL in the partdb section.
> Generate a random string for APP_SECRET.
```yaml
version: '3.3'
@ -142,14 +150,19 @@ services:
environment:
# Replace SECRET_USER_PASSWORD with the value of MYSQL_PASSWORD from below
- DATABASE_URL=mysql://partdb:SECRET_USER_PASSWORD@database:3306/partdb
# Secret key used to sign cookies. MUST be changed to a unique random value before going live!
# Generate one with: openssl rand -hex 32
- APP_SECRET=CHANGE_ME
# In docker env logs will be redirected to stderr
- APP_ENV=docker
# Uncomment this, if you want to use the automatic database migration feature. With this you do not have to
# run the doctrine:migrations:migrate commands on installation or upgrade. A database backup is written to the uploads/
# folder (under .automigration-backup), so you can restore it, if the migration fails.
# This feature is currently experimental, so use it at your own risk!
# - DB_AUTOMIGRATE=true
# Uncomment this, if you want to use the automatic database migration feature. With this you do not have to
# run the doctrine:migrations:migrate commands on installation or upgrade. A database backup is written to the uploads/
# folder (under .automigration-backup), so you can restore it, if the migration fails.
# This feature is currently experimental, so use it at your own risk!
# - DB_AUTOMIGRATE=true
# You can configure Part-DB using the webUI or environment variables
# However you can add any other environment configuration you want here

View file

@ -136,6 +136,15 @@ cp .env .env.local
In your `.env.local` you can configure Part-DB according to your wishes and overwrite web interface settings.
A full list of configuration options can be found [here](../configuration.md).
{: .important }
> **Change `APP_SECRET` before going live.** The default value shipped with Part-DB is publicly known and must not be
> used in production — it would allow an attacker to forge signed cookies and bypass CSRF protection.
> Generate a new value and add it to your `.env.local`:
> ```bash
> echo "APP_SECRET=$(openssl rand -hex 32)" >> .env.local
> ```
> or edit the file with a text editor and add a new value for `APP_SECRET` (you can generate a random value with `openssl rand -hex 32`).
Please check that the configured base currency matches your mainly used currency, as
this can not be changed after creating price information.

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
*/
namespace App\Command;
use App\Services\System\AppSecretChecker;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
@ -33,7 +34,9 @@ use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;
#[AsCommand('partdb:check-requirements', 'Checks if the requirements Part-DB needs or recommends are fulfilled.')]
class CheckRequirementsCommand extends Command
{
public function __construct(protected ContainerBagInterface $params)
public function __construct(protected ContainerBagInterface $params,
private readonly AppSecretChecker $appSecretChecker
)
{
parent::__construct();
}
@ -121,6 +124,16 @@ class CheckRequirementsCommand extends Command
$io->success('Debug mode disabled.');
}
//Check if APP_SECRET has been changed from the default
if ($io->isVerbose()) {
$io->comment('Checking APP_SECRET...');
}
if ($this->appSecretChecker->isInsecureSecret()) {
$io->warning('APP_SECRET is set to the default value shipped with Part-DB. This is a security risk! Generate a new secret (e.g. using "openssl rand -hex 32") and set it as APP_SECRET in your .env.local file.');
} elseif (!$only_issues) {
$io->success('APP_SECRET has been changed from the default value.');
}
}
protected function checkPHPExtensions(SymfonyStyle $io, bool $only_issues = false): void

View file

@ -24,6 +24,7 @@ namespace App\Controller;
use App\DataTables\LogDataTable;
use App\Entity\Parts\Part;
use App\Services\System\AppSecretChecker;
use App\Services\System\BannerHelper;
use App\Services\System\GitVersionInfoProvider;
use App\Services\System\UpdateAvailableFacade;
@ -36,8 +37,11 @@ use Symfony\Component\Routing\Attribute\Route;
class HomepageController extends AbstractController
{
public function __construct(private readonly DataTableFactory $dataTable, private readonly BannerHelper $bannerHelper)
{
public function __construct(
private readonly DataTableFactory $dataTable,
private readonly BannerHelper $bannerHelper,
private readonly AppSecretChecker $appSecretChecker,
) {
}
@ -84,6 +88,8 @@ class HomepageController extends AbstractController
'new_version_available' => $updateAvailableManager->isUpdateAvailable(),
'new_version' => $updateAvailableManager->getLatestVersionString(),
'new_version_url' => $updateAvailableManager->getLatestVersionUrl(),
'insecure_app_secret' => $this->appSecretChecker->isInsecureSecret(),
'suggested_app_secret' => $this->appSecretChecker->isInsecureSecret() ? $this->appSecretChecker->generateSecret() : null,
]);
}
}

View file

@ -0,0 +1,63 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2024 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace App\Services\System;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
/**
* Checks whether APP_SECRET has been changed from the default value shipped with Part-DB.
*/
final readonly class AppSecretChecker
{
/** Known default/example secrets that must not be used in production. */
public const INSECURE_SECRETS = [
'a03498528f5a5fc089273ec9ae5b2849', // default in .env
'318b5d659e07a0b3f96d9b3a83b254ca', // default in .env.dev
'CHANGE_ME' //example secret used in documentation and error messages
];
public function __construct(
#[Autowire('%kernel.secret%')]
private string $appSecret,
) {
}
/**
* @return bool True if the app secret is one of the known insecure default secrets, false otherwise.
*/
public function isInsecureSecret(): bool
{
return in_array($this->appSecret, self::INSECURE_SECRETS, true);
}
/**
* Generates a new random app secret that can be used to replace the default insecure one.
* @return string
* @throws \Random\RandomException
*/
public function generateSecret(): string
{
//Symfony docs recommend 32 characters for the app secret, which are 16 random bytes when hex-encoded.
return bin2hex(random_bytes(16));
}
}

View file

@ -85,6 +85,16 @@
{% block content %}
{% if insecure_app_secret and is_granted('@system.server_infos') %}
<div class="alert alert-warning" role="alert">
<h5><i class="fa-solid fa-triangle-exclamation fa-fw"></i> {% trans %}system.app_secret.insecure.title{% endtrans %}</h5>
<p class="mb-1">{% trans %}system.app_secret.insecure.message{% endtrans %}</p>
<p class="mb-0">{% trans %}system.app_secret.insecure.suggestion{% endtrans %}
<br><code>APP_SECRET={{ suggested_app_secret }}</code></p>
<small>{% trans %}update_manager.new_version_available.only_administrators_can_see{% endtrans %}</small>
</div>
{% endif %}
{% if is_granted('@system.show_updates') %}
{{ nv.new_version_alert(new_version_available, new_version, new_version_url) }}
{% endif %}

View file

@ -64,7 +64,7 @@
<unit id="KSFhj_3" name="currency.iso_code.caption">
<segment state="translated">
<source>currency.iso_code.caption</source>
<target>ISO Code</target>
<target>ISO-Code</target>
</segment>
</unit>
<unit id="UqMuNZQ" name="currency.symbol.caption">
@ -13647,5 +13647,23 @@ Buerklin-API-Authentication-Server:
<target>Aktiviert das Browser-Plugin für diese Instanz.</target>
</segment>
</unit>
<unit id="JqcvhX_" name="system.app_secret.insecure.title">
<segment state="translated">
<source>system.app_secret.insecure.title</source>
<target>Unsicheres APP_SECRET</target>
</segment>
</unit>
<unit id="XSSYWTJ" name="system.app_secret.insecure.message">
<segment state="translated">
<source>system.app_secret.insecure.message</source>
<target>Die Umgebungsvariable &lt;code&gt;APP_SECRET&lt;/code&gt; ist auf den Standardwert gesetzt, der mit Part-DB ausgeliefert wird. Dies stellt ein Sicherheitsrisiko dar! Setzen Sie sie in Ihrer Datei &lt;code&gt;.env.local&lt;/code&gt; oder &lt;code&gt;docker-compose.yaml&lt;/code&gt; auf einen neuen Zufallswert.</target>
</segment>
</unit>
<unit id="e7.f3m0" name="system.app_secret.insecure.suggestion">
<segment state="translated">
<source>system.app_secret.insecure.suggestion</source>
<target>Sie können diesen zufällig generierten Wert verwenden (geben Sie ihn niemandem weiter):</target>
</segment>
</unit>
</file>
</xliff>

View file

@ -13649,5 +13649,23 @@ Buerklin-API Authentication server:
<target>When enabled users with the info provider permission can submit pages to Part-DB and retrieve them later.</target>
</segment>
</unit>
<unit id="JqcvhX_" name="system.app_secret.insecure.title">
<segment state="translated">
<source>system.app_secret.insecure.title</source>
<target>Insecure APP_SECRET</target>
</segment>
</unit>
<unit id="XSSYWTJ" name="system.app_secret.insecure.message">
<segment state="translated">
<source>system.app_secret.insecure.message</source>
<target>The &lt;code&gt;APP_SECRET&lt;/code&gt; environment variable is set to the default value shipped with Part-DB. This is a security risk! Set it to a new random value in your &lt;code&gt;.env.local&lt;/code&gt; or &lt;code&gt;docker-compose.yaml&lt;/code&gt; file.</target>
</segment>
</unit>
<unit id="e7.f3m0" name="system.app_secret.insecure.suggestion">
<segment state="translated">
<source>system.app_secret.insecure.suggestion</source>
<target>You can use this randomly generated value (share it with nobody):</target>
</segment>
</unit>
</file>
</xliff>