RoastMyOpsec

Vulnerabilities

composer.json vs package.json on Production Origins

July 24, 2022

composer.json vs package.json on production origins is two language manifests that must not sit next to index.html. /package.json donates npm names and versions. /composer.json (and composer.lock) donates PHP packages and constraints — the same inventory class for WordPress plugins, Laravel, and Symfony shops. Neither is a pentest. Both shrink reconnaissance and feed advisory lookups. A private Packagist or npm registry is the public catalog. The marketing CDN is not. RoastMyOpsec probes /package.json with a bounded GET. It does not currently score /composer.json, does not parse lockfiles on the URL scan, and does not install packages.

The practical difference

package.json is Node. composer.json is PHP. Dockerfile is how the image is built. composer.lock and package-lock.json pin versions more tightly than the manifest — still do not serve them from the brochure origin. OSV deepen on a repo you own is a different channel than a GET to the CDN.

A 200 on /composer.json is an information leak even when every version is already on Packagist.

How to choose what to publish

CI: fail if composer.json, composer.lock, package.json, or lockfiles appear in a static marketing artifact. WordPress: the app may live on the same host — still deny those filenames at the CDN for paths that are not the app's private deploy. Keep manifests in the private repo. Staging hostnames that are guessable get the same deny list.

FileTypical leakRoast todayTakeaway
/package.jsonJS names and versionsBounded GETSee public package.json vs OSV
/composer.jsonPHP names and versionsNot scored; deny anywaySame class
/composer.lockPinned PHP treeNot scoredDeny the name
/DockerfileImage build inventoryNot scoredSee Dockerfile vs package.json

When composer.json still wins (off the public origin)

It wins in a private repo and in CI. Packagist already lists public packages. The brand origin does not need to mirror the file. Pair with phpinfo vs verbose errors if the same host also dumps the runtime.

What the roast can prove

A reachable /package.json can surface. composer.json is not a scored path. Confirm a 404 yourself. Pair with OSV lockfile deepen on a GitHub repo you own.

Common mistakes

The first mistake is deploying the whole Laravel tree to the document root including composer.json.

The second mistake is treating Packagist visibility as a reason the CDN should serve the file.

The third mistake is Disallow: /composer.json and calling it access control.

Free audit the URL you own

RoastMyOpsec is a defensive public-surface roast: headers, cookies, sensitive paths, and more — no exploit payloads. Start with the free audit, then open the vault if the blurred findings look expensive.

Free audit now

FAQ

Is a public composer.json a vulnerability?
It is an information leak. Remove it from the public origin. It is not a credential dump by itself.
Does RoastMyOpsec fetch composer.json?
Not as a scored path today. It does probe /package.json. Deny Composer filenames at the edge anyway.
Does composer.lock belong on the CDN?
No. Keep lockfiles in the private repo. Use OSV on a repo you own, not a marketing URL.

Sources

Related guides