You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
gh-pages is the last big avoidable runtime dependency of angular-cli-ghpages. It is pinned to 6.3.0 and brings its own dependency tree into every project that installs angular-cli-ghpages:
Through globby → fast-glob → micromatch, this tree includes braces, which currently has an unpatched advisory (CVE-2026-93687 / GHSA-vfj7-8cjw-p6xm, tracked upstream in micromatch/braces#73; gh-pages was notified in tschaub/gh-pages#658). Even the latest releases of that chain still depend on it. The practical impact is negligible: angular-cli-ghpages doesn't pass any glob patterns to gh-pages, so only its fixed defaults (**/* and .) reach braces. But security scanners still flag it in every downstream project.
Long-term reason
Every package in this tree is part of the supply chain of every project that uses angular-cli-ghpages. Fewer third-party packages mean a smaller attack surface.
We only use a small part of what gh-pages offers: publish(), clean() and the internal gh-pages/lib/git module (for getRemoteUrl()). On top of that, the engine already has to work around several gh-pages internals (util.debuglog setup, the find-cache-dir fallback, and a beforeAdd hook that fixes stale-file removal). Replacing that small surface with our own code is a manageable amount of work.
angular-cli-ghpages already took this approach with commander: the standalone CLI uses a minimal fork (src/commander-fork) instead of the npm package (#200). However, commander still ends up in downstream projects as a dependency of gh-pages. Removing gh-pages would finish that job.
Goal
Implement the publishing logic directly in angular-cli-ghpages and drop the gh-pages dependency.
Globbing is the easy part. We never pass src, remove or only, so gh-pages always runs with its defaults. Both are already covered by our own code in engine.prepare-options-helpers.ts:
**/* (list all files to publish) → collectDistFiles() walks the dist directory recursively and honors dotfiles the same way.
. (remove everything from the branch) → createCleanupBeforeAddHook() asks git via git ls-files -z and removes what's no longer in dist. Git already knows what's tracked, no glob needed.
Replacing only the globbing doesn't help, though: gh-pages calls globby internally either way, so braces only disappears once gh-pages is replaced as a whole.
What publish() does beyond that (gh-pages@6.3.0, lib/index.js):
Clone the target repo into the cache dir, or clean/fetch an existing clone
Check out the branch (or create it as an orphan branch)
Remove existing files (see above)
Write .nojekyll and CNAME
Copy files
git add, set the user, commit
Optionally tag
Push
Token injection into the repo URL is already done on our side. At its core this is a handful of git calls via child_process, plus proper error handling, which is exactly where gh-pages keeps causing trouble (#205). Doable, but clearly more than just the two globs.
Activity
JohannesHoppe commentedon Oct 7, 2026
Notes on the scope:
Globbing is the easy part. We never pass
src,removeoronly, sogh-pagesalways runs with its defaults. Both are already covered by our own code inengine.prepare-options-helpers.ts:**/*(list all files to publish) →collectDistFiles()walks the dist directory recursively and honorsdotfilesthe same way..(remove everything from the branch) →createCleanupBeforeAddHook()asks git viagit ls-files -zand removes what's no longer in dist. Git already knows what's tracked, no glob needed.Replacing only the globbing doesn't help, though:
gh-pagescallsglobbyinternally either way, sobracesonly disappears oncegh-pagesis replaced as a whole.What
publish()does beyond that (gh-pages@6.3.0,lib/index.js):.nojekyllandCNAMEgit add, set the user, commitToken injection into the repo URL is already done on our side. At its core this is a handful of git calls via
child_process, plus proper error handling, which is exactly wheregh-pageskeeps causing trouble (#205). Doable, but clearly more than just the two globs.