Download Latest Version v0.51.0.0 source code.zip (25.6 MB) Google Add to Preferred Sources
Home / v0.50.5.0
Name Modified Size InfoDownloads / Week
Parent folder
gbrain-darwin-arm64 2026-09-16 145.6 MB
gbrain-linux-x64 2026-09-16 183.7 MB
README.md 2026-09-16 12.9 kB
v0.50.5.0 source code.tar.gz 2026-09-16 21.9 MB
v0.50.5.0 source code.zip 2026-09-16 25.1 MB
Totals: 5 Items   376.2 MB 1

Security hardening pass across the remote OAuth surface, transcript ingest, and environment handling. This wave closes the critical- and high-severity items from privately reported advisories. Fresh installs and existing brains are on the same footing after upgrade; where an operator kept a security-relevant setting in a project directory's .env, gbrain now says so and names the fix. Thanks to the reporters credited below.

Fixed

  • Self-registered OAuth clients are held to read/write. With --enable-dcr, a self-registered client that requests a privileged scope (admin, sources_admin, users_admin, agent) is now rejected at registration with HTTP 400 invalid_client_metadata and told to use the operator path instead; machine clients registered under --enable-dcr-insecure are read-only. Every self-registered authorization-code connection still stops at the admin dashboard for the owner's approval before a token is issued, and a single client can no longer hold more than a small number of consent requests awaiting a decision. The consent gate is pinned end to end against a real gbrain serve --http --enable-dcr process. Widen a client afterward with gbrain auth rescope-client <client_id> --scopes …, or pre-register it with gbrain auth register-client / the admin API. A client_credentials registration without --enable-dcr-insecure is told the grant is not available, rather than being quoted a read-only ceiling. While self-registration is enabled, OAuth discovery advertises exactly the scopes a self-registering client may request, so a connector that copies scopes_supported into its registration succeeds; operator-registered clients keep their full grant. Reported by @amansk, @rohanprichard, @DanielSiva and @benmiller-SC.
  • Remote sources_remove is confined to the caller's granted sources, matching sources_list / sources_status; an out-of-scope id answers not_found. The local CLI is unchanged; the confinement is one shared helper for sources_remove and sources_status.
  • gbrain doctor flags privileged self-registered clients. oauth_client_scope_health warns about active OAuth clients that hold a scope beyond the self-registration ceiling without an operator grant record, and prints the exact rescope-client / revoke-client fix; if the grant audit schema is absent it says so instead of guessing. The privileged set is derived from the scope registry, so a future scope is audited automatically.
  • Transcript ingest redacts credentials by wire format, not just vendor prefix. The shared secret scanner now detects JWTs, cloud and API key shapes, Bearer headers, connection strings carrying inline passwords, and high-entropy KEY=/TOKEN=/PASSWORD= assignments, and redacts them from message bodies, speaker labels, titles and session metadata before anything is written by gbrain transcripts ingest. Preview with --dry-run. The scanner is linear on long lines — a minified or bundled line of hundreds of KB (a JSON blob of credential-less database URLs, thousands of Bearer headers) scans in milliseconds instead of seconds, so a pasted bundle cannot stall transcript ingest, gbrain sources push, or compiled-context scanning; connection-string detection no longer mistakes a credential-less URL followed by an email address for a password, finding previews redact every secret on the line, and a token that is also a connection-string password is redacted as the full credential span. Connection-string passwords pasted with unescaped /, braces, angle brackets, pipes, carets, backticks or backslashes are redacted, an all-caps BEARER header is recognized, and every detector does constant work per occurrence: JWT, high-entropy-assignment and PEM-block matching are bounded (a PEM body over 16 KB falls back to the header-only match), and corpus redaction rebuilds the text from the claimed spans in a single pass — a 1 MB transcript with thousands of distinct secrets redacts in about the time it takes to scan, and it redacts exactly the spans the scanner reports so the redacted corpus and the push-gate findings can no longer disagree. Overlapping detector matches redact the union of what every pattern matched, so a credential whose neighbouring text happens to look like a vendor identifier is never partially exposed in the page or the finding preview. A bearer token or pasted assignment value is also redacted where the same value recurs bare or embedded anywhere else in the session — across messages, speaker labels, titles and metadata, in either order — bounded (first 64 distinct values per session, values up to 512 characters, streaming so memory stays flat) so hostile page content cannot make redaction slow or memory-hungry. The private-key scanner stays linear on very large single-line inputs. Re-run gbrain transcripts ingest to re-render already-imported sessions. Reported by @Jack82-ai.
  • Raw session metadata follows its page's soft delete. get_raw_data no longer returns rows for a soft-deleted page, and the compiled-context sensitivity scan reports a JWT or bearer token once instead of twice. A repeat transcript import no longer rewrites unchanged session metadata on every run.
  • Security-relevant environment variables are ignored from a project directory's .env. A fixed set of GBRAIN_* variables — the ones that load code, name programs to run, relocate ~/.gbrain, or widen a security posture — are no longer honored when a .env file in the current working directory assigns them; gbrain prints one stderr line naming the variable and where to put it instead. The check runs in compiled binaries and in every gbrain process (hooks, serve, mcp, workers). ~/.gbrain/.env is loaded before the guardrails loader so it is a working home for GBRAIN_GUARDRAILS_MODULE (see Changed for the accepted spec shapes). The quarantine parses .env files with the same line grammar Bun uses (a bare carriage return terminates a line; a BOM or U+2028 cannot hide an assignment), also covers the loader / git / node / proxy / AI-CLI variable families a checkout could plant for the programs gbrain spawns, and re-runs gbrain once with the sanitized environment so git, the agent CLI and workers inherit the clean view. Running gbrain from inside ~/.gbrain no longer warns about its own .env; the shell-job opt-in also reaches --job-isolation process children as --allow-shell-jobs. The quarantine re-runs gbrain from an empty temporary directory so the dropped variables are absent (not empty) for every program gbrain spawns, ignores a planted re-run marker, protects the XDG config roots, TLS trust stores, OpenSSL configuration loaders, temp-directory and HOME roots, editor/pager and every provider-endpoint variable, and lets Ctrl-C reach the running command exactly once. GBRAIN_DATABASE_URL and GBRAIN_OAUTH_RELAY_URL join the protected set: a project's .env can no longer choose which brain gbrain writes to or which relay hands back tokens — export them from your shell or put them in ~/.gbrain/.env. Guardrails fail closed at this boundary too: when a project .env assigns GBRAIN_GUARDRAILS_MODULE and a value was dropped, gbrain refuses to start rather than run without the configured firewall. The quarantine also covers the shell-startup and interpreter-home family (BASH_ENV, SHELLOPTS/PS4, ZDOTDIR, PYTHONHOME, GCONV_PATH, BASH_FUNC_*, …); running gbrain from inside its own config directory keeps its exemption only when the project .env assigns none of GBRAIN_HOME, HOME, USERPROFILE; and the sanitized re-run always exits with the child's status, forwards Ctrl-C only when no controlling terminal exists, hands the child your real HOME when a planted one was dropped, exits within a second when its wrapper is force-killed (supervisor restarts no longer leave an orphaned worker), and keeps relative runtime paths (bun --preload ./x src/cli.ts, --env-file .env.ci, …) working across the hop. Reported by @dberzan.
  • A project directory's bunfig.toml can no longer preload code into the compiled gbrain binary. Every bun build --compile invocation (release workflow, bun run build, CI door builds, docs) now passes --no-compile-autoload-bunfig, and a CI guard keeps every build invocation flagged. Script-mode installs (bun install -g, bun link) run gbrain as an ordinary Bun script, which applies the current directory's bunfig.toml before gbrain starts; gbrain now prints a one-line warning when it finds a top-level preload there (see SECURITY.md).
  • Source removal over MCP keys on the caller's write authority. A federated read grant no longer lets a sources_admin client hard-remove a sibling source; out-of-authority ids answer not_found as before, sources_status is unchanged, and the local CLI keeps full operator authority.
  • gbrain delete <slug> --purge no longer reports success while the page's markdown file is still on disk. An already-soft-deleted page gets its file removal retried against the recorded path, and a removal failure stops with storage_error naming the file so you can fix it and re-run; the row stays soft-deleted until the file is gone.

Added

  • gbrain delete <slug> --purge removes a page — row, chunks, links, and raw session metadata — immediately with no recovery window. Local CLI only; agents connected over MCP get permission_denied for purge and keep the recoverable soft delete, and a purge response always reports its file write-through outcome plus the copies a purge cannot reach (brain-repo history, exports, derived rows) so a credential remediation never stops at the row. The soft-delete response points at it.
  • gbrain jobs work --allow-shell-jobs — the shell-handler opt-in is now also a flag; the supervisor passes it to workers automatically so the cwd-.env quarantine cannot silently disable it.

Changed

  • GBRAIN_GUARDRAILS_MODULE accepts only an absolute path or a ~/ path. cwd-relative specs (./x, ../x) and bare package names are refused because both resolve against whatever directory gbrain happens to run in (a package name loads the current directory's node_modules/<name>/); a refused spec is a fail-closed exit 1 with the fix in the message. This also applies to the published gbrain/core/guardrails library export.
  • Connection strings with inline passwords now count as secrets for gbrain sources push / bootstrap verify and are dropped from compiled-context entries; declare a confirmed non-secret value safe with its fingerprint in .gbrain-scan-allow. The high-entropy assignment rule now requires a digit in the value, so identifier-shaped assignments in code stop being redacted.
  • Startup banner and warning text plus docs/mcp/DEPLOY.md, docs/mcp/CHATGPT.md, SECURITY.md and docs/guardrails.md describe the registration ceiling, the owner-approval step, the widen path, and the cwd-.env trust boundary.

To take advantage of v0.50.5.0

gbrain upgrade, then restart gbrain serve --http and run gbrain doctor. If it lists self-registered OAuth clients with a privileged scope you did not intend, run gbrain auth rescope-client <client_id> --scopes read,write or gbrain auth revoke-client <client_id>. Connectors that request admin at self-registration will now fail to register — pre-register them with gbrain auth register-client <name> --scopes … or let them self-register with read write and rescope later. If you kept GBRAIN_GUARDRAILS_MODULE, GBRAIN_HOME, a GBRAIN_ALLOW_* flag or another protected variable in a project's .env, move it to ~/.gbrain/.env (or your service's EnvironmentFile / shell profile) — gbrain names the variable it ignored and where to put it. A hand-started worker that runs shell jobs should use gbrain jobs work --allow-shell-jobs. If GBRAIN_GUARDRAILS_MODULE is a package name or a relative path, change it to the module's absolute path (or a ~/ path) — gbrain exits 1 until you do. If you set GBRAIN_DATABASE_URL in a project's .env on purpose, export it from your shell or put it in ~/.gbrain/.env instead. If you build the binary yourself, rebuild it with bun run build (Say to your agent: "rebuild the gbrain binary") so it carries the new compile flag.

Say to your agent: "archive my session transcripts" / "import my conversations""a secret leaked into a brain page — rotate it and purge the page" (your agent rotates the credential, then runs gbrain delete <slug> --purge on the host) — "run a brain health check" (your agent runs gbrain doctor and follows any oauth_client_scope_health advice) — "start my brain's MCP server with self-service client registration" (your agent runs gbrain serve --http --enable-dcr; you approve each new connection in the admin UI).

Source: README.md, updated 2026-09-16