PKP-WAL <= 3.5.0-1 (Institution Collector) SQL Injection Vulnerability

https://pkp.sfu.ca

https://github.com/pkp/pkp-lib

• Affected Versions:

PKP Web Application Library (aka PKP-WAL or pkp-lib) version 3.4.0-9 and prior versions, and version 3.5.0-1 and prior versions, as used in Open Journal Systems (OJS), Open Monograph Press (OMP), and Open Preprint Systems (OPS).

• Vulnerability Description:

The vulnerability is located in the /classes/institution/Collector.php script.

Specifically, into the Collector::getQueryBuilder() method:

121    public function getQueryBuilder(): Builder
122    {
123        $qb = DB::table($this->dao->table . ' as i')->select('i.*');
124
125        if (!is_null($this->contextIds)) {
126            $qb->whereIn('i.context_id', $this->contextIds);
127        }
128
129        if (!$this->includeSoftDeletes) {
130            $qb->whereNull('i.deleted_at');
131        }
132
133        if ($this->searchPhrase !== null) {
134            $words = explode(' ', $this->searchPhrase);
135            if (count($words)) {
136                foreach ($words as $word) {
137                    $word = addcslashes($word, '%_');
138                    $qb->where(function ($qb) use ($word) {
139                        $qb->whereIn('i.institution_id', function ($qb) use ($word) {
140                            $qb->select('iss.institution_id')
141                                ->from($this->dao->settingsTable . ' as iss')
142                                ->where('iss.setting_name', '=', 'name')
143                                ->where(DB::raw('lower(iss.setting_value)'), 'LIKE', DB::raw("lower('%{$word}%')"));
144                        })
145                            ->orWhereIn('i.institution_id', function ($qb) use ($word) {
146                                $qb->select('ips.institution_id')
147                                    ->from('institution_ip as ips')
148                                    ->where(DB::raw('lower(ips.ip_string)'), 'LIKE', DB::raw("lower('%{$word}%')"));
149                            });
150                    });
151                }

User input passed through the “searchPhrase” GET parameter is not properly sanitized before being used to construct a SQL query at lines 143 and 148 by leveraging the DB::raw() method. This can be exploited by malicious users to e.g. read sensitive data from the database through boolean-based or time-based SQL Injection attacks.

Successful exploitation of this vulnerability requires an account with permissions to access the .../api/v1/institutions API endpoint, such as a “Journal Editor” or “Production Editor” user account on OJS.

• Proof of Concept:

https://karmainsecurity.com/pocs/CVE-2025-67889.php

• Solution:

Upgrade to versions 3.4.0-10, 3.5.0-2, or later.

• Disclosure Timeline:

[25/10/2025] – Vendor notified

[26/10/2025] – Vendor fixed the issue and opened a public GitHub issue: https://github.com/pkp/pkp-lib/issues/11977

[12/11/2025] – CVE identifier requested

[18/11/2025] – Version 3.4.0-10 released

[12/12/2025] – CVE identifier assigned

[29/11/2025] – Version 3.5.0-2 released

[23/12/2025] – Publication of this advisory

• CVE Reference:

The Common Vulnerabilities and Exposures program (cve.org) has assigned the name CVE-2025-67889 to this vulnerability.

• Credits:

Vulnerability discovered by Egidio Romano.