Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions AUDIT.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ Living posture notes for **hub.fabric.pub** (`@fabric/hub` **0.1.0-RC1**). Re-ru

| Area | Posture |
|------|---------|
| `@fabric/core` | Git pin `FabricLabs/fabric#feature/rsi` (lockfile SHA `1fc616492428ec6e8c731e3afb74fd841407aa0e`) |
| `@fabric/http` | Git pin `FabricLabs/fabric-http#feature/rsi` (lockfile SHA `852520a2bd1070bb974b1a34297811f3c63588eb`) |
| `@fabric/core` | Git pin `FabricLabs/fabric#feature/rsi` (lockfile SHA `9f2eb9453d3af0678b1b393ac0b157b2810f56a0`) |
| `@fabric/http` | Git pin `FabricLabs/fabric-http#feature/rsi` (lockfile SHA `cbdfa858a40fb5ad17be66860d2de928114d1686`) |
| npm `allow-git` | **`.npmrc` `allow-git=all`** — required for nested git-dep preparation (commit-SHA fetches of core/http); `root` is insufficient |
| Node | **`engines.node` = `24.15.0`** (aligned with core / http) |
| WebSocket (`ws`) | **Mitigated** — direct + override **`8.21.2`** |
Expand Down Expand Up @@ -63,9 +63,9 @@ Living posture notes for **hub.fabric.pub** (`@fabric/hub` **0.1.0-RC1**). Re-ru
| Device-link linked GET starving the peer | Fixed upstream in `@fabric/http` (keep until TTL; Hub re-exports) |
| Site-login / device-link Origin redeem | Open — inherited from `@fabric/http` (possession proof). Http device-link also allows thin-client Origins on allowlisted hubs; still not a possession proof. |
| Device-link client-supplied nonce | Open — inherited from `@fabric/http` (prefer always-fresh nonce) |
| Device-link FIFO eviction under create flood | Opennit; per-origin quota |
| Device-link FIFO eviction under create flood | Fixedhttp `MAX_SESSIONS_PER_ORIGIN`; Hub re-exports |
| Identity import / stronger at-rest crypto | Deferred — heavy lift |
| Large WIP split into stacked PRs | Open — process |
| Large WIP split into stacked PRs | Open — process ([#15](https://github.com/FabricLabs/hub.fabric.pub/pull/15) merged; remaining RSI is follow-up PRs) |
| Fabric hallmarks (opt-in OP_RETURN) | In tree — Hub publish/scan + docs; regtest-only |

## Disclosure
Expand Down
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
All notable changes to **hub.fabric.pub** (Fabric Hub) are documented here. RCs are coordinated with **`@fabric/core`** and **`@fabric/http`**.

## [Unreleased]
- **Chat shoutbox:** WebRTC → Fabric TCP `P2P_RELAY` inner chat is UTF-8 text (legacy JSON `{ object.content }` envelopes are unpacked). Registry marks `P2P_CHAT_MESSAGE` as `utf8-text`; author is AMP signature.
- **Bulk security-advisory ingest:** drop OpenSSF / GHSA malware dumps (`security_advisory`, `@zalastax/nolb-*`, “Malicious code in @…”) on `CreateDocument`, P2P file receive, inventory resync, and `recordActivity`. Those Internal-message floods OOMed production Hub. Pair with `@fabric/http` Internal-log + commit snapshot cuts.
- **Chat shoutbox:** WebRTC → Fabric TCP `P2P_RELAY` inner chat is UTF-8 text (legacy JSON `{ object.content }` envelopes are unpacked via `@fabric/core/functions/fabricChatText`). Registry marks `P2P_CHAT_MESSAGE` as `utf8-text`; author is AMP signature.
- **IdentityCrossSign:** `functions/identityCrossSign.js` / `identityCrossSignVerify.js` re-export `@fabric/core`.
- **Identity cluster:** ingest keys must be compressed or x-only hex (`pubkeyXOnly`); colon-smashed strings are `invalid pubkey`.
- **Beacon:** Hub ready-round retry tests match core recovered-witness checks (real Schnorr; fake `'00'` is rejected).
- **Device link:** per-origin create quota is in `@fabric/http` (`MAX_SESSIONS_PER_ORIGIN`); Hub re-exports it from `functions/fabricDeviceLink.js`. Browser device-link fetch omits client-set Origin/Referer.
- **Site login:** expired `GET /sessions/:delegationToken` requires matching `Authorization: Bearer` (http pin).
- **Pins:** `@fabric/core` lockfile `1fc616492…` (first-tier RC1 contract, undersize AMP drop, IdentityCrossSign kind/id guards, canonical `host:port` dial keys); `@fabric/http` lockfile `852520a…` (`pubkey@` strip + dedicated-NIC `:7778`→`:7777`, `--wallet -p` is not a path, Bearer path-token). `package.json` stays on `#feature/rsi`. `report:install` wipes the lockfile then `npm i --allow-git=all`.
- **Pins:** `@fabric/core` lockfile `9f2eb9453…` (UTF-8 shoutbox `fabricChatText`, IPv6 `_connect` bracket strip, first-tier RC1 contract); `@fabric/http` lockfile `cbdfa858…` (Internal-log/commit snapshot cut, `fabricChatText` re-export, `pubkey@` strip + dedicated-NIC `:7778`→`:7777`, Bearer path-token). `package.json` stays on `#feature/rsi`. `report:install` wipes the lockfile then `npm i --allow-git=all`.
- **Managed Bitcoin:** Hub RPC probe keeps cookie credentials (no longer a port-only stub that 401s an orphan `bitcoind`). Spawn early-exit / datadir lock **attaches** to the live node instead of `pm2` crash-looping. Shutdown kills only a Core this process spawned.
- **Playnet:** `npm run playnet:status -- --production` reports native `fabric-beacon` plus an optional sibling GoonCitizen contract id. Deploy the application namespace from GoonCitizen: `npm run playnet:deploy-gooncitizen -- --production --accept`.
- **SPA assets:** `assets/scripts/assets/manifest.json` loads the same-origin `/bundles/browser.min.js` (no remote `fabric.pub` script URI).
Expand Down
4 changes: 2 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ Hub admin capabilities (Beacon accept, generateblock, wallet spend, **regtest fa
## Outstanding (PR #15 / RSI follow-ups)
- **Identity import** — xprv imports should persist through the encrypted identity path (not watch-only `id`/`xpub`) and restore locked/unlocked per password flow (heavy lift; extension sync no longer writes unlocked `xprv`/`masterXprv`).
- ~~**Encrypted backup export**~~ — primary “Download encrypted backup” requires an unlocked signing `xprv` (watch-only disabled + labeled).
- **Large WIP split** — PR #15 still spans far more than review-tool limits; land remaining RSI work as stacked PRs (identity, Bitcoin/HTLC, WebRTC, docs).
- **Large WIP split** — [PR #15](https://github.com/FabricLabs/hub.fabric.pub/pull/15) merged; land remaining RSI (identity import/KDF, login redeem) as stacked follow-ups.
- **`GenericMessage` / WS** — see [MESSAGE_TRANSPORT.md](MESSAGE_TRANSPORT.md); prefer named AMP types on public hubs.
- ~~**`@fabric/core` / `@fabric/http` pin hygiene**~~ — pins: core `1fc616492428ec6e8c731e3afb74fd841407aa0e`, http `852520a2bd1070bb974b1a34297811f3c63588eb` (refreshed via `feature/rsi`; `report:install` wipes the lockfile then `npm i --allow-git=all`). Keep `package.json` on moving `feature/rsi` during RSI; re-pin releases to lockfile SHAs.
- ~~**`@fabric/core` / `@fabric/http` pin hygiene**~~ — pins: core `9f2eb9453d3af0678b1b393ac0b157b2810f56a0`, http `cbdfa858a40fb5ad17be66860d2de928114d1686` (refreshed via `feature/rsi`; `report:install` wipes the lockfile then `npm i --allow-git=all`). Keep `package.json` on moving `feature/rsi` during RSI; re-pin releases to lockfile SHAs.
- ~~**Fabric coin types**~~ — `functions/fabricAccountDerivedIdentity.js` uses core `fabricIdentityDerivationPath` (default **7778**; optional `mainnet` / **7777**). Wire Hub UI / bitcoin network into that optional arg where product wants mainnet identity paths.
- **Site-login / device-link Origin gates** — inherited from `@fabric/http` (forgeable Origin/Referer for session/device-link redeem on shared hosts; Hub self-sign is opt-in + loopback-only in http). Site-login uses `clientMayPollDesktopSession`. Device-link uses that plus thin-client Origins on allowlisted hubs (`clientMayAccessDeviceLink`, re-exported from `functions/fabricDeviceLink.js`). Not a possession proof. Prefer possession proofs before treating QR `sessionId` as browser-grade auth; cleartext production hubs are no longer default-allowlisted. Per-origin device-link create quota is in http. Remaining coordinated follow-ups: always-fresh device-link nonce, bind `sessionId` into link messages.
- **Payment test route** — Hub defaults `exposePaymentTestRoute` **off**; set `FABRIC_HTTP_PAYMENTS_EXPOSE_TEST_ROUTE=1` (or legacy `FABRIC_HTTP_PAYMENTS_HIDE_TEST_ROUTE=0`) when needed for local 402 checks.
Expand Down
10 changes: 5 additions & 5 deletions docs/OUTSTANDING.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Outstanding (security-first)
Living queue for this repo. Detail and closed items live in [SECURITY.md](../SECURITY.md) and [AUDIT.md](../AUDIT.md). Operator deploy: [PRODUCTION.md](PRODUCTION.md). Product roadmap: [PRODUCTION_ROADMAP.md](PRODUCTION_ROADMAP.md). Core class-surface march: [PRODUCTION_MARCH.md](PRODUCTION_MARCH.md).

**Last reviewed:** 2026-08-14 (Hub `4c1cd14` + this slice, core lockfile `1fc616492`, http lockfile `852520a`).
**Last reviewed:** 2026-08-14 (Hub this slice, core lockfile `9f2eb9453`, http lockfile `cbdfa858`).

## Blockers before production shared bind
1. **Inherited login/link redeem** — QR `sessionId` + forgeable Origin is still the capability ([`@fabric/http` OUTSTANDING](https://github.com/FabricLabs/fabric-http/blob/feature/rsi/docs/OUTSTANDING.md)). Hub desktop `allowHubSelfSign` defaults on; http **loopback-gates** the sign so public `hub.fabric.pub` cannot remote self-sign.
Expand All @@ -11,9 +11,9 @@ Living queue for this repo. Detail and closed items live in [SECURITY.md](../SEC
## Next slices
- [ ] Always-fresh device-link nonce (reject client-supplied) — coordinated with http.
- [ ] Named AMP types on public Hub UI WebSocket (`GenericMessage` remaining).
- [ ] Split [PR #15](https://github.com/FabricLabs/hub.fabric.pub/pull/15) (review tools skip at 100+ files; Codacy reports a 100-issue cap on the whole PR).

## Closed this pass (do not re-open)
- Bulk OpenSSF / GHSA malware-advisory documents are not ingested (`functions/bulkSecurityAdvisory.js`).
- WebRTC → TCP shoutbox inner body is UTF-8 `P2P_CHAT_MESSAGE` (legacy JSON envelopes unpacked). Registry encoding `utf8-text`.
- Identity cluster HTTP ingest + package exports; device-link re-exports http thin-client Origin helpers.
- IdentityCrossSign / verify re-export `@fabric/core` (commit/push core before Hub CI, or `npm link @fabric/core`).
Expand All @@ -24,9 +24,9 @@ Living queue for this repo. Detail and closed items live in [SECURITY.md](../SEC
- Managed regtest attach-on-lock: cookie RPC probe + one spawn-failure retry; do not SIGKILL an attached orphan (`functions/bitcoinManagedAttach.js`). Heap OOM that orphaned Core remains a follow-up (teardown cannot run after V8 abort).
- Device-link per-origin create quota lives in `@fabric/http` `fabricDeviceLinkHttp` (Hub re-exports `MAX_SESSIONS_PER_ORIGIN` / `evictDeviceLinkOriginOverflow`).
- Expired `GET /sessions/:delegationToken` requires matching Bearer (http pin).
- Beacon ready-round retry tests use a real Schnorr witness (core `1fc616492` verifies recovered rounds; fake `'00'` now correctly errors).
- Beacon ready-round retry tests use a real Schnorr witness (core `9f2eb9453` verifies recovered rounds; fake `'00'` now correctly errors).
- Identity cluster keys are x-only / compressed hex only (no colon-smashed fallback).
- Http pin `852520a` (`pubkey@` strip + dedicated-NIC `:7778`→`:7777` in `canonicalizeFabricPeerDial`; `--wallet -p` is not a path).
- Core pin `9f2eb9453` (UTF-8 TUI shoutbox `fabricChatText`, IPv6 `_connect` bracket strip). Http pin `cbdfa858` (Internal-log + commit snapshot cut, `fabricChatNormalize` re-exports core `fabricChatText`, `pubkey@` strip + dedicated-NIC `:7778`→`:7777`). WebRTC shoutbox `chatTextOf` uses core `fabricChatText`.

## PRs
[#15](https://github.com/FabricLabs/hub.fabric.pub/pull/15) — only human inline comment was Terrible URI (fixed). Most June/July CodeRabbit “quick wins” are already in tree (`waitForHub` request timeout, wallet-cache `maxCacheAgeMs`, crowdfund BIP44 account, document upload race / `response.ok`, chrome.storage watch-only, `masterXpub` label, explorer admin token, UI flag normalize, payment test route opt-in, `verifyAdminToken` cap/sub, Semantic sync try/catch, prototype-safe `contractId`, pending-overwrite guard). Local `npm run test:unit` after http `852520a`: **644 passing**, 4 pending. PR `build-test` still flakes `Hub document network (multi-hop P2P + tombstone)` `read ECONNRESET` (duplicate job; one green) — do not treat as a product regression. Remaining open: identity import/KDF, login redeem (http), device-link nonce/`sessionId` bind, PR split. Pin `@fabric/core` / `@fabric/http` via lockfile (`#feature/rsi` + `npm run report:install`), currently core **`1fc616492`** / http **`852520a`**. `scripts/hub.js` `~/.fabric` env/wallet fallback waits on unpublished core `fabricHomeEnv` / `fabricWalletIdentity` — leave unstaged until that core cut is pushed.
[#15](https://github.com/FabricLabs/hub.fabric.pub/pull/15) — **merged**. Follow-up on `feature/rsi` is this tree (core `9f2eb9453` + http `cbdfa858` pin, shoutbox, bulk GHSA drop). Most June/July CodeRabbit “quick wins” are already in tree. Local `npm run test:unit` after http `cbdfa858`: **648 passing**, 4 pending. Remaining open: identity import/KDF, login redeem (http), device-link nonce/`sessionId` bind. Pin `@fabric/core` / `@fabric/http` via lockfile (`#feature/rsi` + `npm run report:install`), currently core **`9f2eb9453`** / http **`cbdfa858`**. `scripts/hub.js` `~/.fabric` env/wallet fallback waits on unpublished core `fabricHomeEnv` / `fabricWalletIdentity` — leave unstaged until that core cut is pushed.
2 changes: 1 addition & 1 deletion docs/PRODUCTION_MARCH.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Hub-specific security and deploy queue: **[OUTSTANDING.md](OUTSTANDING.md)**. Op

The type-tree / docs-clutter march below is **inherited from `@fabric/core`** (keep Hub’s public surface on Peer, documents, contracts, Security). Do not expand Hub RC with new payment rails while those leftovers are open.

**This deploy (2026-08-14):** pins core `1fc616492` + http `852520a`; Test workflow `.nvmrc` path; leftover bitcoinClient admin-token leak on payments URLs; `verifyAdminToken` cap/sub; backup KDF bounds. **Next Hub security slice:** identity import / at-rest KDF (heavy lift). **Suite blocker:** http login/link possession proof.
**This deploy (2026-08-14):** pins core `9f2eb9453` + http `cbdfa858`; Test workflow `.nvmrc` path; leftover bitcoinClient admin-token leak on payments URLs; `verifyAdminToken` cap/sub; backup KDF bounds. **Next Hub security slice:** identity import / at-rest KDF (heavy lift). **Suite blocker:** http login/link possession proof.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

---

Expand Down
45 changes: 45 additions & 0 deletions functions/bulkSecurityAdvisory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use strict';

/**
* Detect OpenSSF / GHSA bulk malware advisories (e.g. `@zalastax/nolb-*`).
* Those dumps were ingested as Fabric documents and Internal messages until Hub OOM.
* @param {*} input metadata, JSON object, UTF-8 string, or Buffer
* @returns {boolean}
*/
function looksLikeBulkSecurityAdvisory (input) {
if (input == null) return false;
if (Buffer.isBuffer(input)) {
const n = Math.min(input.length, 8192);
return looksLikeBulkSecurityAdvisory(input.slice(0, n).toString('utf8'));
}
if (typeof input === 'string') {
const s = input.length > 16384 ? input.slice(0, 16384) : input;
if (/@zalastax\/nolb-/i.test(s)) return true;
if (/malicious code in @/i.test(s)) return true;
if (/"security_advisory"\s*:/.test(s) && (
/GHSA-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}/i.test(s) ||
/"type"\s*:\s*"malware"/i.test(s)
)) return true;
const trimmed = s.trim();
if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
try {
return looksLikeBulkSecurityAdvisory(JSON.parse(trimmed));
} catch (_) {
return false;
}
}
return false;
}
if (typeof input !== 'object') return false;
if (input.security_advisory && typeof input.security_advisory === 'object') return true;
const summary = String(input.summary || input.title || input.name || '');
if (input.ghsa_id && /malicious code in @/i.test(summary)) return true;
if (/@zalastax\/nolb-/i.test(summary) || /malicious code in @/i.test(summary)) return true;
const nested = input.object || input.content || input.advisory || input.payload;
if (nested && nested !== input && looksLikeBulkSecurityAdvisory(nested)) return true;
return false;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

module.exports = {
looksLikeBulkSecurityAdvisory
};
2 changes: 1 addition & 1 deletion functions/fabricWebRtcP2pRelay.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

const Message = require('@fabric/core/types/message');
const { HEADER_SIZE, MAGIC_BYTES } = require('@fabric/core/constants');
const { chatTextOf } = require('@fabric/http/functions/fabricChatNormalize');
const { chatTextOf } = require('@fabric/core/functions/fabricChatText');

/** Inner types that are not first-class outer opcodes — carry as GENERIC_MESSAGE JSON. */
const GENERIC_CARRIER_TYPES = new Set([
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion reports/install.log
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
$ npm i --allow-git=all
npm warn Unknown env config "devdir". This will error in a future major version of npm. See `npm help npmrc` for supported config options.
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated rimraf@2.6.3: Rimraf versions prior to v4 are no longer supported
npm warn deprecated rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported
Expand All @@ -8,7 +9,7 @@ npm warn deprecated boolean@3.2.0: Package no longer supported. Contact Support
npm warn deprecated crypto-js@4.2.0: Active development of CryptoJS has been discontinued. This library is no longer maintained.
npm warn deprecated glob@10.5.0: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me

added 1341 packages, and audited 1342 packages in 1m
added 1341 packages, and audited 1342 packages in 60s

211 packages are looking for funding
run `npm fund` for details
Expand Down
Loading
Loading