phpunit/php-file-iterator

FilterIterator implementation that filters files based on a list of suffixes.

100 /100 100 Good

Scanned 5 hours ago

Repository
Security 55%
100 Good
Maintenance 30%
100 Good
Ecosystem 15%

Check details

Security

Tag-pinned Actions can be silently re-pointed to malicious code by a compromised maintainer. The tj-actions/changed-files incident (March 2025) demonstrated this: attackers re-pointed a widely-used tag mid-run and exfiltrated CI secrets from thousands of repositories. Pinning every third-party action reference to a full 40-character commit SHA is the only way to guarantee the code that ran yesterday runs again today. First-party references (./path actions and same-repository reusable workflows) are exempt because they are protected by the repository's own branch-protection rules.

Total
15
Pinned
15
Unpinned
Workflow Count
4

An active, unfixed security advisory against the version users actually install is the most concrete threat we can detect. We cross-reference two independent advisory feeds — GitHub Security Advisories (GHSA) and Packagist's aggregated advisories — and dedupe by CVE id so that lag or downtime in one feed cannot hide a known vulnerability. An advisory counts against a package when the latest released version falls inside the advisory's affected-version range and either no fix has been published or the published fix is no newer than the latest release. Any such advisory fails the check and lowers the Security category score to a maximum of 30. The check is skipped (Not Applicable) when the package has no stable release on Packagist — there is nothing yet to evaluate. If both advisory feeds are unreachable the check reports an error; if only one is unreachable the surviving feed still produces a verdict and the failed feed is recorded in the evidence.

Sources Seen
ghsa, packagist
Latest Version
7.0.0
Sources Failed
Advisories Total
0

A maintainer who leaves Dependabot pull requests open for months is signalling either inattention or an unwillingness to engage with automated dependency management -- both compound into real exposure as vulnerabilities accumulate unpatched. All open Dependabot PRs are scored across two buckets with different urgency thresholds. Security PRs -- identified by a CVE or GHSA identifier in the PR body -- are scored strictly: pass requires no open security PR older than 14 days, with partial credit at 14-30 days (0.7) and 30-90 days (0.3), and failure beyond 90 days. General dependency PRs are scored more leniently: pass within 30 days, partial credit at 30-60 days (0.7) and 60-180 days (0.3), and failure beyond 180 days. The final score is the worse of the two buckets.

General Prs
Security Prs
Verdict Reason
No open Dependabot PRs.
General Pr Count
0
Security Pr Count
0
Oldest General Age Days
Oldest Security Age Days

Without a documented disclosure process, security reports go to public issues — accelerating exploitation while maintainers scramble to triage in the open. A SECURITY.md at one of GitHub's recognized locations (repo root, .github/, or docs/) tells researchers where to send vulnerability reports privately. This is a presence-only check. We do not grade the prose or verify the contact path actually works; the reasoning is mechanical: a file at the standard location is the difference between "I have a clear place to report this" and "I have to guess."

Sha
af0c5a4fd3af92c881150fc5960b6ec3be635b23
Html Url
https://github.com/sebastianbergmann/php-file-iterator/blob/main/SECURITY.md
Location
SECURITY.md

Maintenance

Packagist lets a maintainer explicitly mark a package as abandoned, optionally pointing consumers at a suggested replacement. It is the strongest non-malware signal we can receive: the person closest to the project is telling the ecosystem the package will not be patched. The check is binary. Either the flag is set or it is not — no warn tier. A failure caps the Maintenance category at 20 regardless of how the package scores on every other Maintenance signal, because no amount of recent activity or hygiene offsets the maintainer's own statement that future fixes will not land. When the maintainer provided a replacement package name on Packagist, we surface it in the check evidence so downstream consumers (the API, the website, the Composer plugin) can present the redirect alongside the failure. The replacement suggestion is the actionable next step that helps consumers migrate rather than merely warning them off.

Is Abandoned
false
Verdict Reason
Packagist abandoned flag is not set.
Abandoned Replacement

Recency is a noisy signal — some mature packages legitimately do not need frequent commits — but combined with other maintenance signals it correlates strongly with abandonment risk. We measure two independent signals: the date of the most recent commit on the default branch and the date of the most recent stable release on Packagist. A package passes if either signal is sufficiently recent; it fails only when both signals have been silent for an extended period. Commit threshold (90 days) mirrors the OpenSSF Scorecard "Maintained" check, which uses 90 days as the boundary between active and inactive. Release threshold (180 days active / 365 days stale) is Plumb-specific: releases have a slower natural cadence than commits, so the window is wider. A package that passes on releases alone has published a stable version in the last 6 months; one in the warn zone released between 6 and 12 months ago; one that fails has had no release in over a year and no commit in over a year.

Verdict Reason
Active: last commit 1 days ago; last release 123 days ago.
Last Commit Date
2026-06-07T21:25:44Z
Last Release Date
2026-02-06T04:33:26+00:00
Last Commit Age Days
1
Last Release Age Days
123

Composer ignores nested lockfiles found inside vendor/, so a library committing composer.lock does not change how its consumers resolve dependencies. The real harm is that downstream security scanners (AWS Inspector, dependency-audit tooling) walk installed vendor/ directories and parse any composer.lock they find, flagging the package versions pinned inside — versions that drift from what the consumer is actually using, adding false-positive noise to audits. The check inspects only the released dist archive — the artifact consumers actually receive via composer require. If the lock is absent from the dist, the package passes regardless of how that exclusion was achieved (.gitattributes export-ignore, never committed, composer.json archive.exclude, etc.). The check is mechanism-agnostic: we trust the ground truth rather than modelling every way a maintainer might exclude a file. NotApplicable when no stable release exists on Packagist, or when the package's composer.json declares `type: project` (Symfony skeletons, Laravel applications legitimately commit a lockfile). Low-weight hygiene signal — a slip means downstream audit noise, not a security failure.

Package Type
library
Verdict Reason
composer.lock is absent from the released dist archive.
Release Version
7.0.0
Lock Present In Dist
false

Dev files shipped in the dist archive bloat every install, expand the attack surface, and signal that the maintainer has not configured archive exclusions. Smaller dists mean faster composer require, less noise in security scanners walking vendor/, and a clear signal of care. Files are grouped into four categories: test infrastructure, CI/CD configs, AI assistant configs, and dev tooling/environment. The check passes when all groups are clean, warns (0.5) when exactly one group has flagged files, and fails when two or more groups do. The check inspects the dist archive only — we trust the released bytes regardless of how the maintainer excluded files (.gitattributes export-ignore, composer.json archive.exclude, never committed, etc.). NotApplicable when no stable release exists on Packagist.

Hits
4 items
Release Version
7.0.0

Add a Plumb badge to your README.

Composite Score Plumb score
[![Plumb score](https://plumbphp.dev/badges/phpunit/php-file-iterator/composite.svg)](https://plumbphp.dev/phpunit/php-file-iterator)
Security Plumb security score
[![Plumb security score](https://plumbphp.dev/badges/phpunit/php-file-iterator/security.svg)](https://plumbphp.dev/phpunit/php-file-iterator)
Maintenance Plumb maintenance score
[![Plumb maintenance score](https://plumbphp.dev/badges/phpunit/php-file-iterator/maintenance.svg)](https://plumbphp.dev/phpunit/php-file-iterator)
Ecosystem Plumb ecosystem score
[![Plumb ecosystem score](https://plumbphp.dev/badges/phpunit/php-file-iterator/ecosystem.svg)](https://plumbphp.dev/phpunit/php-file-iterator)
Scanned Scanned by Plumb
[![Scanned by Plumb](https://plumbphp.dev/badges/phpunit/php-file-iterator/scanned.svg)](https://plumbphp.dev/phpunit/php-file-iterator)