-
Notifications
You must be signed in to change notification settings - Fork 100
#185 Fixing critical vulnerabilities on 2.0.0-beta.2, caused by [email protected] #186
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Thank you so much, Isahann! @JohannesHoppe will review and merge this one. |
|
@isahann Thanks for starting this PR! 😃 🙏 Do you think you have the resources to figure out how we can address the breaking change? |
I've just downloaded the repo, haven't checked much of it besides the package.json and the breaking test.... But I'll try to take a better look into it... |
|
We have holidays in Germany. I will run all tests on Monday! 👍 |
|
@JohannesHoppe Any updates from the Monday tests? Would be awesome to see this critical vulnerability fixed. |
|
Excuse me, just commented to up the topic |
|
Any updates on this? |
|
I'm also looking forward this new version to be available, any update on this PR? |
|
Looking forward to merge this PR - folks. Current version is causing havoc with the critical vulnerabilities |
|
👀 |
|
@JohannesHoppe any updates on this? I've recently updated to v2.0.3, but I see that it's still using [email protected]... |
|
Any chance of movement? Would you like any help? |
|
This PR addressing a critical vulnerability has been open for over a year. @JohannesHoppe, could you please confirm whether this repository is still being maintained? My team needs to decide whether to continue relying on this package or migrate away in order to resolve the issue. |
|
Hi @BGBRWR, thank you very much for your patience, and sorry for the long delay in responding - I’ve been on a long holiday and just got back. The main issue with PR #186 is that it bumps gh-pages from v3 to v6. That introduces some tricky changes, especially because gh-pages updated its dependency on commander. Unfortunately, that results in a different version of commander than the one we’re currently using. I tried to update this in the past, but commander itself introduced breaking changes in how values are parsed from the command line. From what I remember, it opens the door to all kinds of regressions. Another challenge is that no tests are failing with this PR, which is actually a sign that we don’t have test coverage for this area. Until now we’ve just assumed infrastructure like commander wouldn’t change in breaking ways. That leaves us with three possible paths forward:
Each option is quite intensive. To make progress, I’ll start by increasing the test coverage this weekend, so we can document the current status quo. That way we’ll have a foundation for moving forward. Thanks again for your patience and understanding! |
Short Update: Analysis of Breaking ChangesThank you all for your patience! I've completed a first analysis of the dependency upgrades and discovered several critical issues that need careful handling. Current versions: gh-pages: ^3.1.0 → ^6.1.1 (3 major versions) 1. Critical Finding: gh-pages Promise Bug (FIXED in v5.0.0)The Problem We've Been Working Around: In gh-pages v3.1.0, the publish() method has a critical bug where early error cases don't return a promise, causing errors to be silently swallowed if you use Evidence: try {
if (!fs.statSync(basePath).isDirectory()) {
done(new Error('The "base" option must be an existing directory'));
return; // ❌ NO PROMISE RETURNED!
}
} catch (err) {
done(err);
return; // ❌ NO PROMISE RETURNED!
}Our Workaround: // do NOT (!!) await ghPages.publish,
// the promise is implemented in such a way that it always succeeds – even on errors!
return new Promise((resolve, reject) => {
ghPages.publish(dir, options, error => {
if (error) {
return reject(error);
}
resolve(undefined);
});
});Fixed in v5.0.0+:
Impact: Our callback workaround should still work in v6, but we need intensive testing of error cases after upgrade and remove the workaround if possible. 2. Critical Finding: CNAME and .nojekyll File Creation (NEW in v6.1.0)The Change: gh-pages v6.1.0 added native support for creating CNAME and .nojekyll files, which we've been creating manually since the beginning. Evidence:
.then((git) => {
if (options.nojekyll) {
log('Creating .nojekyll');
fs.createFileSync(path.join(git.cwd, '.nojekyll'));
}
if (options.cname) {
log('Creating CNAME for %s', options.cname);
fs.writeFileSync(path.join(git.cwd, 'CNAME'), options.cname);
}
// ...
})Our Current Implementation: Impact:
3. Critical Finding: commander Boolean --no- Options Default Handling (v9)THE MOST CRITICAL ISSUE! Commander v9 completely changed how boolean options with --no- prefix handle default values. Evidence:
Our Broken Code: .option('-T, --no-dotfiles', 'Includes dotfiles by default...')
.option('--no-notfound', 'By default a 404.html file is created...')
.option('--no-nojekyll', 'By default a .nojekyll file is created...')The Problem: Our defaults are in https://github.com/angular-schule/angular-cli-ghpages/blob/v2.0.3/src/engine/defaults.ts#L8-L10: dotfiles: true, // Default should be true
notfound: true, // Default should be true
nojekyll: true, // Default should be trueBut commander options DON'T have these defaults specified!
Impact:
Fix Required: // Option 1: Pass defaults explicitly
.option('-T, --no-dotfiles', 'description', defaults.dotfiles)
.option('--no-notfound', 'description', defaults.notfound)
.option('--no-nojekyll', 'description', defaults.nojekyll)4. Critical Finding: commander v9: Option Property Casing ChangeProblem:
Our Code Impact: We access them as: commander.dir, commander.repo, commander.name, etc. (lowercase) User Impact - BREAKING: Our Risk:
Cannot prevent or fix - this is commander's new behavior! (So do we really want to upgrade, see below!) 5. Critical Finding: commander v9: Excess Arguments ErrorProblem:
User Impact - BREAKING: We could explicitly set commander
.allowExcessArguments(true) // Restore v3 behaviour
.option(...)Minor Breaking Change: commander Default Export Removed (v12)The Issue: Our standalone CLI uses the default export which was removed in commander v12. Evidence:
To many breaking changes in commander!I must admit, I'm quite concerned about the extent of breaking changes in commander across major versions. The fundamental changes to boolean option handling, default value behaviour, and potentially more (??) represent significant shifts in the library's API contract. Given that we use only a small subset of commander's features (basic option parsing for our standalone CLI), it may be worth considering forking commander v3, stripping it down to just what we need, Other Small Breaking Changes (not an issue)
|
This massive update increases test coverage from 213 to 285 tests (+72 tests, +34%) to prepare for the gh-pages v6 upgrade (PR #186). All critical paths are now tested, prepareOptions is refactored into testable functions, and a public API is exported. ## Phase 1: Critical Test Gaps (20 new tests) ### gh-pages Error Callback Tests (4 tests) - Add tests for the "do NOT await" error handling pattern - Test error rejection, message preservation, and auth failures - Verifies we never fall into gh-pages v3 silent failure trap - File: src/engine/engine.spec.ts ### Monkeypatch Verification Tests (5 tests) - Add first-ever tests for util.debuglog interception (was 0% coverage) - Test gh-pages logging forwarding to Angular logger - Test message formatting with placeholders - Verify critical ordering (monkeypatch before gh-pages require) - File: src/engine/engine.spec.ts ### Real Filesystem Tests (11 tests) - Create first-ever real filesystem integration tests - Use actual temp directories instead of mocks - Test .nojekyll, CNAME, and 404.html file creation - Test graceful error handling when index.html missing - File: src/engine/engine-filesystem.spec.ts (NEW) ## Phase 2: Refactor prepareOptions (34 new tests) ### Code Refactoring - Extract prepareOptions (157 lines) into 6 testable functions: 1. setupMonkeypatch() - Intercept util.debuglog 2. mapNegatedBooleans() - Transform noDotfiles → dotfiles 3. handleUserCredentials() - Create user object or warn 4. warnDeprecatedParameters() - Warn about deprecated noSilent 5. appendCIMetadata() - Add CI environment metadata 6. injectTokenIntoRepoUrl() - Inject authentication tokens - prepareOptions() is now a clean orchestrator function - File: src/engine/engine.ts ### Intensive Tests - Add 34 comprehensive tests covering 100% of option transformation logic - Test every extracted function exhaustively with all edge cases - Covers all boolean combinations, CI environments, and token scenarios - File: src/engine/prepare-options.spec.ts (NEW) ## Phase 3: Export Public API (18 new tests) ### Public API Exports - Export Schema, PublishOptions, DeployUser, and other types - Export defaults configuration object - Export core functions (deployToGHPages, angularDeploy) - Export advanced functions (all prepareOptions helpers) - Users can now extend angular-cli-ghpages functionality - File: src/public_api.ts ### Public API Tests - Add 18 tests verifying all exports are accessible - Test type compilation and runtime function availability - Include example usage scenarios - File: src/public-api.spec.ts (NEW) ## Documentation - Add TEST_COVERAGE_PLAN.md documenting the complete plan - Includes implementation order, success criteria, and file listing - Documents context from PR #186 analysis ## Test Results - Test suites: 16 → 18 (+2) - Tests: 213 → 285 (+72, +34%) - Pass rate: 100% (285/285) - Zero regressions ## Breaking Changes None - all changes are backwards compatible. The refactoring maintains exact same behavior while adding exports and improving testability. ## Related - Addresses PR #186 preparation (gh-pages v3 → v6 upgrade) - Completes audit remediation priorities 7-10 - Enables future refactoring with test safety net
Add extensive test coverage for PR #186 breaking change analysis: 1. Commander v3 Boolean Defaults (NEW FILE) - pr-186-commander-defaults.spec.ts (9 tests) - Tests Commander v3 fork --no- option behavior - Covers all edge cases: single, double, triple negations - Documents why we forked Commander v3 (avoid v9+ breaking changes) - Eliminates all 'as any' violations (HARD RULE compliance) 2. gh-pages v6.1.0+ File Creation Compatibility - engine-filesystem.spec.ts (+3 tests) - Verifies we DON'T pass cname/nojekyll to gh-pages - Documents that gh-pages v6+ would create duplicates - Explains future upgrade path options 3. gh-pages Promise Bug Documentation - engine.gh-pages-behavior.spec.ts (documentation block) - Documents gh-pages v3.1.0 early error promise bug - Explains our callback workaround in engine.ts - Notes fix in v5.0.0+ and upgrade implications Test Results: - 354 tests passing (consolidated redundant tests) - Zero 'as any' violations - Complete edge case coverage - Production-ready for external audit Related: PR #186 (gh-pages v3→v6 & commander v3→v14 analysis)
Just upgraded to the latest version of
gh-pagesavailable at the moment.After upgrading, removed the
node_modules,package-lock.json, and then ran a freshnpm i.Building with
npm buildruns just fine. And after fixing a single test,npm test(building first) passes all tests too.Please feel free to request any changes.