Skip to content

docs(supply-chain): add private registries and package mirrors - #627

Open
s1ns3nz0 wants to merge 2 commits into
security-alliance:developfrom
s1ns3nz0:docs/private-registries-and-mirrors
Open

s1ns3nz0 wants to merge 2 commits into
security-alliance:developfrom
s1ns3nz0:docs/private-registries-and-mirrors

Conversation

@s1ns3nz0

@s1ns3nz0 s1ns3nz0 commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

What does this PR change?

Adds a Supply Chain page on running an internal package registry: what mirroring gives a team, how registry routing blocks dependency confusion, and why the registry becomes a component that has to be secured like part of the pipeline.

The gap is that this framework already recommends the control in four places and never explains it:

  • devsecops/repository-hardening.mdx:251 — "Consider using a private registry (Artifactory, npm enterprise) to proxy and cache dependencies, preventing dependency confusion attacks."
  • devsecops/security-testing.mdx:120 — the same recommendation with different tools
  • incident-management/.../runbooks/dependency-attack.mdx:84 — "Consider using a private registry" as a prevention checklist item
  • front-end-web-app/third-party-script-security.mdx:300 — points at Dependency Awareness "for guidance on vendoring, version pinning, and managing the operational trade-offs"

That last one links to something that is not there. Dependency Awareness mentions vendoring twice while listing lockfile mechanisms and never covers it. Dependency confusion is named twice across the whole repository and never explained, so a reader who follows the recommendation has no way to learn what it defends against or how to configure it.

This PR adds the page and points those four mentions at it. For third-party-script-security the reference is split, so version pinning still routes to Dependency Awareness and vendoring routes here.

What the page covers

Cache, curation, and vendoring. Three arrangements get called the same thing and give different guarantees. A pull-through cache delivers availability and a record but not a gate; a curated repository is the arrangement that turns a registry into a control, and it needs an owner; vendoring removes the registry entirely at the cost of updates becoming commits.

Dependency confusion. The failure is in resolution order, so pinning a version does not address it. Two controls close it and both belong at the registry: reserving the namespace publicly, and routing by name with index replacement instead of index extension. The pip --index-url / --extra-index-url distinction is the concrete case.

The registry is part of the trust base. Routing configured correctly means every resolution terminates at the internal registry, which is the protection and also what makes it worth attacking. A lockfile does not close this: it records hashes computed from whatever was fetched when the lock was written, so a registry already serving modified content at lock time gets those bytes recorded as correct. Write access, the promotion path, the registry's own upstream credentials, and backups become security controls.

Operational failure modes. A stale cache hiding an upstream security release, an unowned approval queue that developers route around, an upstream deletion becoming invisible including a malware takedown, and availability risk concentrated in one server.

Scope boundaries

Written to avoid overlapping what already exists:

Existing page Keeps This page
Dependency Awareness pinning, lockfiles, checksums the operator side, and links out instead of restating
Policy as Code the registry allowlist as policy data a gate reads how the registry behind that allowlist is run
Supply Chain Levels artifact risk tiering links to it for deciding what warrants curation

Type of change

  • New content
  • Edit to existing content
  • Outline / structure change
  • Typo or formatting fix
  • Tooling / config

If applicable

  • Editing existing content: tagged the current contributors from the attribution list
  • Framework has a steward: asked them to review (Supply Chain is on the open-steward list)
  • Outline change: updated vocs.config.ts with the dev: true parameter
  • Want community feedback: shared this PR in our Discord

Verification

  • validate:content --path docs/pages/supply-chain — 7 passed, 0 failed
  • markdownlint-cli2 on every touched file — no new issues. The three MD013 warnings in dependency-attack.mdx are on lines I did not touch and are present on develop.
  • cspell — clean; Birsan added to wordlist.txt
  • docs:build — passes
  • All six internal links resolve and are registered in the sidebar; the three external links return 200 and their anchors exist
  • Rendered locally and checked the page, the sidebar entry, and the interactive checklist
  • Style guide: sentence-case headings, RFC modality in the checklist, no second person, concrete subjects
  • Commits are signed

A note on drafting

I picked the topic, ran the overlap check against the existing pages, and set the scope boundaries above. English is not my first language, so I used AI assistance for phrasing and for auditing the draft against the content model and style guide.

Four pages already recommend running a private registry without explaining
it: repository-hardening, security-testing, the dependency-attack runbook,
and third-party-script-security. The last of those points at Dependency
Awareness "for guidance on vendoring", which that page does not cover.
Dependency confusion is named twice across the repository and never
explained.

Adds a page covering what each arrangement gives a team (pull-through
cache, curated repository, vendoring), how registry routing closes
dependency confusion, why the registry itself joins the trust base, and the
operational failures that remove the properties it was deployed for.

Points the four existing mentions at the new page, and splits the
third-party-script-security reference so pinning still routes to Dependency
Awareness while vendoring routes here.

Claude-Session: https://claude.ai/code/session_01CPQ1FcHGiBKWPd8waT7uGx
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

Sidebar Configuration Reminder

This PR includes added, renamed, or removed documentation files:

  • docs/pages/supply-chain/private-registries-and-mirrors.mdx (added)

Please ensure that:

  • The sidebar in vocs.config.ts has been updated to include these files
  • New content has the dev: true parameter so it's marked as under development
  • Sidebar links match the file paths - use the preview deployment to verify

See Contributing guidelines - Sidebar / Navigation for more details.


This is an automated reminder. If this PR doesn't need sidebar changes, you can ignore this message.

@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
built with Refined Cloudflare Pages Action

⚡ Cloudflare Pages Deployment

Name Status Preview Last Commit
frameworks ✅ Ready (View Log) Visit Preview 1c971b2

@frameworks-volunteer frameworks-volunteer left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Model: x-ai/grok-4.6 Reasoning: medium Provider: openrouter

Security: no secrets, no XSS/eval, no suspicious deps. External links are the Birsan writeup, Microsoft private-feed guidance, npm scope docs, and pip index-url docs. CI is green (lint, preview build, Socket).

QA: page fills a real gap (four existing mentions had nowhere to land). Cache vs curated vs vendoring, extra-index-url vs index-url, and lockfile-timing vs registry integrity are accurate and scoped against Dependency Awareness / Policy as Code / Supply Chain Levels. Sidebar dev: true, cspell Birsan, and inbound links look correct.

One fix before merge:

  • s1ns3nz0 is in frontmatter contributors.wrote but is not in docs/pages/config/contributors.json. AttributionList drops unknown slugs, so the page will render with no author. CONTRIBUTING requires a profile there on first contribution.

Nits (non-blocking):

  • security-testing.mdx inbound text says "what each arrangement gives you" (second person). The new page itself stays third-person.
  • Pinning claim is slightly broad: exact-pin + lockfile hashes still help after lock; the real miss is resolution order before/without a lock, and same-version squat. The later lockfile-timing section already covers this.

No request-changes on content. Add the contributor profile and this is ready.

Address review nits on security-alliance#627.

The dependency confusion section claimed a version pin does not address the
attack, which overstated it and contradicted the lockfile-timing paragraph
later on the same page. A lockfile with integrity hashes does catch a
substitution on later installs; the exposure is the resolution that writes
the lock, and a name that was never published publicly the moment an
attacker claims it.

Also replaces "gives you" with "provides" in the security-testing inbound
link, matching the third person the rest of the page uses.

Claude-Session: https://claude.ai/code/session_01CPQ1FcHGiBKWPd8waT7uGx
@s1ns3nz0

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Both nits are fixed in e9bfc9d.

The pinning claim was the more useful catch. You're right that it overstated things, and it also contradicted my own lockfile-timing paragraph later on the same page. Rewritten:

The failure is in resolution order, not in the package itself, so a version constraint does not close it on its own. A lockfile with integrity hashes catches a substitution on later installs, but the lock has to be written from a correct resolution first, and an internal name that has never been published publicly becomes resolvable from a public source the moment an attacker registers it.

That now sets up the trust-base section instead of arguing with it.

Second person in the security-testing.mdx inbound link: "gives you" is now "provides".

On the blocking item, I think this one is a false positive. s1ns3nz0 is already in docs/pages/config/contributors.json on develop — it was added when #592 merged, which is why this PR's diff does not touch that file. AttributionList looks up contributorsData[slug] and the key matches exactly.

The preview build confirms it renders: https://s1ns3nz0-docs-private-regist.frameworks-573.pages.dev/supply-chain/private-registries-and-mirrors shows "Authored by: s1ns3nz0" with the avatar and profile link.

Happy to be corrected if you're seeing something different.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

content:add This issue or PR adds content or suggests to

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

4 participants