Download the PHP package gumslone/laravel-vulns without Composer

On this page you can find all versions of the php package gumslone/laravel-vulns. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package laravel-vulns

laravel-vulns

CI

Multi-source vulnerability lookups for PHP — eleven production sources behind one contract, with CVSS v2/v3/v4 scoring, EPSS + CISA KEV threat enrichment and change classification. Extracted from and battle-tested in OSSaur.

Source Coverage
OsvSource OSV.dev — registry ecosystems, PURLs, git commits (submodules), batch + pagination + payload caching
GitHubAdvisorySource GitHub Advisory DB (GraphQL, token) and repository security advisories (REST, tokenless)
NvdSource NVD 2.0 by CPE, rate-limit aware, parses configurations into real version ranges
CveSearchSource CVE-Search / CIRCL by CPE
EuvdSource ENISA EU Vulnerability Database
SnykSource Snyk REST (token + org)
OssIndexSource Sonatype OSS Index — purl-native, 128-coordinate batches (free account required)
RedHatSource Red Hat Security Data — RPM ecosystem and container base images
ShodanCvedbSource Shodan CVEDB — CVSS + EPSS + KEV in one record, product search
MitreCveSource MITRE CVE Services — authoritative CVE Record v5 by id, often pre-NVD
VulnCheckSource VulnCheck Community "NVD++" by id (free token)

The core is framework-free (plain Guzzle, PSR-3, PSR-16); the Laravel service provider is optional sugar.

Install

Built-in search UI

One dependency-free page at /vulns (no build step): paste anything searchAny() accepts — advisory id, purl, CPE, commit sha, release/download URL — and see the merged, enriched results with KEV / ransomware / exploit tags, plus a warning when a source failed (empty + failed source = shown as inconclusive, never as a clean bill). Off by default:

Path and middleware are configurable (vulns.ui) — put your auth middleware in front for anything beyond local use.

Searching

Every lookup starts from a PackageData — build one from a purl, a CPE, or explicit coordinates — and goes to one source or to all of them.

Search all sources at once

Results are merged across sources by canonical id (the CVE when any source knows one), aliases pooled, and the richest field kept — OSV's version ranges plus NVD's CVSS score end up on the same record, sorted by score.

A source that fails does not abort the search; check errors() so an unreachable feed reads as "possibly incomplete", never as "clean":

Choosing which sources to search

only() and except() return a restricted copy — the library equivalent of the CLI's --source=:

An unknown name throws rather than quietly searching fewer feeds — a typo that silently narrowed the search would look exactly like "nothing found".

When sources disagree: priority and freshness

Several sources usually know the same CVE, with different scores, severities and wording. The merge picks one record as the base — its fields win, the others only fill gaps (ranges, vectors, references are still pooled from all).

By default the base comes from the source trust order — osv → github → nvd → mitre → redhat → oss_index → vulncheck → snyk → euvd → shodan_cvedb → cve_search, configurable via config('vulns.priority') or per call:

preferLatest() makes the most recently modified record win instead, so a CVSS rescore or rewritten description reaches the result no matter which feed published it first — including downward rescores, which a "keep the highest score" merge would silently undo:

Records without a modification date fall back to the trust order. Both settings survive only() / except() chaining, and the merged record's sourceModifiedAt always carries the base's timestamp so you can see how fresh the winning data is.

For one advisory, latest() is the shortcut — every source asked, the most recently modified answer winning, EPSS/KEV stamped:

EPSS and KEV: how likely, and actually exploited?

CVSS says how bad; EPSS (FIRST.org) says how likely — the probability of exploitation in the wild within 30 days — and CISA KEV says it is being exploited. Merged results are stamped with both automatically (keyed by canonical CVE id, cached, no API keys needed):

Configure or disable via vulns.epss / vulns.kev (VULNS_EPSS_ENABLED, VULNS_KEV_ENABLED), or per instance with $search->withEnricher(null). A failing feed leaves results un-enriched and lands in errors() — a missing EPSS score reads as "unknown", never "not exploited".

Detecting what changed on a re-query

When you refresh a stored advisory, changesSince() classifies the difference so you can route on it — reopen triage on a major change, update silently on a minor one:

A description or reference update alone is Minor. A downgrade is deliberately as major as an upgrade — it can release an SLA-tracked assessment, which someone should look at rather than have slip through. A source dropping its score (value → null) is treated as upstream data loss, not a rescore.

refresh() does the re-query and the comparison in one step — the freshest record for the stored advisory's canonical id (see latest()), classified against what you have:

Batching lets sources use their bulk endpoints and request pooling — one call for a whole lockfile, results keyed like the input:

Look one advisory up by id across every source:

Knowing what was covered

An empty answer from a source means "nothing found" only if the source could look the package up at all — an unmapped ecosystem, a purl-less package on a purl-keyed feed, or an id-only feed never does. coverage() says which sources actually queried each package in the last batch search:

Nothing queried is "not covered", not "clean" — treat it like errors().

Storing and rehydrating records

toArray() / fromArray() round-trip a record, so a stored snapshot can be rebuilt for changesSince() / refresh(). Inferred values (see below) are re-derived rather than restored, so the snapshot stays faithful to its source:

Triage helpers

SSVC "active" counts as exploited in exploitMaturity() (weaponized) and in changesSince() (a KnownExploited major change), whether or not KEV has caught up.

From the terminal

Exits non-zero when a source failed (results may be incomplete) or the query is unrecognisable — never merely because advisories were found.

Calling one source directly

What each source needs

Source Queried by Needs Notes
OsvSource ecosystem + name + version; purl (deb/apk/rpm); git commit — Batch endpoint, pagination, payload cache. Ecosystems: composer, npm, pypi, maven, nuget, go, cargo, gem, cocoapods, pub, hex, swift, conan (+ deb/apk/rpm by purl). Unmapped ecosystems are skipped, not guessed.
NvdSource CPE api_key recommended 5 req/30s anonymous, 50/30s with a key — the source throttles itself. Parses configurations into real version ranges.
CveSearchSource CPE — CIRCL; records often carry no version data (treat as undeterminable).
GitHubAdvisorySource ecosystem + name (registry); owner/repo (repository advisories) token for the registry feed Repository advisories work without a token — they cover projects that are in no registry database.
EuvdSource ecosystem + name — ENISA EUVD.
SnykSource purl token + org_id Disabled unless both are configured.
OssIndexSource purl username + api_token (free account) Sonatype's dataset; batched 128 purls per request. Disabled without credentials — anonymous access 401s since 2025. Versionless packages are skipped.
RedHatSource name — Red Hat Security Data — the source for RPM-ecosystem and container base-image packages. NEVRA strings land in extra, not ranges.
ShodanCvedbSource name (product search) — One record carries CVSS + EPSS + KEV.
MitreCveSource fetchById only — Authoritative CVE Record v5 (incl. CNA CVSS v4), often live before NVD analysis. No package search.
VulnCheckSource fetchById only api_token VulnCheck Community "NVD++" — NVD 2.0-shaped records without the NVD lag. Disabled without a token.

A CPE-driven source given a package without a CPE derives one from the purl or name (CpeResolver), or from your curated catalog if you bind Contracts\CpeLookup. Passing PackageData::fromCpe(...) — or cpe23: on the constructor — always wins over both.

Coordinates convert in every direction: build a PackageData from a purl, a CPE, or a git commit (fromPurl / fromCpe / fromCommit — bare sha or forge commit URL), and read the other form back off it:

Credentials & configuration

No source needs a key to work; keys raise limits or unlock a feed:

Env var Used by Effect if unset
NVD_API_KEY NVD Still works at 5 req/30s instead of 50 — the source throttles itself either way.
GITHUB_TOKEN GitHub Advisories Repository advisories still work; the registry GraphQL feed is skipped.
SNYK_API_TOKEN + SNYK_ORG_ID Snyk Source stays disabled (it needs both).
OSS_INDEX_USERNAME + OSS_INDEX_API_TOKEN OSS Index Source stays disabled (it needs both).
VULNCHECK_API_TOKEN VulnCheck Source stays disabled.

OSV, CVE-Search, EUVD, Red Hat, Shodan CVEDB, MITRE — and the EPSS / KEV enrichment feeds — need no credentials at all.

In Laravel — just set the env vars. The package's config is merged automatically, so app(VulnSearch::class) and every app(…Source::class) pick the credentials up with no further wiring:

Publishing the config is optional — do it to change base URLs, cache TTLs, concurrency, or to toggle sources per environment:

Config beats env: anything you set in config/vulns.php (or at runtime with config([...])) is what the source receives.

In plain PHP — there is no config file; pass the block directly, so the credential comes from wherever you keep secrets:

Every source also understands enabled, timeout, retry and base_url (point CVE-Search or OSV at a self-hosted instance). Keys are read per request and never written anywhere by this package.

Laravel

Auto-discovered. Publish the config to tune sources:

Logging goes to the app logger and payload caching to the app cache automatically. Bind Gumslone\Vulns\Contracts\CpeLookup to plug a curated PURL→CPE catalog into the NVD-style sources.

Plain PHP

Every source takes (?Client $http, array $options, ?LoggerInterface $logger, ?CacheInterface $cache).

What you get back

Gumslone\Vulns\Data\VulnerabilityData — a normalised record, whatever source answered. A real result from searchPurl('pkg:npm/[email protected]'):

Fields a given source doesn't provide are null or empty — merging across sources is what fills them in, so OSV's ranges and NVD's score end up on the same record. EPSS and KEV are stamped after the merge by the threat enricher (see above), and $fresh->changesSince($stored) classifies what a re-query changed — including landing in KEV or crossing the EPSS triage threshold.

CVSS: a score always has its vector

Feeds are inconsistent here — EUVD, Snyk, Shodan and Red Hat often publish a bare score, OSV only a vector, and some file a CVSS:4.0 vector in the v3 column. Every VulnerabilityData completes this on construction:

Anything filled in this way is listed in $v->inferredFields (isInferred('cvss_v3_vector'), reported('cvss_v3_vector') for the source's own value or null), so reports can mark it — and the merge always prefers a source's own vector or link over another record's inferred one, whichever record wins. Merged records also keep every source's link in $v->extra['source_urls'].

Adjusting a score for your environment (vector merging)

A CVSS vector is three groups of metrics:

Group What it says v3 metrics v4 metrics
Base how bad the flaw is, as published by the advisory AV AC PR UI S C I A AV AC AT PR UI VC VI VA SC SI SA
Temporal (v4: threat) how real the threat is right now — exploit code, a patch E RL RC E
Environmental what it means for you — your deployment, your data CR IR AR + MAV MAC MPR MUI MS MC MI MA CR IR AR + MAV … MSA

CvssVector (v2.0, v3.0, v3.1, v4.0) keeps them apart. The base group is the advisory's and never changes; you set the other two and read the score each group yields.

Scenario 1 — an assessor adjusts an advisory for their own deployment. CVE-… is a 9.8; there's only proof-of-concept code, an official fix exists, and in this deployment the component is reachable only locally by admins:

Set a metric to X (or null) to unset it again; an illegal value or an unknown metric throws instead of silently scoring as something else.

Scenario 2 — you have two vector strings: take the temporal + environmental metrics from A and put them on the base of B. Typical when your environment profile lives in one vector and the advisory in another — or when the advisory (B) already carries somebody else's modifiers that you want replaced with yours (A):

B's E:U/RL:W/MAV:A/CR:H are gone entirely — replaced, not combined. That holds metric by metric: if A had no RL, C would have no RL either, and if A carries no modifiers at all, C is B's bare base. To move one group only:

The three ways to combine, side by side. Same B, and an A that sets E:P and MAV:L but no RL:

B's base metrics both set (E, MAV) metrics only B sets (RL, CR) metrics only A sets
withModifiersOf($a) kept A's dropped A's
merge($a) kept A's B's A's
fill($a) kept B's B's A's

merge($a, keepBase: false) flips the roles (A's base, B's modifiers on top).

Rules that apply to all of them. Scores are always recomputed from the metrics — CVSS has no way to carry a temporal or environmental score over as a number, only the metrics that produce it. Both vectors must share a major version: v3.0 and v3.1 mix (the result keeps the base's prefix), v3 and v4 don't — a v3 environmental group means nothing on a v4 base, so that throws InvalidArgumentException. In v4 the "temporal" group is the single threat metric E, and the base's supplemental metrics (S AU R V RE U) pass through:

On a vulnerability record the same operations act on the record's own vector; the stored base score field is never rewritten, the adjusted figure is read separately:

Does it actually affect my version?

Not every source version-filters: some return advisories for a package name. VersionRange answers the real question, and deliberately distinguishes "proven safe" from "can't tell":

null means undeterminable — decide your own fail-safe (a scanner should usually keep the finding and flag it for review rather than silently drop it).

Related

Testing code that uses this package

Gumslone\Vulns\Testing\FakeSource is a canned source for your own tests — answers by package name or purl, finds records by id or alias, and can be made to fail so the "source down" path is exercised:

Tests

License

MIT


All versions of laravel-vulns with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
guzzlehttp/guzzle Version ^7.8
illuminate/collections Version ^11.0 || ^12.0 || ^13.0
psr/log Version ^2.0 || ^3.0
psr/simple-cache Version ^2.0 || ^3.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package gumslone/laravel-vulns contains the following files

Loading the files please wait ...