RoastMyOpsec

Vulnerabilities

Gemfile vs package.json on Production Origins

December 17, 2023

Gemfile 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. /Gemfile (and Gemfile.lock) donates Ruby gems and pins — the same inventory class for Rails, Sinatra, and Jekyll shops. Neither is a pentest. Both shrink reconnaissance and feed advisory lookups. A private gem server 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 /Gemfile, does not parse lockfiles on the URL scan, and does not install gems.

The practical difference

package.json is Node inventory. Gemfile is Bundler's constraint list. composer.json is PHP. requirements.txt is Python. Dockerfile is how the image is built. .env is secrets, not inventory.

A 200 on /Gemfile is an information leak even when every gem looks boring. Deny the names at the edge.

How to choose what to publish

CI: fail if Gemfile, Gemfile.lock, package.json, or other lockfiles appear in a static marketing artifact. App origins that must serve those files are rare — prefer not. CDN: deny those basenames. Keep Ruby files in the private repo. Staging hostnames that are guessable get the same deny list.

FileTypical leakRoast todayTakeaway
/package.jsonnpm names and versionsBounded GETSee public package.json vs OSV
/GemfileRuby gem pinsNot scored; deny anywaySame class
/Gemfile.lockExact gem graphNot scoredDeny the name
/.envLive secretsBounded signature GETSee .git vs .env

When a Gemfile still wins (off the public origin)

It wins in a private repo and in CI. It never wins as a downloadable object on the marketing bucket. Pair with requirements.txt vs package.json if the same zip also shipped Python pins.

What the roast can prove

A reachable /package.json can surface. Gemfile is not a scored path. Confirm a 404 yourself. Pair with OSV lockfile deepen on a repo you own — that is a different channel than a URL roast.

Common mistakes

The first mistake is copying the whole Rails tree to S3 because public/ lived next to the Gemfile.

The second mistake is a Gemfile source line with a private index token in the URL.

The third mistake is Disallow: /Gemfile 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 Gemfile a vulnerability?
It is an information leak. Remove it and deny the name. It is not always a credential dump, but it is not harmless.
Does RoastMyOpsec fetch Gemfile?
Not as a scored path today. It does probe /package.json. Deny Ruby inventory filenames at the edge anyway.
Does Gemfile.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