diff --git a/phpstan.neon b/phpstan.neon
index 0021dc712..58d51a908 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -58,7 +58,7 @@ parameters:
PackageUpdateJob: 'array{id: int, update_equal_refs: bool, delete_before: bool, force_dump: bool, source: string}'
GitHubUserMigrateJob: 'array{id: int, old_scope: string, new_scope: string}'
SecurityAdvisoryJob: 'array{source: string}'
- FilterListJob: 'array{list: string}'
+ FilterListJob: 'array{list: string, source: string}'
JobResult: 'array{status: \App\Entity\Job::STATUS_*, message: string, vendor?: string, details?: string, exceptionMsg?: string, exceptionClass?: class-string<\Throwable>, results?: array{hooks_setup: int, hooks_failed: array, hooks_ok_unchanged: int}}'
ErroredResult: 'array{status: \App\Entity\Job::STATUS_ERRORED, message: string, exception: \Throwable}'
diff --git a/src/Audit/Display/AuditLogDisplayFactory.php b/src/Audit/Display/AuditLogDisplayFactory.php
index a1cb9aa76..b2a7a3101 100644
--- a/src/Audit/Display/AuditLogDisplayFactory.php
+++ b/src/Audit/Display/AuditLogDisplayFactory.php
@@ -17,6 +17,7 @@
use App\Entity\AuditRecord;
use App\Entity\User;
use App\FilterList\FilterLists;
+use App\FilterList\FilterSources;
use Symfony\Bundle\SecurityBundle\Security;
class AuditLogDisplayFactory
@@ -222,6 +223,7 @@ public function buildSingle(AuditRecord $record): AuditLogDisplayInterface
$record->attributes['entry']['package_name'],
$record->attributes['entry']['version'],
FilterLists::from($record->attributes['entry']['list']),
+ FilterSources::from($record->attributes['entry']['source']),
$record->attributes['entry']['reason'] ?? $record->attributes['entry']['category'],
$this->buildActor($record->attributes['actor'] ?? null),
$record->ip
@@ -231,6 +233,7 @@ public function buildSingle(AuditRecord $record): AuditLogDisplayInterface
$record->attributes['entry']['package_name'],
$record->attributes['entry']['version'],
FilterLists::from($record->attributes['entry']['list']),
+ FilterSources::from($record->attributes['entry']['source']),
$record->attributes['entry']['reason'] ?? $record->attributes['entry']['category'],
$this->buildActor($record->attributes['actor'] ?? null),
$record->ip
diff --git a/src/Audit/Display/FilterListEntryAddedDisplay.php b/src/Audit/Display/FilterListEntryAddedDisplay.php
index 4a58a3d60..089000f54 100644
--- a/src/Audit/Display/FilterListEntryAddedDisplay.php
+++ b/src/Audit/Display/FilterListEntryAddedDisplay.php
@@ -14,6 +14,7 @@
use App\Audit\AuditRecordType;
use App\FilterList\FilterLists;
+use App\FilterList\FilterSources;
readonly class FilterListEntryAddedDisplay extends AbstractAuditLogDisplay
{
@@ -22,6 +23,7 @@ public function __construct(
public string $packageName,
public string $version,
public FilterLists $list,
+ public FilterSources $source,
public string $reason,
ActorDisplay $actor,
?string $ip,
diff --git a/src/Audit/Display/FilterListEntryDeletedDisplay.php b/src/Audit/Display/FilterListEntryDeletedDisplay.php
index 08afd450d..8deba7526 100644
--- a/src/Audit/Display/FilterListEntryDeletedDisplay.php
+++ b/src/Audit/Display/FilterListEntryDeletedDisplay.php
@@ -14,6 +14,7 @@
use App\Audit\AuditRecordType;
use App\FilterList\FilterLists;
+use App\FilterList\FilterSources;
readonly class FilterListEntryDeletedDisplay extends AbstractAuditLogDisplay
{
@@ -22,6 +23,7 @@ public function __construct(
public string $packageName,
public string $version,
public FilterLists $list,
+ public FilterSources $source,
public string $reason,
ActorDisplay $actor,
?string $ip,
diff --git a/src/Command/UpdateFilterListCommand.php b/src/Command/UpdateFilterListCommand.php
index 164fd4b91..6ab7cfc99 100644
--- a/src/Command/UpdateFilterListCommand.php
+++ b/src/Command/UpdateFilterListCommand.php
@@ -13,6 +13,7 @@
namespace App\Command;
use App\FilterList\FilterLists;
+use App\FilterList\FilterSources;
use App\Service\Locker;
use App\Service\Scheduler;
use Symfony\Component\Console\Command\Command;
@@ -35,8 +36,9 @@ protected function configure(): void
->setName('packagist:filter-list')
->setDefinition([
new InputArgument('list', InputArgument::REQUIRED, 'The name of the filter list', null, FilterLists::cases()),
+ new InputArgument('source', InputArgument::REQUIRED, 'The name of the filter source', null, FilterSources::cases()),
])
- ->setDescription('Updates all entries for a single filter list')
+ ->setDescription('Updates all entries for a single filter list source')
;
}
@@ -50,12 +52,20 @@ protected function execute(InputInterface $input, OutputInterface $output): int
return self::INVALID;
}
+ try {
+ $source = FilterSources::from($input->getArgument('source'));
+ } catch (\ValueError) {
+ $output->writeln('source must be one of '.implode(', ', array_map(fn (FilterSources $source) => $source->value, FilterSources::cases())));
+
+ return self::INVALID;
+ }
+
$lockAcquired = $this->locker->lockFilterList($list->value);
if (!$lockAcquired) {
return 0;
}
- $this->scheduler->scheduleFilterList($list, 0);
+ $this->scheduler->scheduleFilterList($list, $source, 0);
sleep(2); // sleep to prevent running the same command on multiple machines at around the same time via cron
$this->locker->unlockFilterList($list->value);
diff --git a/src/Controller/PackageController.php b/src/Controller/PackageController.php
index 5b49c5d13..337112f1c 100644
--- a/src/Controller/PackageController.php
+++ b/src/Controller/PackageController.php
@@ -31,6 +31,7 @@
use App\Entity\Version;
use App\Event\PackageAbandonedEvent;
use App\Event\PackageUnabandonedEvent;
+use App\FilterList\FilterLists;
use App\Form\Model\MaintainerRequest;
use App\Form\Model\TransferPackageRequest;
use App\Form\Type\AbandonedType;
@@ -74,6 +75,7 @@
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
+use Symfony\Component\Routing\Requirement\EnumRequirement;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
@@ -681,7 +683,7 @@ public function viewPackageAction(Request $req, string $name, CsrfTokenManagerIn
foreach ($versions as $version) {
if ($version->getNormalizedVersion() === $normalizedVersion) {
$data['hasVersionsFlaggedAsMalware'][$version->getId()] = true;
- $data['listsFlaggingVersionsAsMalware'][$packageVersionFlaggedAsMalware->getList()->value] = $packageVersionFlaggedAsMalware->getList();
+ $data['listsFlaggingVersionsAsMalware'][$packageVersionFlaggedAsMalware->getSource()->value] = $packageVersionFlaggedAsMalware->getSource();
}
}
}
@@ -1656,12 +1658,12 @@ public function securityAdvisoryAction(Request $request, string $id): Response
return $this->render('package/security_advisory.html.twig', ['securityAdvisories' => $securityAdvisories, 'id' => $id]);
}
- #[Route(path: '/packages/{name}/filter-lists/', name: 'view_package_filter_lists', requirements: ['name' => Package::PACKAGE_NAME_OR_EXT_REGEX])]
- public function filterListsAction(Request $request, string $name): Response
+ #[Route(path: '/packages/{name}/filter-lists/{list}/', name: 'view_package_filter_lists', requirements: ['name' => Package::PACKAGE_NAME_OR_EXT_REGEX, 'list' => new EnumRequirement(FilterLists::class)])]
+ public function filterListsAction(Request $request, string $name, FilterLists $list): Response
{
/** @var FilterListEntryRepository $repo */
$repo = $this->getEM()->getRepository(FilterListEntry::class);
- $entries = $repo->getPackageEntries($name);
+ $entries = $repo->getPackageEntries($name, $list);
$data = [];
$data['name'] = $name;
@@ -1693,6 +1695,7 @@ public function filterListsAction(Request $request, string $name): Response
$data['entries'] = $entries;
$data['count'] = \count($entries);
+ $data['list'] = $list;
return $this->render('package/filter_list_entries.html.twig', $data);
}
diff --git a/src/Entity/FilterListEntry.php b/src/Entity/FilterListEntry.php
index db6a752d3..155032a1e 100644
--- a/src/Entity/FilterListEntry.php
+++ b/src/Entity/FilterListEntry.php
@@ -13,6 +13,7 @@
namespace App\Entity;
use App\FilterList\FilterLists;
+use App\FilterList\FilterSources;
use App\FilterList\RemoteFilterListEntry;
use App\Service\IdGenerator;
use Doctrine\ORM\Mapping as ORM;
@@ -48,8 +49,11 @@ class FilterListEntry
#[ORM\Column]
private \DateTimeImmutable $updatedAt;
- #[ORM\Column(nullable: true)]
- private ?string $publicId;
+ #[ORM\Column]
+ private string $publicId;
+
+ #[ORM\Column]
+ private FilterSources $source;
public function __construct(RemoteFilterListEntry $remote)
{
@@ -59,6 +63,7 @@ public function __construct(RemoteFilterListEntry $remote)
$this->link = $remote->link;
$this->list = $remote->list;
$this->reason = $remote->reason;
+ $this->source = $remote->source;
$this->createdAt = $this->updatedAt = new \DateTimeImmutable();
}
@@ -93,7 +98,12 @@ public function getPublicId(): ?string
return $this->publicId;
}
- public function assignPublicId(): void
+ public function getSource(): FilterSources
+ {
+ return $this->source;
+ }
+
+ private function assignPublicId(): void
{
$this->publicId = IdGenerator::generateFilterListEntry();
}
diff --git a/src/Entity/FilterListEntryRepository.php b/src/Entity/FilterListEntryRepository.php
index 0596a85d0..2f82b5db4 100644
--- a/src/Entity/FilterListEntryRepository.php
+++ b/src/Entity/FilterListEntryRepository.php
@@ -13,6 +13,7 @@
namespace App\Entity;
use App\FilterList\FilterLists;
+use App\FilterList\FilterSources;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\DBAL\ArrayParameterType;
use Doctrine\Persistence\ManagerRegistry;
@@ -31,11 +32,13 @@ public function __construct(
/**
* @return list
*/
- public function getEntriesInList(FilterLists $list): array
+ public function getEntriesInList(FilterLists $list, FilterSources $source): array
{
return $this->createQueryBuilder('fl')
->where('fl.list = :list')
+ ->andWhere('fl.source = :source')
->setParameter('list', $list)
+ ->setParameter('source', $source)
->getQuery()
->getResult();
}
@@ -47,9 +50,9 @@ public function getPackageVersionsFlaggedAsMalwareForPackage(Package $package):
{
return $this->createQueryBuilder('fl')
->where('fl.packageName = :packageName')
- ->andWhere('fl.list IN (:lists)')
+ ->andWhere('fl.list = :malware')
->setParameter('packageName', $package->getName())
- ->setParameter('lists', FilterLists::malwareListsValues(), ArrayParameterType::STRING)
+ ->setParameter('malware', FilterLists::MALWARE)
->getQuery()
->getResult();
}
@@ -57,11 +60,13 @@ public function getPackageVersionsFlaggedAsMalwareForPackage(Package $package):
/**
* @return list
*/
- public function getPackageEntries(string $packageName): array
+ public function getPackageEntries(string $packageName, FilterLists $list): array
{
return $this->createQueryBuilder('fl')
->where('fl.packageName = :packageName')
+ ->andWhere('fl.list = :list')
->setParameter('packageName', $packageName)
+ ->setParameter('list', $list)
->getQuery()
->getResult();
}
@@ -69,7 +74,7 @@ public function getPackageEntries(string $packageName): array
/**
* @param array $packageNames
*
- * @return array>
+ * @return array>
*/
public function getAllPackageEntriesMap(array $packageNames): array
{
@@ -86,6 +91,7 @@ public function getAllPackageEntriesMap(array $packageNames): array
'list' => $entry->getList()->value,
'reason' => $entry->getReason(),
'publicId' => $entry->getPublicId(),
+ 'source' => $entry->getSource()->value,
];
}
diff --git a/src/FilterList/Dump/DumpableFilterList.php b/src/FilterList/Dump/DumpableFilterList.php
index 1ed2971e3..2928c7cdb 100644
--- a/src/FilterList/Dump/DumpableFilterList.php
+++ b/src/FilterList/Dump/DumpableFilterList.php
@@ -12,6 +12,8 @@
namespace App\FilterList\Dump;
+use App\FilterList\FilterSources;
+
final readonly class DumpableFilterList
{
public function __construct(
@@ -19,6 +21,7 @@ public function __construct(
public string $url,
public ?string $reason,
public ?string $id,
+ public string $source,
) {
}
}
diff --git a/src/FilterList/Dump/FilterListDumperProvider.php b/src/FilterList/Dump/FilterListDumperProvider.php
index b3efc7154..acc519d89 100644
--- a/src/FilterList/Dump/FilterListDumperProvider.php
+++ b/src/FilterList/Dump/FilterListDumperProvider.php
@@ -41,9 +41,10 @@ public function getEntriesForDump(array $packageNames): array
foreach ($entries as $entry) {
$groupedEntries[$packageName][$entry['list']][] = new DumpableFilterList(
$entry['version'],
- $this->urlGenerator->generate('view_package_filter_lists', ['name' => $packageName], UrlGeneratorInterface::ABSOLUTE_URL),
+ $this->urlGenerator->generate('view_package_filter_lists', ['name' => $packageName, 'list' => $entry['list']], UrlGeneratorInterface::ABSOLUTE_URL),
$entry['reason'],
$entry['publicId'],
+ $entry['source'],
);
}
}
diff --git a/src/FilterList/FilterListResolver.php b/src/FilterList/FilterListResolver.php
index 60c94dfd3..925aa422d 100644
--- a/src/FilterList/FilterListResolver.php
+++ b/src/FilterList/FilterListResolver.php
@@ -20,18 +20,12 @@ class FilterListResolver
* @param array $existingEntries
* @param array $remoteEntries
*
- * @return array{list, list, bool}
+ * @return array{list, list}
*/
public function resolve(array $existingEntries, array $remoteEntries): array
{
- $modifiedExisting = false;
$existingMap = [];
foreach ($existingEntries as $existing) {
- if (!$existing->getPublicId()) {
- $existing->assignPublicId();
- $modifiedExisting = true;
- }
-
$existingMap[$existing->getPackageName()][$existing->getVersion()] = $existing;
}
@@ -58,7 +52,6 @@ public function resolve(array $existingEntries, array $remoteEntries): array
return [
$new,
$unmatched,
- $modifiedExisting,
];
}
}
diff --git a/src/FilterList/FilterLists.php b/src/FilterList/FilterLists.php
index be1977dd8..686891930 100644
--- a/src/FilterList/FilterLists.php
+++ b/src/FilterList/FilterLists.php
@@ -14,50 +14,5 @@
enum FilterLists: string
{
- case AIKIDO_MALWARE = 'aikido-malware';
-
- public function logo(): string
- {
- return match ($this) {
- self::AIKIDO_MALWARE => 'img/aikido-dark.svg',
- };
- }
-
- public function displayName(): string
- {
- return match ($this) {
- self::AIKIDO_MALWARE => 'Aikido',
- };
- }
-
- public function url(): string
- {
- return match ($this) {
- self::AIKIDO_MALWARE => 'https://aikido.dev/',
- };
- }
-
- /**
- * @return list
- */
- public static function defaultLists(): array
- {
- return [self::AIKIDO_MALWARE];
- }
-
- /**
- * @return list
- */
- public static function malwareLists(): array
- {
- return [self::AIKIDO_MALWARE];
- }
-
- /**
- * @return list
- */
- public static function malwareListsValues(): array
- {
- return array_map(fn (FilterLists $list) => $list->value, self::malwareLists());
- }
+ case MALWARE = 'malware';
}
diff --git a/src/FilterList/FilterSources.php b/src/FilterList/FilterSources.php
new file mode 100644
index 000000000..12c91a6f4
--- /dev/null
+++ b/src/FilterList/FilterSources.php
@@ -0,0 +1,39 @@
+
+ * Nils Adermann
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace App\FilterList;
+
+enum FilterSources: string
+{
+ case AIKIDO = 'aikido';
+
+ public function logo(): string
+ {
+ return match ($this) {
+ self::AIKIDO => 'img/aikido-dark.svg',
+ };
+ }
+
+ public function displayName(): string
+ {
+ return match ($this) {
+ self::AIKIDO => 'Aikido',
+ };
+ }
+
+ public function url(): string
+ {
+ return match ($this) {
+ self::AIKIDO => 'https://aikido.dev/',
+ };
+ }
+}
diff --git a/src/FilterList/List/AikidoMalwareFilterList.php b/src/FilterList/List/AikidoMalwareFilterList.php
index 88f8da9da..7f790ed85 100644
--- a/src/FilterList/List/AikidoMalwareFilterList.php
+++ b/src/FilterList/List/AikidoMalwareFilterList.php
@@ -13,6 +13,7 @@
namespace App\FilterList\List;
use App\FilterList\FilterLists;
+use App\FilterList\FilterSources;
use App\FilterList\RemoteFilterListEntry;
use Psr\Log\LoggerInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
@@ -55,9 +56,10 @@ public function getListEntries(): ?array
$entries[] = new RemoteFilterListEntry(
$packageName,
$entry['version'],
- FilterLists::AIKIDO_MALWARE,
+ FilterLists::MALWARE,
\sprintf('https://app.aikido.dev/reports/malware/software-supply-chain-attacks?search=%s&ecosystem=packagist', urlencode($packageName)),
'malware',
+ FilterSources::AIKIDO,
);
}
diff --git a/src/FilterList/RemoteFilterListEntry.php b/src/FilterList/RemoteFilterListEntry.php
index b6f4586aa..65fc196f1 100644
--- a/src/FilterList/RemoteFilterListEntry.php
+++ b/src/FilterList/RemoteFilterListEntry.php
@@ -20,6 +20,7 @@ public function __construct(
public FilterLists $list,
public ?string $link,
public string $reason,
+ public FilterSources $source,
) {
}
}
diff --git a/src/Package/V2Dumper.php b/src/Package/V2Dumper.php
index 50d4c3892..56ecef590 100644
--- a/src/Package/V2Dumper.php
+++ b/src/Package/V2Dumper.php
@@ -98,7 +98,6 @@ public function dumpRoot(bool $verbose = false): void
$rootFileContents['filter'] = [
'metadata' => true,
'lists' => array_map(fn (FilterLists $list) => $list->value, FilterLists::cases()),
- 'default-lists' => array_map(fn (FilterLists $list) => $list->value, FilterLists::defaultLists()),
];
if ($verbose) {
diff --git a/src/Service/FilterListWorker.php b/src/Service/FilterListWorker.php
index 6db8c9e11..1872e9bcf 100644
--- a/src/Service/FilterListWorker.php
+++ b/src/Service/FilterListWorker.php
@@ -18,6 +18,7 @@
use App\FilterList\FilterListEntryUpdateListener;
use App\FilterList\FilterListResolver;
use App\FilterList\FilterLists;
+use App\FilterList\FilterSources;
use App\FilterList\List\FilterListInterface;
use App\Model\DownloadManager;
use Doctrine\Persistence\ManagerRegistry;
@@ -58,24 +59,28 @@ public function __construct(
public function process(Job $job, SignalHandler $signal): array
{
$list = FilterLists::from($job->getPayload()['list']);
+ $source = FilterSources::from($job->getPayload()['source']);
$lockAcquired = $this->locker->lockFilterList(self::FILTER_LIST_WORKER_RUN);
if (!$lockAcquired) {
return ['status' => Job::STATUS_RESCHEDULE, 'after' => new \DateTimeImmutable('+2 minutes'), 'message' => 'Could not acquire lock'];
}
- $source = $this->filterLists[$list->value];
- $remoteEntries = $source->getListEntries();
+ $filterList = $this->filterLists[$source->value . '-' . $list->value];
+ $remoteEntries = $filterList->getListEntries();
if (null === $remoteEntries) {
- $this->logger->info('Filter list update failed, skipping', ['list' => $list]);
+ $this->logger->info('Filter list update failed, skipping', [
+ 'list' => $list,
+ 'source' => $source,
+ ]);
$this->locker->unlockFilterList(self::FILTER_LIST_WORKER_RUN);
return ['status' => Job::STATUS_ERRORED, 'message' => 'Filter list update failed, skipped'];
}
/** @var FilterListEntry[] $existingEntries */
- $existingEntries = $this->doctrine->getRepository(FilterListEntry::class)->getEntriesInList($list);
- [$new, $removed, $modifiedExisting] = $this->malwareFeedResolver->resolve($existingEntries, $remoteEntries);
+ $existingEntries = $this->doctrine->getRepository(FilterListEntry::class)->getEntriesInList($list, $source);
+ [$new, $removed] = $this->malwareFeedResolver->resolve($existingEntries, $remoteEntries);
foreach ($new as $entry) {
$this->doctrine->getManager()->persist($entry);
@@ -85,7 +90,7 @@ public function process(Job $job, SignalHandler $signal): array
$this->doctrine->getManager()->remove($entry);
}
- if ($new !== [] || $removed !== [] || $modifiedExisting) {
+ if ($new !== [] || $removed !== []) {
$this->doctrine->getManager()->flush();
}
diff --git a/src/Service/Scheduler.php b/src/Service/Scheduler.php
index bc8bba6d8..4b675ad99 100644
--- a/src/Service/Scheduler.php
+++ b/src/Service/Scheduler.php
@@ -15,6 +15,7 @@
use App\Entity\Job;
use App\Entity\Package;
use App\FilterList\FilterLists;
+use App\FilterList\FilterSources;
use Doctrine\Persistence\ManagerRegistry;
use Predis\Client as RedisClient;
@@ -80,9 +81,9 @@ public function scheduleSecurityAdvisory(string $source, int $packageId, ?\DateT
/**
* @return Job
*/
- public function scheduleFilterList(FilterLists $list, int $packageId, ?\DateTimeImmutable $executeAfter = null): Job
+ public function scheduleFilterList(FilterLists $list, FilterSources $source, int $packageId, ?\DateTimeImmutable $executeAfter = null): Job
{
- return $this->createJob('filter:update', ['list' => $list->value], $packageId, $executeAfter);
+ return $this->createJob('filter:update', ['list' => $list->value, 'source' => $source->value], $packageId, $executeAfter);
}
private function getPendingUpdateJob(int $packageId, bool $updateEqualRefs = false, bool $deleteBefore = false): ?string
diff --git a/templates/audit_log/display/filter_list_entry_added.html.twig b/templates/audit_log/display/filter_list_entry_added.html.twig
index f3fc0037e..17460ccc9 100644
--- a/templates/audit_log/display/filter_list_entry_added.html.twig
+++ b/templates/audit_log/display/filter_list_entry_added.html.twig
@@ -1,4 +1,4 @@
{% import 'audit_log/macros.html.twig' as auditLog %}
{{ auditLog.packageLink(display.packageName) }}
-Versions {{ display.version}} were flagged by {{ display.list.displayName }}. Reason: {{ display.reason }}.
+Versions {{ display.version}} were flagged as {{ display.list.value }} by {{ display.source.displayName }}. Reason: {{ display.reason }}.
diff --git a/templates/audit_log/display/filter_list_entry_deleted.html.twig b/templates/audit_log/display/filter_list_entry_deleted.html.twig
index 7a67e0202..4cc103e8f 100644
--- a/templates/audit_log/display/filter_list_entry_deleted.html.twig
+++ b/templates/audit_log/display/filter_list_entry_deleted.html.twig
@@ -1,4 +1,4 @@
{% import 'audit_log/macros.html.twig' as auditLog %}
{{ auditLog.packageLink(display.packageName) }}
-Versions {{ display.version}} were unflagged by {{ display.list}}.
+Versions {{ display.version }} were unflagged by {{ display.source.displayName }} as {{ display.list.value }}.
diff --git a/templates/package/_filter_list_entries_list.html.twig b/templates/package/_filter_list_entries_list.html.twig
index d3fc03897..84aef43f0 100644
--- a/templates/package/_filter_list_entries_list.html.twig
+++ b/templates/package/_filter_list_entries_list.html.twig
@@ -13,13 +13,13 @@
Reason: {{ entry.reason }}
{% if entry.link %}
- View details on {{ entry.list.displayName }}
+ View details on {{ entry.source.displayName }}
{% endif %}
-
Reported by:  }})
+
Reported by:  }})
diff --git a/templates/package/filter_list_entries.html.twig b/templates/package/filter_list_entries.html.twig
index 5f342aa7c..e473c03cb 100644
--- a/templates/package/filter_list_entries.html.twig
+++ b/templates/package/filter_list_entries.html.twig
@@ -4,7 +4,7 @@
{% block head_additions %}{% endblock %}
-{% block title %}{{ 'packages.filter_lists'|trans }} - {{ name }} - {{ parent() }}{% endblock %}
+{% block title %}{{ ('packages.filter_lists.' ~ list.value)|trans }} - {{ name }} - {{ parent() }}{% endblock %}
{% block content %}
@@ -12,6 +12,7 @@