znframework/software-drivers

ZN Framework Software Drivers

85 /100 85 Fair

Last checked 2 hours ago

Repository
Security 55%
85 Good
Maintenance 30%
76 Fair
Ecosystem 15%
100 Good

Check details

Security

Checks whether third-party GitHub Actions used in the workflows are pinned to a full commit SHA instead of a tag or branch. No .github/workflows directory found
How this check works

A GitHub Actions workflow runs code from other repositories through uses: lines such as actions/checkout@v4. A tag like v4 or a branch name is a moving target: whoever controls that repository can point it at different code at any time, and every workflow using it will run the new code on its next run, with access to the repository's secrets. In March 2025 the popular tj-actions/changed-files action was compromised exactly this way and leaked CI secrets from thousands of repositories. A full 40-character commit SHA cannot be moved, so pinning to one guarantees the same code runs every time.

Plumb reads every workflow file in .github/workflows and collects each uses: reference from jobs and steps. References to the repository's own actions (paths starting with ./ and the repository's own reusable workflows) are skipped, because they are already protected by the repository's own review process. Each remaining reference counts as pinned when the part after @ is a 40-character hexadecimal SHA.

The check passes when every third-party reference is pinned. If more than 80 percent are pinned it warns and awards half credit. Otherwise it fails. The unpinned references are listed in the evidence so they can be fixed. The check is not applicable when the repository has no workflows or the workflows use no third-party actions, and it only runs for repositories hosted on GitHub.

Learn more about this check
Checks whether external include: entries in the GitLab CI configuration are pinned to a full commit SHA instead of a branch, tag, or version. Applies only to GitLab-hosted repositories.
How this check works

A GitLab CI pipeline can pull configuration from outside the repository through include: entries: files from other projects, CI/CD components, and remote URLs. When such an include points at a branch, a tag, or a component version such as 1.2 or ~latest, whoever controls the source can change what the pipeline runs without touching this repository. This is the same class of attack seen against tag-pinned GitHub Actions in the tj-actions/changed-files incident of March 2025. A full 40-character commit SHA cannot be changed after the fact.

Plumb reads the project's CI configuration file (.gitlab-ci.yml, or the custom path the project sets) and classifies each include. local: files from the same repository and GitLab-bundled template: includes are skipped, because they are covered by the repository's own review controls or ship with GitLab itself. A project: include is pinned when its ref is a full SHA. A component: include is pinned when its version after @ is a full SHA. A remote: URL has no pinning mechanism and always counts as unpinned.

The check passes when every external include is pinned. If more than 80 percent are pinned it warns and awards half credit. Otherwise it fails. It is not applicable when there is no CI configuration or no external includes, and it only runs for repositories hosted on GitLab.

Learn more about this check
Checks whether the newest release of this package has a known, unfixed security vulnerability.

This is a veto check: if it fails, the Security score is capped at 30/100 no matter how other checks score. The veto is not currently affecting this package's score. Learn how scoring works.

Latest release
2.0.0
Advisories on record
0
Advisory feeds consulted
  • ghsa
  • packagist
Advisory feeds unavailable
none
How this check works

A security advisory is a public notice that a specific range of package versions has a known vulnerability. When the newest release still falls inside that range, everyone who installs the package today is installing a known problem. This is the most concrete risk Plumb can detect.

Plumb reads two independent advisory feeds: GitHub Security Advisories and the Packagist security advisories database. The two feeds are merged and duplicates are removed by CVE id, so a delay or outage in one feed cannot hide an advisory the other one knows about.

The check passes when no advisory covers the latest released version. It fails when at least one advisory does: either no fixed version has been published yet, or the fix is not newer than the latest release. Failing also caps the Security score at 30 out of 100. The check is not applicable when the package has no stable release to evaluate. If one feed is unreachable the other still produces a verdict and the failure is noted in the evidence; if every feed is unreachable the check reports an error instead of guessing.

Learn more about this check
Checks how long the oldest open Dependabot pull requests have been waiting, with a shorter allowance for security fixes. No open Dependabot PRs.
Open general pull requests
0
Open security pull requests
0
Oldest general pull request, in days
none
Oldest security pull request, in days
none
General pull requests
none
Security pull requests
none
How this check works

An automated update tool only helps if its pull requests get reviewed and merged. Dependabot pull requests left open for months mean fixes are known but not shipped, and the gap keeps growing as more releases pile up. Security fixes are the urgent case, because they address a published vulnerability.

Plumb lists the repository's open pull requests authored by Dependabot and sorts them into two groups. A pull request whose description mentions a CVE or GHSA identifier is a security update. Everything else is a general update. For each group only the oldest open pull request matters.

Security updates pass when the oldest is 14 days old or less, earn 70 percent credit up to 30 days, 30 percent credit up to 90 days, and fail beyond 90 days. General updates pass up to 30 days, earn 70 percent credit up to 60 days, 30 percent credit up to 180 days, and fail beyond 180 days. The final result is whichever group scored worse. A repository with no open Dependabot pull requests passes. The check only runs for repositories hosted on GitHub.

Learn more about this check
Checks how long the oldest open Renovate merge requests have been waiting, with a shorter allowance for security fixes. Applies only to GitLab-hosted repositories.
How this check works

An automated update tool only helps if its merge requests get reviewed and merged. Renovate merge requests left open for months mean fixes are known but not shipped, and the gap keeps growing as more releases pile up. Security fixes are the urgent case, because they address a published vulnerability.

Plumb lists the project's open merge requests and keeps the ones that come from Renovate: the source branch starts with renovate/, or the author's username contains renovate. These are mechanical markers, not a judgement about the account. Each merge request is then sorted into two groups. One whose description mentions a CVE or GHSA identifier is a security update. Everything else is a general update. For each group only the oldest open merge request matters.

Security updates pass when the oldest is 14 days old or less, earn 70 percent credit up to 30 days, 30 percent credit up to 90 days, and fail beyond 90 days. General updates pass up to 30 days, earn 70 percent credit up to 60 days, 30 percent credit up to 180 days, and fail beyond 180 days. The final result is whichever group scored worse. A project with no open Renovate merge requests passes. The check only runs for repositories hosted on GitLab.

Learn more about this check
Checks whether an automated dependency update tool is set up and covers every package ecosystem the repository actually uses. No committed lockfiles or workflows for an updater to maintain.
Update tool
none
JavaScript lockfile committed
No
GitHub Actions workflows present
No
Composer lockfile committed
No
Locations searched
  • renovate.json
  • renovate.json5
  • .github/renovate.json
  • .github/dependabot.yml
  • package.json
JavaScript lockfiles
none
How this check works

Most vulnerabilities reach a project through its dependencies rather than its own code. Automated update tools such as Dependabot and Renovate open pull requests as new versions appear, so fixes arrive without anyone having to remember to look. A tool that is installed but skips an ecosystem in use leaves that part of the project unpatched.

Plumb looks for a Renovate configuration (renovate.json, renovate.json5, the .github/ or .gitlab/ variants, or a renovate key in package.json) or a Dependabot configuration at .github/dependabot.yml. It then works out which ecosystems the repository maintains: Composer when a composer.lock is committed, GitHub Actions when workflow files exist, and JavaScript when an npm, yarn, pnpm, or bun lockfile is committed. For Dependabot, coverage comes from the package-ecosystem entries. For Renovate, coverage follows enabledManagers; when that setting is absent Renovate covers everything by default.

The check passes when a tool is configured and covers every ecosystem in use. It is not applicable when the repository has no committed lockfiles and no workflows, because there is nothing for an updater to maintain. It fails when no tool is configured, or when the tool covers none of the ecosystems in use. It warns when some ecosystems are missed: a missing Composer manager is the most serious gap and leaves the least credit, while a missing GitHub Actions or JavaScript manager leaves most of the credit.

Learn more about this check
Checks whether the dependency update tool waits a few days after a new release before proposing it. No dependency updater configured
How this check works

When a package release is malicious or badly broken, it is usually discovered and pulled within the first few days. Projects that update the moment a release appears are the ones that get caught. A cooldown tells the update tool to wait a minimum number of days before proposing a new version, giving the wider community time to notice problems first. The 2024 xz-utils backdoor targeted exactly this early-adopter window.

Plumb reads the same configuration files as the updater check. In a Dependabot configuration it looks for a cooldown block on each update entry and takes the smallest of default-days, semver-major-days, semver-minor-days, and semver-patch-days. In a Renovate configuration it reads minimumReleaseAge, at the top level or inside packageRules, and takes the smallest value expressed in days.

The check passes when the smallest configured cooldown is at least 3 days. It warns with proportional credit when a cooldown is set but shorter than 3 days, and fails when the updater has no cooldown at all. It is not applicable when no dependency update tool is configured, since that is already reported by the updater check.

Learn more about this check
Checks whether the repository tells people how to report a security problem privately, usually through a SECURITY.md file.
Locations searched
  • SECURITY.md
  • .github/SECURITY.md
  • docs/SECURITY.md
How this check works

When someone finds a vulnerability in a package, they need to know where to report it. Without a documented process, many people never report it at all, and others post it in a public issue where attackers can read it before a fix exists. A security policy gives researchers a private place to send reports.

Plumb looks for a SECURITY.md file in the repository root, in .github/, or in docs/. A package registered with Plumb can also supply a security policy during registration, which counts the same way; this is how private repositories satisfy the check.

The check passes when a policy is found in any of those places and fails when none is found. It only checks that a policy exists. It does not judge the writing or test whether the contact address works. If the repository files cannot be read and no registered policy exists, the check is unassessable rather than failed.

How to improve this

Maintenance

Checks whether the maintainer has marked the package abandoned on Packagist or archived its repository. No consulted source marks the package abandoned (packagist, github).

This is a veto check: if it fails, every category score is set to 0/100 no matter how other checks score. The veto is not currently affecting this package's score. Learn how scoring works.

Archived on
none
Repository archived
No
Marked abandoned on Packagist
No
Suggested replacement
none
Sources consulted
  • packagist
  • github
How this check works

A maintainer can tell the world that a package will not receive further fixes in two places: by marking it abandoned on Packagist, optionally naming a replacement, or by archiving the repository on the source host. Either one is the maintainer's own statement that future fixes will not come. That is the strongest warning a package can carry short of being malicious, and no amount of recent activity elsewhere changes it.

Plumb reads the abandoned flag from Packagist and the archived flag from the repository. Maintainers often set one without the other, so either one alone is enough. For a package that is not listed on public Packagist, the archived flag is the only signal available.

The check passes when neither flag is set and fails when either is. Failing sets every category score and the composite score to 0. When Packagist already carries the abandoned flag, the scan stops at this check, because nothing the other checks measure could change the outcome. When the maintainer named a replacement package, it is included in the evidence so the package page, the API, and the Composer plugin can point people to it.

Learn more about this check
Checks when the package last had a commit on its default branch or a stable release. Inactive: last commit 1339 days ago; last release 1339 days ago.
Last commit
2023-01-07
Last stable release
2023-01-07
Days since last commit
1339
Days since last release
1339
How this check works

A package that has not changed in a long time may simply be finished, but it may also be quietly abandoned. Recency alone cannot tell the two apart, which is why this check carries a modest weight. Combined with the other maintenance signals it is a useful early warning: a package with no recent commits and no recent releases is unlikely to receive a fix when one is needed.

Plumb reads two dates: the most recent commit on the repository's default branch, and the publication date of the most recent stable release on Packagist. Either one being recent is enough, so a stable package that ships a release without many commits, or one that commits steadily between releases, is treated fairly.

The check passes when the latest commit is 90 days old or less, or the latest stable release is 180 days old or less. The 90-day commit window follows the OpenSSF Scorecard Maintained check. It fails when both signals have been silent for more than a year. Anything in between warns with half credit. When neither date can be determined the check is unassessable.

How to improve this
Checks that a library does not ship a composer.lock file in its released package. composer.lock is absent from the released dist archive.
Package type
library
Release inspected
2.0.0
composer.lock in the archive
No
How this check works

A composer.lock file records the exact dependency versions one project installed. Composer ignores a lockfile that sits inside an installed dependency, so a library shipping one does not affect anyone's install. The harm is indirect: security scanners and audit tools that walk the vendor/ directory read any lockfile they find and report the versions pinned inside it, which are not the versions the consuming project actually uses. The result is false alarms for every downstream user.

Plumb inspects the released archive, which is exactly what composer require downloads, rather than the repository. It does not matter how the file was kept out of the archive: export-ignore in .gitattributes, archive.exclude in composer.json, or never committing the file all work.

The check passes when composer.lock is absent from the released archive and fails when it is present. It is not applicable when the package declares type: project in its composer.json, because applications such as a Laravel or Symfony skeleton are supposed to commit a lockfile, and when there is no stable release to inspect. This is a low-weight hygiene signal.

Learn more about this check
Checks whether the released package archive is free of test suites, CI configuration, editor settings, and other development-only files.
Release inspected
2.0.0
Development files in the archive
AI assistant configuration none
CI configuration none
Test files none
Development tooling none
How this check works

The archive that Composer downloads should contain what the package needs at runtime and nothing else. Test suites, CI pipelines, editor and AI assistant settings, and developer tooling configuration make every install larger and slower, give security scanners more files to raise questions about, and suggest the release process has not been tuned. Keeping them out is a small, one-time piece of configuration.

Plumb lists every file in the released archive and matches the paths against four groups of known development files: test infrastructure (such as tests/, phpunit.xml, phpstan.neon), CI configuration (such as .github/, .gitlab-ci.yml), AI assistant configuration (such as .claude/, CLAUDE.md, .cursorrules), and development tooling (such as .php-cs-fixer.php, .editorconfig, Makefile, CHANGELOG.md). Matching files are listed by group in the evidence.

The check passes when no group has any matching files. It warns with half credit when exactly one group has matches, and fails when two or more do. It is not applicable when there is no stable release to inspect. As with the lockfile check, only the released bytes matter, not how the exclusion was configured.

Learn more about this check

Ecosystem

Checks whether a Laravel package can be installed alongside the current stable Laravel release. No Laravel dependency detected in the package require or its resolved dependency graph
How this check works

A package built for Laravel that cannot be installed with the current Laravel release forces its users to postpone their framework upgrade, and with it the security fixes that come with staying current. Supporting the latest Laravel line is how a package stays usable for the projects that depend on it.

Rather than reading version strings, Plumb runs a real Composer dependency resolution of the package's released dependencies together with the current Laravel line, the same calculation composer require performs. This respects replace and conflict rules and catches limits buried inside intermediate dependencies. If the current line resolves, the package is compatible. Otherwise Plumb finds the newest Laravel line that does resolve and looks at where that line sits in its support lifecycle. The solver's own explanation of the conflict is recorded in the evidence.

A package counts as Laravel-related when its require names laravel/framework or an illuminate/* component, or when its dependency graph reaches one of those through other Laravel packages. The check passes when the current line resolves. It warns with 70 percent credit when the newest working line is still in active support, and with 40 percent credit when that line only receives security fixes. It fails when the newest working line is end of life or no line works at all. It is not applicable for packages unrelated to Laravel, when the package's own dependencies do not resolve at all, or when there is no stable release with a composer.json.

Learn more about this check
Checks whether the package can be installed on the current stable PHP release. No PHP constraint declared; package imposes no version restriction.
PHP constraint
none
Constraint declared
No
How this check works

PHP versions have a fixed support lifetime. When a package's version constraint rules out the current PHP release, its users have to stay on an older PHP, and eventually on one that no longer receives security fixes. Keeping up with PHP is how a package avoids holding its users back.

Plumb reads the php entry under require in the released composer.json and compares it with the PHP release calendar. If the constraint allows the current stable PHP version, the package is compatible. Otherwise Plumb finds the newest PHP version the constraint does allow and looks at where that version sits in its lifecycle.

The check passes when the current PHP version is allowed, or when no constraint is declared at all (including *), since that imposes no limit. It warns with 70 percent credit when the newest allowed version still receives active support, and with 40 percent credit when it only receives security fixes. It fails when the newest allowed version is end of life, or when the constraint matches no known PHP version. It is not applicable when there is no stable release or the release has no composer.json.

Learn more about this check
Checks whether a Symfony package can be installed alongside the current stable Symfony release. No Symfony dependency detected in the package require or its resolved dependency graph
How this check works

A package built for Symfony that cannot be installed with the current Symfony release forces its users to postpone their framework upgrade, and with it the security fixes that come with staying current. Supporting the latest Symfony line is how a package stays usable for the projects that depend on it.

Rather than reading version strings, Plumb runs a real Composer dependency resolution of the package's released dependencies together with the current Symfony line, pinning every framework component to that line the way a Symfony application locks them. This is the same calculation composer require performs, so it respects replace and conflict rules and catches limits buried inside intermediate dependencies. If the current line resolves, the package is compatible. Otherwise Plumb finds the newest Symfony line that does resolve and looks at where that line sits in its support lifecycle. The solver's own explanation of the conflict is recorded in the evidence.

A package counts as Symfony-related when its require names symfony/framework-bundle or a component versioned with the framework (such as symfony/http-kernel, symfony/console, symfony/yaml, symfony/validator), or when its dependency graph reaches the framework through other Symfony packages. Independently versioned packages such as symfony/polyfill-*, the contracts, symfony/ux-*, Flex, MakerBundle, and MonologBundle do not count on their own, and a package is not treated as Symfony-related just because a framework it builds on uses Symfony components internally. The check passes when the current line resolves. It warns with 70 percent credit when the newest working line is still in active support, and with 40 percent credit when that line is an LTS release receiving only security fixes. It fails when the newest working line is end of life or no line works at all. It is not applicable for packages unrelated to Symfony, when the package's own dependencies do not resolve at all, or when there is no stable release with a composer.json.

Learn more about this check

Add a Plumb badge to your README. Displaying scores on your own site instead? See the API usage guidelines for attribution requirements.

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