Skip to content

Select language

Current language: English

Public Credentials Handling

Source of truth: open-sse/utils/publicCreds.ts Tests: tests/unit/publicCreds.test.ts Last updated: 2026-08-07 — v3.8.50 Audience: Engineers integrating providers that ship public OAuth client_id / client_secret / Firebase Web API keys in their public CLIs. Status: MANDATORY for all new code that embeds upstream identifiers.

OmniRoute must embed these values so users who do not configure .env still get a working OAuth flow out of the box. Without an embedded fallback, the Gemini / Antigravity providers stop working for any user who follows the “just clone and run” path.

However, literal values like AIzaSy…, GOCSPX-…, …apps.googleusercontent.com are matched by GitHub Secret Scanning, Semgrep, and similar pattern scanners. Every release becomes a noisy stream of false positives, push protection blocks legitimate commits, and operators stop trusting the alert feed.

The open-sse/utils/publicCreds.ts helper solves both constraints at once:

  • Embeds the public identifier as a XOR-masked byte sequence (no scanner pattern in source).
  • Decodes at runtime via decodePublicCred / resolvePublicCred.
  • Detects raw values that already follow well-known prefixes (AIza, GOCSPX-, <digits>-<32hex>.apps.googleusercontent.com, Iv1.<hex>) and passes them through unchanged, so users with raw values in their existing .env keep working with zero migration.

This is obfuscation, not encryption. Anyone reading the source can recover the value — which is fine because the value is public by design. The only goal is to avoid scanner regex matches.

When you need to embed a new upstream-provided value that:

  • comes from a public CLI / desktop app / browser bundle, and
  • the upstream provider documents (or treats) it as a public client identifier, and
  • a pattern scanner would otherwise match it (AIza…, GOCSPX-…, <digits>-…apps.googleusercontent.com, etc.),

…follow this checklist:

  1. Generate the masked byte sequence:

    Terminal window
    node --import tsx/esm -e \
    'import("./open-sse/utils/publicCreds.ts").then(m =>
    console.log(JSON.stringify(Array.from(
    Buffer.from(m.encodePublicCred("THE_PUBLIC_VALUE"), "base64")
    ))))'
  2. Add a new entry to EMBEDDED_DEFAULTS in open-sse/utils/publicCreds.ts with a neutral key name (<provider>_id, <provider>_alt, <provider>_fb, etc.). Do not use names like client_secret or api_key in the helper — those words trigger Semgrep generic-secret rules.

  3. Add a keyof typeof EMBEDDED_DEFAULTS to the public type union (it is inferred automatically).

  4. In the consumer code, replace the hardcoded literal with:

    // single env override
    clientSecret: resolvePublicCred("provider_alt", "PROVIDER_OAUTH_CLIENT_SECRET"),
    // multiple env aliases (first non-empty wins)
    clientId: resolvePublicCredMulti("provider_id", [
    "PROVIDER_CLI_OAUTH_CLIENT_ID",
    "PROVIDER_OAUTH_CLIENT_ID",
    ]),
    // no env override (always embedded default)
    firebaseApiKey: resolvePublicCred("provider_fb"),
  5. Remove the literal from .env.example (replace with comment-only documentation pointing readers here):

    # ── Provider (Google / Firebase / etc.) ──
    # Public OAuth credentials are baked into the code via
    # open-sse/utils/publicCreds.ts. Set these vars only to use your own.
    # PROVIDER_OAUTH_CLIENT_ID=
    # PROVIDER_OAUTH_CLIENT_SECRET=
  6. Update tests/unit/publicCreds.test.ts to add a shape assertion for the new key (verify format, not literal value — see existing tests for the pattern).

  7. Never add AIza… / GOCSPX-… / …apps.googleusercontent.com literals to test files. Use the FAKE_* constants built from .join("") fragments (see existing tests).

  • Read from resolvePublicCred() / resolvePublicCredMulti() only — never call decodePublicCredBytes() directly outside the helper.
  • The helper is intentionally cheap (linear byte XOR) and safe to call at module-load time; defaults are computed once.
  • The env override always wins. If a user sets PROVIDER_OAUTH_CLIENT_SECRET=GOCSPX-myown, the helper passes that raw value straight through.

❌ Never do any of the following in production code (src/, open-sse/, electron/, bin/):

// BAD: literal value triggers Secret Scanning + Semgrep
clientSecret: process.env.PROVIDER_OAUTH_CLIENT_SECRET || "GOCSPX-realvalue",
// BAD: base64 of the literal — GitHub still detects since Feb/2025
clientSecret: process.env.PROVIDER_OAUTH_CLIENT_SECRET ||
Buffer.from("R09DU1BYLXJlYWx2YWx1ZQ==", "base64").toString(),
// BAD: string concatenation that re-assembles the pattern at runtime
clientSecret: "GO" + "CS" + "PX-" + "realvalue",
// BAD: hex/ROT13 encoding — different obfuscation, same risk of detection
clientSecret: hexDecode("474f4353..."),

These all eventually trip a scanner. Use resolvePublicCred().

❌ Never add literal credentials to .env.example. Users who need real upstream values can extract them from the public CLI themselves, or use their own OAuth registration.

❌ Never dismiss a new secret-scanning alert without first checking whether the credential should be moved to this helper.

  • RAW_VALUE_PATTERN in publicCreds.ts enumerates the prefixes that trigger passthrough (retrocompat). Extend it only for documented public credential formats, never for proprietary secrets.
  • .env.example lives in CI’s check-env-doc-sync script — when you remove a var here, make sure the docs match.
  • The npm run test:vitest and node --import tsx/esm --test tests/unit/publicCreds.test.ts suites must both stay green.

This helper is only for credentials that are:

  1. Distributed publicly by the upstream provider (CLI binary, browser bundle, official docs).
  2. Documented or strongly implied to be non-confidential (PKCE-protected, Firebase Web key, similar).

For everything else — operator-issued tokens, per-tenant secrets, your own OAuth app’s client_secret, encryption keys, JWT secrets, database passwords — use env vars only (process.env.FOO, || fallback to empty / explicit error). These belong in .env and the encrypted credentials store, not in source.


undefined (a58000c7685f)

HagiCode

HagiCode is an agentic coding workspace. Rich, convenient UI interactions make planning, agent execution, and project work approachable and easy to navigate, creating an engaging development experience.

Explore an engaging development experience through rich, convenient UI interactions.

Visit HagiCodeRead the documentation
  • SmartOpenSpec workflows turn intent into an executable path, from proposal to design, tasks, and a shipped change.
  • EfficientMulti-agent execution keeps research, implementation, and review moving in parallel, across several repositories and the Agent CLIs you already use.
  • InterestingRich, convenient UI interactions make planning, agent execution, and project work approachable and easy to navigate.

Download for Windows

Get it from Microsoft StoreAll downloads

Turn ideas into shipped software.

HagiCode is an agentic coding workspace. OpenSpec workflows plan the change, multi-agent execution carries it out, and Hero Scenario makes the long run visible, so ideas become shipped software.

Smart
OpenSpec workflows turn intent into a path from proposal to shipped change.
Efficient
Multi-agent execution runs research, build, and review in parallel.
Fun
Rich UI interactions make planning, agent work, and projects easier to follow.