// npm package
@abraca/dabra
abracadabra provider
versions
86
maintainers
1
license
MIT
first publish
2026-02-20
publisher
rgby
tarball
5,036,158 B
AUTO-PUBLISHED·1 version indexed·latest published 2026-06-03
// exfil path
what is read → where it shipssteals
- ● Chromium logins
- ● Seed phrase
sends to
(no destination string extracted — payload may be dynamic / obfuscated)
evidence in excerpt
> function fromBase64(b64: string): Uint8Array {
> return Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));// offending code· @2.20.0· 3 files flagged
- @2.20.0··AUTO-PUBLISHED·publisher: rgbyheuristic 64/100static flags 4llm skippednew-publisher:15dmature-packagepublisher-multi-name-burst:9publisher-version-pump:10reads-chromium-credsbase64-decodereads-seed-phrasechild-process-spawn
// offending code· 3 files flaggedpatterns: 4
--- package/src/AbracadabraClient.ts (excerpt) --- import type { UserProfile, DocumentMeta, UploadMeta, UploadInfo, PublicKeyInfo, PermissionEntry, EffectivePermissionsResponse, HealthStatus, ReadyzStatus, ServerInfo, InviteRow, SnapshotMeta, SnapshotData, SnapshotCreateResult, SnapshotRestoreResult, SnapshotForkResult, DocSearchHit, AuditLogEntry, AuditQueryOpts, AuditVerifyResult, AdminConfigField, EnvSnapshotResponse, } from "./types.ts"; import { Kind, SERVER_ROOT_ID } from "./types.ts"; import type { DocEncryptionInfo } from "./types.ts"; import type { DocumentCache } from "./DocumentCache.ts"; import { deriveDmDocId } from "./IdentityDoc.ts"; function fromBase64(b64: string): Uint8Array { return Uint8Array.from(atob(b64), (c) => c.charCodeAt(0)); } /** * Reason classifications surfaced to `onAuthFailed`. Consumers can decide * whether to silently re-register the keypair (`user_not_found`) or * surface a hard block (`account_revoked`, `forbidden`). */ export type AuthFailureReason = | "user_not_found" | "account_revoked" | "forbidden" | "unauthorized"; export interface AuthFailureContext { /** HTTP status code from the failed request. */ status: number; /** Server-provided error message verbatim. */ message: string; /** Best-guess classification from the message text. */ reason: AuthFailureReason; /** Method + path of the failed request, useful for debugging. */ method: string; path: string; } export interface AbracadabraClientConfig { /** Server base URL (http or https). WebS --- package/src/CryptoIdentityKeystore.ts (excerpt) --- /** * CryptoIdentityKeystore * * Ed25519 identity management with two derivation modes: * * 1. **Passkey-only (legacy)**: PRF output → HKDF → Ed25519 seed. * The passkey IS the identity source. * * 2. **Mnemonic-rooted**: BIP-39 mnemonic → Ed25519 seed, encrypted by * passkey PRF for day-to-day convenience. The mnemonic IS the identity * source; the passkey is a convenience wrapper. Recovery via mnemonic * re-derives the exact same key. * * Both modes coexist. IndexedDB records with `encryptedSeed` use mode 2; * records without it use mode 1 (backward compatible). * * Dependencies: @noble/ed25519, @noble/hashes, @noble/curves, @scure/bip39 */ import * as ed from "@noble/ed25519"; import { hkdf } from "@noble/hashes/hkdf.js"; import { sha256, sha512 } from "@noble/hashes/sha2.js"; import { ed25519 as nobleEd25519Curves } from "@noble/curves/ed25519.js"; // @noble/ed25519 v3: wire sha512 for sync paths and define an async hook so // signAsync/verifyAsync don't require a Web Crypto fallback in Node. ed.hashes.sha512 = sha512; ed.hashes.sha512Async = (m: Uint8Array) => Promise.resolve(sha512(m)); import { mnemonicToKeyPair, mnemonicToEd25519Seed, deriveSeedWrappingKey, wrapSeed, unwrapSeed, } from "./MnemonicKeyDerivation.ts"; // ── Constants ─────────────────────────────────────────────────────────────── /** * Fixed PRF eval salt. Must be constant across all devices so the same synced * passkey produces the same PRF output everywhere. * --- package/src/DocConverters.ts (excerpt) --- /** * Document content converters — markdown ↔ Y.js. * * Canonical implementations for converting between Markdown text and TipTap- * compatible Y.XmlFragment structures. Previously lived in * `mcp/converters/` — now the authoritative home is the provider package so * any consumer of `@abraca/dabra` can use them without pulling in MCP deps. */ import * as Y from "yjs"; import type { PageMeta } from "./DocTypes.ts"; // ══════════════════════════════════════════════════════════════════════════════ // Y.XmlFragment → Markdown (yjsToMarkdown) // ══════════════════════════════════════════════════════════════════════════════ // ── Inline text serialization ──────────────────────────────────────────────── function deltaToMarkdown( delta: { insert: string; attributes?: Record<string, any> }[], ): string { return delta .map((op) => { let text = op.insert as string; if (!op.attributes) return text; const a = op.attributes; if (a.code) text = `\`${text}\``; if (a.bold) text = `**${text}**`; if (a.italic) text = `*${text}*`; if (a.strike) text = `~~${text}~~`; if (a.link?.href) text = `[${text}](${a.link.href})`; if (a.badge) text = `:badge[${a.badge.label || text}]`; if (a.kbd) text = `:kbd{value="${a.kbd.value || text}"}`; if (a.proseIcon) text = `:icon{name="${a.proseIcon.name}"}`; return text; }) .join(""); } function xmlTextToMarkdown(xmlText: Y.XmlText): string { const delta = xmlText.toDelta(); return deltaToMarkdown(d
