Theo Docs
TheoKitTheoKit-SDKTheoUITheo PaaS
Concepts

Security

Secret redaction at output boundaries, path traversal defense, TOCTOU primitives.

Canonical contract: packages/sdk/docs.md — "Security — secret redaction" + "Security — path traversal + TOCTOU".

The SDK takes two security concerns seriously: secrets in observable output and filesystem operations on untrusted input.

Secret redaction (ADR D68-D73)

Every output boundary (logs, telemetry attrs, error metadata, transcripts) is wrapped by redactSecrets. The canonical implementation lives at internal/security/redact.ts — there's one source of truth.

What gets redacted:

  • API key patterns (sk-..., Bearer ey..., xoxb-...)
  • AWS access keys (AKIA[0-9A-Z]{16})
  • GitHub tokens (ghp_..., gho_...)
  • JWT-like tokens (3-part base64url)
  • URL ?token= / ?api_key= query params
  • Environment-variable values when stringified

Two-bucket masking (ADR D71):

  • Short tokens (less than 18 chars) → ***
  • Long tokens → prefix...suffix (first 4 + last 4)

Opt-out (NOT recommended):

export THEOKIT_REDACT_SECRETS=0

Emits a one-time stderr warning (ADR D70). The env var is snapshotted at module init (ADR D69) — prompt-injection defense.

codeFile: true flag (ADR D72):

When generating .env.example placeholders or similar, set codeFile: true to skip PARAM_PATTERN redaction — preserves intentional examples like OPENAI_API_KEY=sk-....

Path traversal + TOCTOU (ADRs D79-D85)

When the SDK writes to user-supplied paths (skills, agents, personalities, OAuth tokens), it routes through path-safety primitives:

PrimitiveUse
safePathJoin(base, ...parts)Resolves THEN prefix-checks (defeats normalized .. escape)
sanitizeIdentifier(name)Strict grammar ^[a-z0-9][a-z0-9_-]*$
createExclusive(path, mode)O_EXCL open with default mode 0o600
casUpdate(db, stmt, params)SQLite optimistic compare-and-swap

Available as Security.* namespace and at @theokit/sdk/path-safety sub-export (separate from main barrel to keep DTS bundle clean).

import { Security } from "@theokit/sdk";

const safe = Security.safePathJoin(".theokit/skills", userProvidedName);

CI lint gate (ADR D85)

packages/sdk/tests/lint/no-unredacted-sink.test.ts runs in CI and fails if a new console.log/writeFile/span.setAttribute lands in src/ without going through redactSecrets. Each whitelisted file carries a rationale comment.

packages/sdk/tests/lint/no-todo-fixme.test.ts prevents production stubs.

API reference

On this page